Merge JDK-8200758-branch
authorherrick
Fri, 03 May 2019 14:59:32 -0400
branchJDK-8200758-branch
changeset 57350 bf3d37105ef9
parent 57349 c6cd128bf0cd (current diff)
parent 54711 297ddf282627 (diff)
child 57352 51709d9aab69
Merge
make/CompileJavaModules.gmk
src/hotspot/os_cpu/linux_x86/gc/z/zAddress_linux_x86.inline.hpp
src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp
src/hotspot/share/gc/cms/cmsCollectorPolicy.hpp
src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp
src/hotspot/share/gc/g1/g1CollectorPolicy.cpp
src/hotspot/share/gc/g1/g1CollectorPolicy.hpp
src/hotspot/share/gc/g1/g1HeterogeneousCollectorPolicy.cpp
src/hotspot/share/gc/g1/g1HeterogeneousCollectorPolicy.hpp
src/hotspot/share/gc/parallel/generationSizer.cpp
src/hotspot/share/gc/parallel/generationSizer.hpp
src/hotspot/share/gc/parallel/heterogeneousGenerationSizer.cpp
src/hotspot/share/gc/parallel/heterogeneousGenerationSizer.hpp
src/hotspot/share/gc/shared/collectorPolicy.cpp
src/hotspot/share/gc/shared/collectorPolicy.hpp
src/hotspot/share/gc/shared/gcArguments.inline.hpp
src/hotspot/share/gc/z/zCollectorPolicy.cpp
src/hotspot/share/gc/z/zCollectorPolicy.hpp
src/hotspot/share/jvmci/systemDictionary_jvmci.hpp
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java
test/jdk/java/lang/String/concat/StringConcatFactoryEmptyMethods.java
test/jdk/java/net/Socket/OldImpl.java
test/jdk/java/net/Socket/OldSocketImpl.java
test/jdk/java/net/Socket/OldSocketImplTestDriver.java
test/jdk/java/nio/channels/SocketChannel/Stream.java
test/jdk/jdk/nio/zipfs/MultiReleaseJarTest.java
test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt
test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt
test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt
test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt
test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt
test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt
test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt
test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt
test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java
--- a/.hgtags	Fri May 03 11:28:14 2019 -0700
+++ b/.hgtags	Fri May 03 14:59:32 2019 -0400
@@ -555,3 +555,5 @@
 f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15
 9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16
 93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17
+bebb82ef3434a25f8142edafec20165f07ac562d jdk-13+18
+a43d6467317d8f1e160f67aadec37919c9d64443 jdk-13+19
--- a/doc/building.html	Fri May 03 11:28:14 2019 -0700
+++ b/doc/building.html	Fri May 03 14:59:32 2019 -0400
@@ -369,7 +369,7 @@
 $ CC -V
 CC: Sun C++ 5.13 SunOS_i386 151846-10 2015/10/30</code></pre>
 <h3 id="microsoft-visual-studio">Microsoft Visual Studio</h3>
-<p>The minimum accepted version of Visual Studio is 2010. Older versions will not be accepted by <code>configure</code>. The maximum accepted version of Visual Studio is 2017. Versions older than 2017 are unlikely to continue working for long.</p>
+<p>The minimum accepted version of Visual Studio is 2010. Older versions will not be accepted by <code>configure</code>. The maximum accepted version of Visual Studio is 2019. Versions older than 2017 are unlikely to continue working for long.</p>
 <p>If you have multiple versions of Visual Studio installed, <code>configure</code> will by default pick the latest. You can request a specific version to be used by setting <code>--with-toolchain-version</code>, e.g. <code>--with-toolchain-version=2015</code>.</p>
 <p>If you get <code>LINK: fatal error LNK1123: failure during conversion to COFF: file invalid</code> when building using Visual Studio 2010, you have encountered <a href="http://support.microsoft.com/kb/2757355">KB2757355</a>, a bug triggered by a specific installation order. However, the solution suggested by the KB article does not always resolve the problem. See <a href="https://stackoverflow.com/questions/10888391">this stackoverflow discussion</a> for other suggestions.</p>
 <h3 id="ibm-xl-cc">IBM XL C/C++</h3>
--- a/doc/building.md	Fri May 03 11:28:14 2019 -0700
+++ b/doc/building.md	Fri May 03 14:59:32 2019 -0400
@@ -404,7 +404,7 @@
 
 The minimum accepted version of Visual Studio is 2010. Older versions will not
 be accepted by `configure`. The maximum accepted version of Visual Studio is
-2017. Versions older than 2017 are unlikely to continue working for long.
+2019. Versions older than 2017 are unlikely to continue working for long.
 
 If you have multiple versions of Visual Studio installed, `configure` will by
 default pick the latest. You can request a specific version to be used by
--- a/make/CompileJavaModules.gmk	Fri May 03 11:28:14 2019 -0700
+++ b/make/CompileJavaModules.gmk	Fri May 03 14:59:32 2019 -0400
@@ -469,6 +469,7 @@
     org.graalvm.compiler.core.test \
     org.graalvm.compiler.debug.test \
     org.graalvm.compiler.graph.test \
+    org.graalvm.compiler.hotspot.aarch64.test \
     org.graalvm.compiler.hotspot.amd64.test \
     org.graalvm.compiler.hotspot.jdk9.test \
     org.graalvm.compiler.hotspot.lir.test \
--- a/make/autoconf/flags-cflags.m4	Fri May 03 11:28:14 2019 -0700
+++ b/make/autoconf/flags-cflags.m4	Fri May 03 14:59:32 2019 -0400
@@ -219,7 +219,7 @@
           -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual"
       WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
 
-      DISABLED_WARNINGS="unused-parameter unused"
+      DISABLED_WARNINGS="unknown-warning-option unused-parameter unused"
 
       if test "x$OPENJDK_TARGET_OS" = xmacosx; then
         # missing-method-return-type triggers in JavaNativeFoundation framework
@@ -536,6 +536,12 @@
     TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -mno-omit-leaf-frame-pointer -mstack-alignment=16"
 
     if test "x$OPENJDK_TARGET_OS" = xlinux; then
+      if test "x$DEBUG_LEVEL" = xrelease; then
+        # Clang does not inline as much as GCC does for functions with "inline" keyword by default.
+        # This causes noticeable slowdown in pause time for G1, and possibly in other areas.
+        # Increasing the inline hint threshold avoids the slowdown for Clang-built JVM.
+        TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -mllvm -inlinehint-threshold=100000"
+      fi
       TOOLCHAIN_CFLAGS_JDK="-pipe"
       TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX
     fi
--- a/make/autoconf/hotspot.m4	Fri May 03 11:28:14 2019 -0700
+++ b/make/autoconf/hotspot.m4	Fri May 03 14:59:32 2019 -0400
@@ -392,9 +392,8 @@
     JVM_FEATURES_jvmci=""
     INCLUDE_JVMCI="false"
   else
-    # Only enable jvmci on x86_64, sparcv9 and aarch64
+    # Only enable jvmci on x86_64 and aarch64
     if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \
-       test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \
        test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then
       AC_MSG_RESULT([yes])
       JVM_FEATURES_jvmci="jvmci"
--- a/make/autoconf/toolchain_windows.m4	Fri May 03 11:28:14 2019 -0700
+++ b/make/autoconf/toolchain_windows.m4	Fri May 03 14:59:32 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
@@ -25,7 +25,7 @@
 
 ################################################################################
 # The order of these defines the priority by which we try to find them.
-VALID_VS_VERSIONS="2017 2013 2015 2012 2010"
+VALID_VS_VERSIONS="2017 2019 2013 2015 2012 2010"
 
 VS_DESCRIPTION_2010="Microsoft Visual Studio 2010"
 VS_VERSION_INTERNAL_2010=100
@@ -89,6 +89,20 @@
 VS_SUPPORTED_2017=true
 VS_TOOLSET_SUPPORTED_2017=true
 
+VS_DESCRIPTION_2019="Microsoft Visual Studio 2019"
+VS_VERSION_INTERNAL_2019=141
+VS_MSVCR_2019=vcruntime140.dll
+VS_MSVCP_2019=msvcp140.dll
+VS_ENVVAR_2019="VS160COMNTOOLS"
+VS_USE_UCRT_2019="true"
+VS_VS_INSTALLDIR_2019="Microsoft Visual Studio/2019"
+VS_EDITIONS_2019="BuildTools Community Professional Enterprise"
+VS_SDK_INSTALLDIR_2019=
+VS_VS_PLATFORM_NAME_2019="v142"
+VS_SDK_PLATFORM_NAME_2019=
+VS_SUPPORTED_2019=false
+VS_TOOLSET_SUPPORTED_2019=false
+
 ################################################################################
 
 AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT],
@@ -99,7 +113,7 @@
     METHOD="$3"
 
     BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(VS_BASE)
-    # In VS 2017, the default installation is in a subdir named after the edition.
+    # In VS 2017 and VS 2019, the default installation is in a subdir named after the edition.
     # Find the first one present and use that.
     if test "x$VS_EDITIONS" != x; then
       for edition in $VS_EDITIONS; do
@@ -662,7 +676,7 @@
       else
         CYGWIN_VC_TOOLS_REDIST_DIR="$VCToolsRedistDir"
         BASIC_FIXUP_PATH(CYGWIN_VC_TOOLS_REDIST_DIR)
-        # Probe: Using well-known location from VS 2017
+        # Probe: Using well-known location from VS 2017 and VS 2019
         if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
           POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
         else
--- a/make/conf/jib-profiles.js	Fri May 03 11:28:14 2019 -0700
+++ b/make/conf/jib-profiles.js	Fri May 03 14:59:32 2019 -0400
@@ -1283,7 +1283,10 @@
     var version = (feature != null ? feature : version_numbers.get("DEFAULT_VERSION_FEATURE"))
         + "." + (interim != null ? interim : version_numbers.get("DEFAULT_VERSION_INTERIM"))
         + "." + (update != null ? update :  version_numbers.get("DEFAULT_VERSION_UPDATE"))
-        + "." + (patch != null ? patch : version_numbers.get("DEFAULT_VERSION_PATCH"));
+        + "." + (patch != null ? patch : version_numbers.get("DEFAULT_VERSION_PATCH"))
+        + "." + version_numbers.get("DEFAULT_VERSION_EXTRA1")
+        + "." + version_numbers.get("DEFAULT_VERSION_EXTRA2")
+        + "." + version_numbers.get("DEFAULT_VERSION_EXTRA3");
     while (version.match(".*\\.0$")) {
         version = version.substring(0, version.length - 2);
     }
--- a/make/data/lsrdata/language-subtag-registry.txt	Fri May 03 11:28:14 2019 -0700
+++ b/make/data/lsrdata/language-subtag-registry.txt	Fri May 03 14:59:32 2019 -0400
@@ -1,4 +1,4 @@
-File-Date: 2018-11-30
+File-Date: 2019-04-03
 %%
 Type: language
 Subtag: aa
@@ -43008,6 +43008,7 @@
 Description: Lyons Sign Language
 Added: 2009-07-29
 Deprecated: 2018-03-08
+Preferred-Value: lsg
 Prefix: sgn
 %%
 Type: extlang
@@ -43406,6 +43407,7 @@
 Description: Rennellese Sign Language
 Added: 2009-07-29
 Deprecated: 2017-02-23
+Preferred-Value: rsi
 Prefix: sgn
 %%
 Type: extlang
@@ -43760,6 +43762,7 @@
 Description: Yiddish Sign Language
 Added: 2009-07-29
 Deprecated: 2015-02-12
+Preferred-Value: yds
 Prefix: sgn
 %%
 Type: extlang
@@ -46537,16 +46540,16 @@
 Description: Eastern Armenian
 Added: 2006-09-18
 Deprecated: 2018-03-24
-Preferred-Value: hy
 Prefix: hy
+Comments: Preferred tag is hy
 %%
 Type: variant
 Subtag: arevmda
 Description: Western Armenian
 Added: 2006-09-18
 Deprecated: 2018-03-24
-Preferred-Value: hyw
 Prefix: hy
+Comments: Preferred tag is hyw
 %%
 Type: variant
 Subtag: asante
@@ -46642,6 +46645,12 @@
 Comments: Jargon embedded in American English
 %%
 Type: variant
+Subtag: bornholm
+Description: Bornholmsk
+Added: 2019-03-27
+Prefix: da
+%%
+Type: variant
 Subtag: cisaup
 Description: Cisalpine
 Added: 2018-04-22
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/devkit/createWindowsDevkit2019.sh	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,209 @@
+#!/bin/bash
+#
+# 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.
+#
+
+# This script copies parts of a Visual Studio installation into a devkit
+# suitable for building OpenJDK and OracleJDK. Needs to run in Cygwin or WSL.
+# erik.joelsson@oracle.com
+
+VS_VERSION="2019"
+VS_VERSION_NUM_NODOT="160"
+VS_DLL_VERSION="140"
+SDK_VERSION="10"
+SDK_FULL_VERSION="10.0.17763.0"
+MSVC_DIR="Microsoft.VC141.CRT"
+MSVC_FULL_VERSION="14.12.27508"
+REDIST_FULL_VERSION="14.20.27508"
+
+SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
+BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
+
+################################################################################
+# Prepare settings
+
+UNAME_SYSTEM=`uname -s`
+UNAME_RELEASE=`uname -r`
+
+# Detect cygwin or WSL
+IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN`
+IS_WSL=`echo $UNAME_RELEASE | grep Microsoft`
+if test "x$IS_CYGWIN" != "x"; then
+    BUILD_ENV="cygwin"
+elif test "x$IS_WSL" != "x"; then
+    BUILD_ENV="wsl"
+else
+    echo "Unknown environment; only Cygwin and WSL are supported."
+    exit 1
+fi
+
+if test "x$BUILD_ENV" = "xcygwin"; then
+    WINDOWS_PATH_TO_UNIX_PATH="cygpath -u"
+elif test "x$BUILD_ENV" = "xwsl"; then
+    WINDOWS_PATH_TO_UNIX_PATH="wslpath -u"
+fi
+
+# Work around the insanely named ProgramFiles(x86) env variable
+PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")"
+
+# Find Visual Studio installation dir
+VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'`
+if [ -d "$VSNNNCOMNTOOLS" ]; then
+    VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")"
+else
+    VS_INSTALL_DIR="${PROGRAMFILES_X86}/Microsoft Visual Studio/2019"
+    VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)"
+fi
+echo "VS_INSTALL_DIR: $VS_INSTALL_DIR"
+
+# Extract semantic version
+POTENTIAL_INI_FILES="Common7/IDE/wdexpress.isolation.ini Common7/IDE/devenv.isolation.ini"
+for f in $POTENTIAL_INI_FILES; do
+    if [ -f "$VS_INSTALL_DIR/$f" ]; then
+        VS_VERSION_SP="$(grep ^SemanticVersion= "$VS_INSTALL_DIR/$f")"
+        # Remove SemnaticVersion=
+        VS_VERSION_SP="${VS_VERSION_SP#*=}"
+        # Remove suffix of too detailed numbering starting with +
+        VS_VERSION_SP="${VS_VERSION_SP%+*}"
+        break
+    fi
+done
+if [ -z "$VS_VERSION_SP" ]; then
+    echo "Failed to find SP version"
+    exit 1
+fi
+echo "Found Version SP: $VS_VERSION_SP"
+
+# Setup output dirs
+DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit"
+DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz"
+
+echo "Creating devkit in $DEVKIT_ROOT"
+
+MSVCR_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}.dll
+MSVCP_DLL=${MSVC_DIR}/msvcp${VS_DLL_VERSION}.dll
+
+################################################################################
+# Copy Visual Studio files
+
+TOOLS_VERSION="$(ls "$VS_INSTALL_DIR/VC/Tools/MSVC" | sort -r -n | head -n1)"
+echo "Found Tools version: $TOOLS_VERSION"
+VC_SUBDIR="VC/Tools/MSVC/$TOOLS_VERSION"
+REDIST_VERSION="$(ls "$VS_INSTALL_DIR/VC/Redist/MSVC" | sort -r -n | head -n1)"
+echo "Found Redist version: $REDIST_VERSION"
+REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION"
+echo "Copying VC..."
+rm -rf $DEVKIT_ROOT/VC
+mkdir -p $DEVKIT_ROOT/VC/bin
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/
+mkdir -p $DEVKIT_ROOT/VC/lib
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x64" $DEVKIT_ROOT/VC/lib/
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x86" $DEVKIT_ROOT/VC/lib/
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/include" $DEVKIT_ROOT/VC/
+mkdir -p $DEVKIT_ROOT/VC/atlmfc/lib
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x64" $DEVKIT_ROOT/VC/atlmfc/lib/
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x86" $DEVKIT_ROOT/VC/atlmfc/lib/
+cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/include" $DEVKIT_ROOT/VC/atlmfc/
+mkdir -p $DEVKIT_ROOT/VC/Auxiliary
+cp -r "$VS_INSTALL_DIR/VC/Auxiliary/Build" $DEVKIT_ROOT/VC/Auxiliary/
+mkdir -p $DEVKIT_ROOT/VC/redist
+cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x64" $DEVKIT_ROOT/VC/redist/
+cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x86" $DEVKIT_ROOT/VC/redist/
+
+# The redist runtime libs are needed to run the compiler but may not be
+# installed on the machine where the devkit will be used.
+cp $DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x86
+cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x86
+cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x64
+cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x64
+
+################################################################################
+# Copy SDK files
+
+SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION"
+echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR"
+
+SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)"
+echo "Found SDK version: $SDK_FULL_VERSION"
+UCRT_VERSION="$(ls "$SDK_INSTALL_DIR/Redist" | grep $SDK_VERSION | sort -r -n | head -n1)"
+echo "Found UCRT version: $UCRT_VERSION"
+echo "Copying SDK..."
+rm -rf $DEVKIT_ROOT/$SDK_VERSION
+mkdir -p $DEVKIT_ROOT/$SDK_VERSION/bin
+cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x64" $DEVKIT_ROOT/$SDK_VERSION/bin/
+cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x86" $DEVKIT_ROOT/$SDK_VERSION/bin/
+mkdir -p $DEVKIT_ROOT/$SDK_VERSION/lib
+cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/
+cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/
+cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/
+cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/
+mkdir -p $DEVKIT_ROOT/$SDK_VERSION/Redist
+cp -r "$SDK_INSTALL_DIR/Redist/$UCRT_VERSION/ucrt" $DEVKIT_ROOT/$SDK_VERSION/Redist/
+mkdir -p $DEVKIT_ROOT/$SDK_VERSION/include
+cp -r "$SDK_INSTALL_DIR/include/$SDK_FULL_VERSION/"* $DEVKIT_ROOT/$SDK_VERSION/include/
+
+################################################################################
+# Generate devkit.info
+
+echo-info() {
+    echo "$1" >> $DEVKIT_ROOT/devkit.info
+}
+
+echo "Generating devkit.info..."
+rm -f $DEVKIT_ROOT/devkit.info
+echo-info "# This file describes to configure how to interpret the contents of this devkit"
+echo-info "DEVKIT_NAME=\"Microsoft Visual Studio $VS_VERSION $VS_VERSION_SP (devkit)\""
+echo-info "DEVKIT_VS_VERSION=\"$VS_VERSION\""
+echo-info ""
+echo-info "DEVKIT_TOOLCHAIN_PATH_x86=\"\$DEVKIT_ROOT/VC/bin/x86:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\""
+echo-info "DEVKIT_VS_INCLUDE_x86=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\""
+echo-info "DEVKIT_VS_LIB_x86=\"\$DEVKIT_ROOT/VC/lib/x86;\$DEVKIT_ROOT/VC/atlmfc/lib/x86;\$DEVKIT_ROOT/$SDK_VERSION/lib/x86\""
+echo-info "DEVKIT_MSVCR_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL\""
+echo-info "DEVKIT_MSVCP_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL\""
+echo-info "DEVKIT_UCRT_DLL_DIR_x86=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x86\""
+echo-info ""
+echo-info "DEVKIT_TOOLCHAIN_PATH_x86_64=\"\$DEVKIT_ROOT/VC/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\""
+echo-info "DEVKIT_VS_INCLUDE_x86_64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\""
+echo-info "DEVKIT_VS_LIB_x86_64=\"\$DEVKIT_ROOT/VC/lib/x64;\$DEVKIT_ROOT/VC/atlmfc/lib/x64;\$DEVKIT_ROOT/$SDK_VERSION/lib/x64\""
+echo-info "DEVKIT_MSVCR_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL\""
+echo-info "DEVKIT_MSVCP_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL\""
+echo-info "DEVKIT_UCRT_DLL_DIR_x86_64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x64\""
+echo-info ""
+echo-info "DEVKIT_TOOLS_VERSION=\"$TOOLS_VERSION\""
+echo-info "DEVKIT_REDIST_VERSION=\"$REDIST_VERSION\""
+echo-info "DEVKIT_SDK_VERSION=\"$SDK_FULL_VERSION\""
+echo-info "DEVKIT_UCRT_VERSION=\"$UCRT_VERSION\""
+
+################################################################################
+# Copy this script
+
+echo "Copying this script..."
+cp $0 $DEVKIT_ROOT/
+
+################################################################################
+# Create bundle
+
+echo "Creating bundle: $DEVKIT_BUNDLE"
+(cd "$DEVKIT_ROOT" && tar zcf "$DEVKIT_BUNDLE" .)
--- a/make/hotspot/lib/CompileGtest.gmk	Fri May 03 11:28:14 2019 -0700
+++ b/make/hotspot/lib/CompileGtest.gmk	Fri May 03 14:59:32 2019 -0400
@@ -76,7 +76,8 @@
     DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc) \
         undef, \
     DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang) \
-        undef switch format-nonliteral tautological-undefined-compare, \
+        undef switch format-nonliteral tautological-undefined-compare \
+        self-assign-overloaded, \
     DISABLED_WARNINGS_solstudio := $(DISABLED_WARNINGS_solstudio) \
         identexpected, \
     DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft) \
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Fri May 03 11:28:14 2019 -0700
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Fri May 03 14:59:32 2019 -0400
@@ -72,6 +72,8 @@
         String SC     = String.valueOf(args.length) + "string";
         String SCS    = String.valueOf(args.length) + "string" + String.valueOf(args.length);
         String CSS    = "string" + String.valueOf(args.length) + String.valueOf(args.length);
+        String CSC    = "string" + String.valueOf(args.length) + "string";
+        String SSC    = String.valueOf(args.length) + String.valueOf(args.length) + "string";
         String CSCS   = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
         String SCSC   = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
         String CSCSC  = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
--- a/make/lib/Lib-jdk.jdwp.agent.gmk	Fri May 03 11:28:14 2019 -0700
+++ b/make/lib/Lib-jdk.jdwp.agent.gmk	Fri May 03 14:59:32 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
@@ -66,6 +66,7 @@
     LIBS_solaris := $(LIBDL), \
     LIBS_macosx := -liconv, \
     LIBS_aix := -liconv, \
+    LIBS_windows := $(WIN_JAVA_LIB), \
 ))
 
 $(BUILD_LIBJDWP): $(call FindLib, java.base, java)
--- a/make/test/JtregGraalUnit.gmk	Fri May 03 11:28:14 2019 -0700
+++ b/make/test/JtregGraalUnit.gmk	Fri May 03 14:59:32 2019 -0400
@@ -91,6 +91,7 @@
               $(SRC_DIR)/org.graalvm.compiler.core.test/src \
               $(SRC_DIR)/org.graalvm.compiler.debug.test/src \
               $(SRC_DIR)/org.graalvm.compiler.graph.test/src \
+              $(SRC_DIR)/org.graalvm.compiler.hotspot.aarch64.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \
--- a/make/test/JtregNativeHotspot.gmk	Fri May 03 11:28:14 2019 -0700
+++ b/make/test/JtregNativeHotspot.gmk	Fri May 03 14:59:32 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
@@ -736,6 +736,7 @@
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv002 := $(NSK_JVMTI_AGENT_INCLUDES)
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv001 := $(NSK_JVMTI_AGENT_INCLUDES)
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexception001 := $(NSK_JVMTI_AGENT_INCLUDES)
+BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexceptionjni001 := $(NSK_JVMTI_AGENT_INCLUDES)
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresexhausted := $(NSK_JVMTI_AGENT_INCLUDES)
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart001 := $(NSK_JVMTI_AGENT_INCLUDES)
 BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart002 := $(NSK_JVMTI_AGENT_INCLUDES)
@@ -1375,6 +1376,7 @@
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter004 += -lpthread
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter001 += -lpthread
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdealloc001 += -lpthread
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libexceptionjni001 += -lpthread
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin003 += -lpthread
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin002 += -lpthread
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrgrpinfo001 += -lpthread
--- a/src/hotspot/.mx.jvmci/suite.py	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/.mx.jvmci/suite.py	Fri May 03 14:59:32 2019 -0400
@@ -56,6 +56,9 @@
     "jdk.vm.ci.common" : {
       "subDir" : "../jdk.internal.vm.ci/share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.services",
+      ],
       "checkstyle" : "jdk.vm.ci.services",
       "javaCompliance" : "9+",
       "workingSets" : "API,JVMCI",
@@ -258,9 +261,11 @@
       "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
       "dependencies" : [
         "jdk.vm.ci.runtime.test",
+        "jdk.vm.ci.hotspot.test",
       ],
       "distDependencies" : [
         "JVMCI_API",
+        "JVMCI_HOTSPOT",
       ],
       "exclude" : ["mx:JUNIT"],
     },
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Fri May 03 14:59:32 2019 -0400
@@ -11343,14 +11343,11 @@
 instruct sbfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count)
 %{
   match(Set dst (RShiftL (LShiftL src lshift_count) rshift_count));
-  // Make sure we are not going to exceed what sbfm can do.
-  predicate((unsigned int)n->in(2)->get_int() <= 63
-            && (unsigned int)n->in(1)->in(2)->get_int() <= 63);
-
   ins_cost(INSN_COST * 2);
   format %{ "sbfm  $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %}
   ins_encode %{
-    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int lshift = $lshift_count$$constant & 63;
+    int rshift = $rshift_count$$constant & 63;
     int s = 63 - lshift;
     int r = (rshift - lshift) & 63;
     __ sbfm(as_Register($dst$$reg),
@@ -11366,14 +11363,11 @@
 instruct sbfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count)
 %{
   match(Set dst (RShiftI (LShiftI src lshift_count) rshift_count));
-  // Make sure we are not going to exceed what sbfmw can do.
-  predicate((unsigned int)n->in(2)->get_int() <= 31
-            && (unsigned int)n->in(1)->in(2)->get_int() <= 31);
-
   ins_cost(INSN_COST * 2);
   format %{ "sbfmw  $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %}
   ins_encode %{
-    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int lshift = $lshift_count$$constant & 31;
+    int rshift = $rshift_count$$constant & 31;
     int s = 31 - lshift;
     int r = (rshift - lshift) & 31;
     __ sbfmw(as_Register($dst$$reg),
@@ -11389,14 +11383,11 @@
 instruct ubfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count)
 %{
   match(Set dst (URShiftL (LShiftL src lshift_count) rshift_count));
-  // Make sure we are not going to exceed what ubfm can do.
-  predicate((unsigned int)n->in(2)->get_int() <= 63
-            && (unsigned int)n->in(1)->in(2)->get_int() <= 63);
-
   ins_cost(INSN_COST * 2);
   format %{ "ubfm  $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %}
   ins_encode %{
-    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int lshift = $lshift_count$$constant & 63;
+    int rshift = $rshift_count$$constant & 63;
     int s = 63 - lshift;
     int r = (rshift - lshift) & 63;
     __ ubfm(as_Register($dst$$reg),
@@ -11412,14 +11403,11 @@
 instruct ubfmwI(iRegINoSp dst, iRegIorL2I src, immI lshift_count, immI rshift_count)
 %{
   match(Set dst (URShiftI (LShiftI src lshift_count) rshift_count));
-  // Make sure we are not going to exceed what ubfmw can do.
-  predicate((unsigned int)n->in(2)->get_int() <= 31
-            && (unsigned int)n->in(1)->in(2)->get_int() <= 31);
-
   ins_cost(INSN_COST * 2);
   format %{ "ubfmw  $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %}
   ins_encode %{
-    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int lshift = $lshift_count$$constant & 31;
+    int rshift = $rshift_count$$constant & 31;
     int s = 31 - lshift;
     int r = (rshift - lshift) & 31;
     __ ubfmw(as_Register($dst$$reg),
@@ -11491,13 +11479,12 @@
 instruct ubfizwI(iRegINoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask)
 %{
   match(Set dst (LShiftI (AndI src mask) lshift));
-  predicate((unsigned int)n->in(2)->get_int() <= 31 &&
-    (exact_log2(n->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= (31+1));
+  predicate((exact_log2(n->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 31)) <= (31 + 1));
 
   ins_cost(INSN_COST);
   format %{ "ubfizw $dst, $src, $lshift, $mask" %}
   ins_encode %{
-    int lshift = $lshift$$constant;
+    int lshift = $lshift$$constant & 31;
     long mask = $mask$$constant;
     int width = exact_log2(mask+1);
     __ ubfizw(as_Register($dst$$reg),
@@ -11510,13 +11497,12 @@
 instruct ubfizL(iRegLNoSp dst, iRegL src, immI lshift, immL_bitmask mask)
 %{
   match(Set dst (LShiftL (AndL src mask) lshift));
-  predicate((unsigned int)n->in(2)->get_int() <= 63 &&
-    (exact_log2_long(n->in(1)->in(2)->get_long()+1) + (unsigned int)n->in(2)->get_int()) <= (63+1));
+  predicate((exact_log2_long(n->in(1)->in(2)->get_long() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1));
 
   ins_cost(INSN_COST);
   format %{ "ubfiz $dst, $src, $lshift, $mask" %}
   ins_encode %{
-    int lshift = $lshift$$constant;
+    int lshift = $lshift$$constant & 63;
     long mask = $mask$$constant;
     int width = exact_log2_long(mask+1);
     __ ubfiz(as_Register($dst$$reg),
@@ -11528,14 +11514,13 @@
 // If there is a convert I to L block between and AndI and a LShiftL, we can also match ubfiz
 instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask)
 %{
-  match(Set dst (LShiftL (ConvI2L(AndI src mask)) lshift));
-  predicate((unsigned int)n->in(2)->get_int() <= 31 &&
-    (exact_log2((unsigned int)n->in(1)->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= 32);
+  match(Set dst (LShiftL (ConvI2L (AndI src mask)) lshift));
+  predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1));
 
   ins_cost(INSN_COST);
   format %{ "ubfiz $dst, $src, $lshift, $mask" %}
   ins_encode %{
-    int lshift = $lshift$$constant;
+    int lshift = $lshift$$constant & 63;
     long mask = $mask$$constant;
     int width = exact_log2(mask+1);
     __ ubfiz(as_Register($dst$$reg),
@@ -11549,7 +11534,7 @@
 instruct extrOrL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr)
 %{
   match(Set dst (OrL (LShiftL src1 lshift) (URShiftL src2 rshift)));
-  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63));
+  predicate(0 == (((n->in(1)->in(2)->get_int() & 63) + (n->in(2)->in(2)->get_int() & 63)) & 63));
 
   ins_cost(INSN_COST);
   format %{ "extr $dst, $src1, $src2, #$rshift" %}
@@ -11564,7 +11549,7 @@
 instruct extrOrI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr)
 %{
   match(Set dst (OrI (LShiftI src1 lshift) (URShiftI src2 rshift)));
-  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31));
+  predicate(0 == (((n->in(1)->in(2)->get_int() & 31) + (n->in(2)->in(2)->get_int() & 31)) & 31));
 
   ins_cost(INSN_COST);
   format %{ "extr $dst, $src1, $src2, #$rshift" %}
@@ -11579,7 +11564,7 @@
 instruct extrAddL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr)
 %{
   match(Set dst (AddL (LShiftL src1 lshift) (URShiftL src2 rshift)));
-  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63));
+  predicate(0 == (((n->in(1)->in(2)->get_int() & 63) + (n->in(2)->in(2)->get_int() & 63)) & 63));
 
   ins_cost(INSN_COST);
   format %{ "extr $dst, $src1, $src2, #$rshift" %}
@@ -11594,7 +11579,7 @@
 instruct extrAddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift, immI rshift, rFlagsReg cr)
 %{
   match(Set dst (AddI (LShiftI src1 lshift) (URShiftI src2 rshift)));
-  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31));
+  predicate(0 == (((n->in(1)->in(2)->get_int() & 31) + (n->in(2)->in(2)->get_int() & 31)) & 31));
 
   ins_cost(INSN_COST);
   format %{ "extr $dst, $src1, $src2, #$rshift" %}
@@ -14061,55 +14046,63 @@
 // ============================================================================
 // Max and Min
 
-instruct minI_rReg(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
-%{
-  match(Set dst (MinI src1 src2));
-
-  effect(DEF dst, USE src1, USE src2, KILL cr);
-  size(8);
-
-  ins_cost(INSN_COST * 3);
-  format %{
-    "cmpw $src1 $src2\t signed int\n\t"
-    "cselw $dst, $src1, $src2 lt\t"
-  %}
-
-  ins_encode %{
-    __ cmpw(as_Register($src1$$reg),
-            as_Register($src2$$reg));
+instruct cmovI_reg_reg_lt(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
+%{
+  effect( DEF dst, USE src1, USE src2, USE cr );
+
+  ins_cost(INSN_COST * 2);
+  format %{ "cselw $dst, $src1, $src2 lt\t"  %}
+
+  ins_encode %{
     __ cselw(as_Register($dst$$reg),
              as_Register($src1$$reg),
              as_Register($src2$$reg),
              Assembler::LT);
   %}
 
-  ins_pipe(ialu_reg_reg);
+  ins_pipe(icond_reg_reg);
+%}
+
+instruct minI_rReg(iRegINoSp dst, iRegI src1, iRegI src2)
+%{
+  match(Set dst (MinI src1 src2));
+  ins_cost(INSN_COST * 3);
+
+  expand %{
+    rFlagsReg cr;
+    compI_reg_reg(cr, src1, src2);
+    cmovI_reg_reg_lt(dst, src1, src2, cr);
+  %}
+
 %}
 // FROM HERE
 
-instruct maxI_rReg(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
-%{
-  match(Set dst (MaxI src1 src2));
-
-  effect(DEF dst, USE src1, USE src2, KILL cr);
-  size(8);
-
-  ins_cost(INSN_COST * 3);
-  format %{
-    "cmpw $src1 $src2\t signed int\n\t"
-    "cselw $dst, $src1, $src2 gt\t"
-  %}
-
-  ins_encode %{
-    __ cmpw(as_Register($src1$$reg),
-            as_Register($src2$$reg));
+instruct cmovI_reg_reg_gt(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
+%{
+  effect( DEF dst, USE src1, USE src2, USE cr );
+
+  ins_cost(INSN_COST * 2);
+  format %{ "cselw $dst, $src1, $src2 gt\t"  %}
+
+  ins_encode %{
     __ cselw(as_Register($dst$$reg),
              as_Register($src1$$reg),
              as_Register($src2$$reg),
              Assembler::GT);
   %}
 
-  ins_pipe(ialu_reg_reg);
+  ins_pipe(icond_reg_reg);
+%}
+
+instruct maxI_rReg(iRegINoSp dst, iRegI src1, iRegI src2)
+%{
+  match(Set dst (MaxI src1 src2));
+  ins_cost(INSN_COST * 3);
+  expand %{
+    rFlagsReg cr;
+    compI_reg_reg(cr, src1, src2);
+    cmovI_reg_reg_gt(dst, src1, src2, cr);
+  %}
 %}
 
 // ============================================================================
--- a/src/hotspot/cpu/aarch64/aarch64_ad.m4	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/aarch64/aarch64_ad.m4	Fri May 03 14:59:32 2019 -0400
@@ -154,14 +154,11 @@
 instruct $4$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift_count, immI rshift_count)
 %{
   match(Set dst EXTEND($1, $3, src, lshift_count, rshift_count));
-  // Make sure we are not going to exceed what $4 can do.
-  predicate((unsigned int)n->in(2)->get_int() <= $2
-            && (unsigned int)n->in(1)->in(2)->get_int() <= $2);
-
   ins_cost(INSN_COST * 2);
   format %{ "$4  $dst, $src, $rshift_count - $lshift_count, #$2 - $lshift_count" %}
   ins_encode %{
-    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int lshift = $lshift_count$$constant & $2;
+    int rshift = $rshift_count$$constant & $2;
     int s = $2 - lshift;
     int r = (rshift - lshift) & $2;
     __ $4(as_Register($dst$$reg),
@@ -224,13 +221,12 @@
 `instruct $2$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift, imm$1_bitmask mask)
 %{
   match(Set dst (LShift$1 (And$1 src mask) lshift));
-  predicate((unsigned int)n->in(2)->get_int() <= $3 &&
-    (exact_log2$5(n->in(1)->in(2)->get_$4()+1) + (unsigned int)n->in(2)->get_int()) <= ($3+1));
+  predicate((exact_log2$5(n->in(1)->in(2)->get_$4() + 1) + (n->in(2)->get_int() & $3)) <= ($3 + 1));
 
   ins_cost(INSN_COST);
   format %{ "$2 $dst, $src, $lshift, $mask" %}
   ins_encode %{
-    int lshift = $lshift$$constant;
+    int lshift = $lshift$$constant & $3;
     long mask = $mask$$constant;
     int width = exact_log2$5(mask+1);
     __ $2(as_Register($dst$$reg),
@@ -239,19 +235,18 @@
   ins_pipe(ialu_reg_shift);
 %}')
 UBFIZ_INSN(I, ubfizw, 31, int)
-UBFIZ_INSN(L, ubfiz, 63, long, _long)
+UBFIZ_INSN(L, ubfiz,  63, long, _long)
 
 // If there is a convert I to L block between and AndI and a LShiftL, we can also match ubfiz
 instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask)
 %{
-  match(Set dst (LShiftL (ConvI2L(AndI src mask)) lshift));
-  predicate((unsigned int)n->in(2)->get_int() <= 31 &&
-    (exact_log2((unsigned int)n->in(1)->in(1)->in(2)->get_int()+1) + (unsigned int)n->in(2)->get_int()) <= 32);
+  match(Set dst (LShiftL (ConvI2L (AndI src mask)) lshift));
+  predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1));
 
   ins_cost(INSN_COST);
   format %{ "ubfiz $dst, $src, $lshift, $mask" %}
   ins_encode %{
-    int lshift = $lshift$$constant;
+    int lshift = $lshift$$constant & 63;
     long mask = $mask$$constant;
     int width = exact_log2(mask+1);
     __ ubfiz(as_Register($dst$$reg),
@@ -266,7 +261,7 @@
 `instruct extr$3$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immI lshift, immI rshift, rFlagsReg cr)
 %{
   match(Set dst ($3$1 (LShift$1 src1 lshift) (URShift$1 src2 rshift)));
-  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & $2));
+  predicate(0 == (((n->in(1)->in(2)->get_int() & $2) + (n->in(2)->in(2)->get_int() & $2)) & $2));
 
   ins_cost(INSN_COST);
   format %{ "extr $dst, $src1, $src2, #$rshift" %}
--- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,7 +33,6 @@
 // (see globals.hpp)
 
 define_pd_global(bool, ShareVtableStubs,         true);
-define_pd_global(bool, NeedsDeoptSuspend,        false); // only register window machines need this
 
 define_pd_global(bool, ImplicitNullChecks,       true);  // Generate code for implicit null checks
 define_pd_global(bool, TrapBasedNullChecks,  false);
--- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp	Fri May 03 14:59:32 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,7 +30,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "vmreg_aarch64.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump() || inst->is_blr()) {
     return pc_offset + NativeCall::instruction_size;
   } else if (inst->is_general_jump()) {
@@ -43,12 +43,12 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
 #ifdef ASSERT
   {
     NativeInstruction *insn = nativeInstruction_at(pc);
-    if (HotSpotObjectConstantImpl::compressed(constant)) {
+    if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
       // Mov narrow constant: movz n << 16, movk
       assert(Instruction_aarch64::extract(insn->encoding(), 31, 21) == 0b11010010101 &&
              nativeInstruction_at(pc+4)->is_movk(), "wrong insn in patch");
@@ -59,7 +59,7 @@
     }
   }
 #endif // ASSERT
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
   jobject value = JNIHandles::make_local(obj());
   MacroAssembler::patch_oop(pc, (address)obj());
   int oop_index = _oop_recorder->find_index(value);
@@ -67,21 +67,21 @@
   _instructions->relocate(pc, rspec);
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
-    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK);
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
+    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     MacroAssembler::patch_narrow_klass(pc, narrowOop);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
   } else {
     NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    void* reference = record_metadata_reference(_instructions, pc, constant, CHECK);
+    void* reference = record_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t) reference);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
   NativeInstruction* inst = nativeInstruction_at(pc);
   if (inst->is_adr_aligned() || inst->is_ldr_literal()
@@ -94,7 +94,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     NativeCall* call = nativeCall_at(pc);
@@ -118,12 +118,12 @@
   TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -157,7 +157,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR:
       JVMCI_ERROR("unimplemented");
@@ -178,7 +178,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   if (jvmci_reg < RegisterImpl::number_of_registers) {
     return as_Register(jvmci_reg)->as_VMReg();
   } else {
--- a/src/hotspot/cpu/arm/globals_arm.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/arm/globals_arm.hpp	Fri May 03 14:59:32 2019 -0400
@@ -40,8 +40,6 @@
 define_pd_global(intx,  CodeEntryAlignment,       16);
 define_pd_global(intx,  OptoLoopAlignment,        16);
 
-define_pd_global(bool,  NeedsDeoptSuspend,        false); // only register window machines need this
-
 #define DEFAULT_STACK_YELLOW_PAGES (2)
 #define DEFAULT_STACK_RED_PAGES (1)
 #define DEFAULT_STACK_SHADOW_PAGES (5 DEBUG_ONLY(+1))
--- a/src/hotspot/cpu/ppc/globals_ppc.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/ppc/globals_ppc.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,8 +33,6 @@
 // (see globals.hpp)
 
 define_pd_global(bool, ShareVtableStubs,      true);
-define_pd_global(bool, NeedsDeoptSuspend,     false); // Only register window machines need this.
-
 
 define_pd_global(bool, ImplicitNullChecks,    true);  // Generate code for implicit null checks.
 define_pd_global(bool, TrapBasedNullChecks,   true);
--- a/src/hotspot/cpu/s390/globals_s390.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/s390/globals_s390.hpp	Fri May 03 14:59:32 2019 -0400
@@ -35,7 +35,6 @@
 
 // z/Architecture remembers branch targets, so don't share vtables.
 define_pd_global(bool,  ShareVtableStubs,            true);
-define_pd_global(bool,  NeedsDeoptSuspend,           false); // Only register window machines need this.
 
 define_pd_global(bool,  ImplicitNullChecks,          true);  // Generate code for implicit null checks.
 define_pd_global(bool,  TrapBasedNullChecks,         true);
--- a/src/hotspot/cpu/sparc/globals_sparc.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/sparc/globals_sparc.hpp	Fri May 03 14:59:32 2019 -0400
@@ -38,7 +38,6 @@
 // according to the prior table. So, we let the thread continue and let it block by itself.
 define_pd_global(bool, DontYieldALot,               true);  // yield no more than 100 times per second
 define_pd_global(bool, ShareVtableStubs,            false); // improves performance markedly for mtrt and compress
-define_pd_global(bool, NeedsDeoptSuspend,           true); // register window machines need this
 
 define_pd_global(bool, ImplicitNullChecks,          true);  // Generate code for implicit null checks
 define_pd_global(bool, TrapBasedNullChecks,         false); // Not needed on sparc.
--- a/src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp	Fri May 03 14:59:32 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
@@ -31,7 +31,7 @@
 #include "utilities/align.hpp"
 #include "vmreg_sparc.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump()) {
     return pc_offset + NativeCall::instruction_size;
   } else if (inst->is_call_reg()) {
@@ -44,11 +44,11 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
   jobject value = JNIHandles::make_local(obj());
-  if (HotSpotObjectConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
     int oop_index = _oop_recorder->find_index(value);
     RelocationHolder rspec = oop_Relocation::spec(oop_index);
     _instructions->relocate(pc, rspec, 1);
@@ -64,22 +64,22 @@
   }
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
     NativeMovConstReg32* move = nativeMovConstReg32_at(pc);
-    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK);
+    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t)narrowOop);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
   } else {
     NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    void* reference = record_metadata_reference(_instructions, pc, constant, CHECK);
+    void* reference = record_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t)reference);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
   NativeInstruction* inst = nativeInstruction_at(pc);
   NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
@@ -100,7 +100,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     NativeCall* call = nativeCall_at(pc);
@@ -116,12 +116,12 @@
   TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -155,7 +155,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR:
       JVMCI_ERROR("unimplemented");
@@ -176,7 +176,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   // JVMCI Registers are numbered as follows:
   //   0..31: Thirty-two General Purpose registers (CPU Registers)
   //   32..63: Thirty-two single precision float registers
--- a/src/hotspot/cpu/x86/globals_x86.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/x86/globals_x86.hpp	Fri May 03 14:59:32 2019 -0400
@@ -32,7 +32,6 @@
 // (see globals.hpp)
 
 define_pd_global(bool, ShareVtableStubs,         true);
-define_pd_global(bool, NeedsDeoptSuspend,        false); // only register window machines need this
 
 define_pd_global(bool, ImplicitNullChecks,       true);  // Generate code for implicit null checks
 define_pd_global(bool, TrapBasedNullChecks,      false); // Not needed on x86.
--- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
 #include "code/vmreg.hpp"
 #include "vmreg_x86.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump()) {
     assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
     return (pc_offset + NativeCall::instruction_size);
@@ -54,7 +54,7 @@
     return (offset);
   } else if (inst->is_call_reg()) {
     // the inlined vtable stub contains a "call register" instruction
-    assert(method.not_null(), "only valid for virtual calls");
+    assert(method.is_non_null(), "only valid for virtual calls");
     return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
   } else if (inst->is_cond_jump()) {
     address pc = (address) (inst);
@@ -64,11 +64,12 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
+  Thread* THREAD = Thread::current();
   jobject value = JNIHandles::make_local(obj());
-  if (HotSpotObjectConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
 #ifdef _LP64
     address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
     int oop_index = _oop_recorder->find_index(value);
@@ -85,24 +86,24 @@
   }
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
 #ifdef _LP64
     address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
-    *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, CHECK);
+    *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, JVMCI_CHECK);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
 #else
     JVMCI_ERROR("compressed Klass* on 32bit");
 #endif
   } else {
     address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-    *((void**) operand) = record_metadata_reference(_instructions, operand, constant, CHECK);
+    *((void**) operand) = record_metadata_reference(_instructions, operand, constant, JVMCI_CHECK);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
 
   address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
@@ -117,7 +118,7 @@
   TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     // NOTE: for call without a mov, the offset must fit a 32-bit immediate
@@ -145,12 +146,12 @@
   TRACE_jvmci_3("relocating (foreign call)  at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -199,7 +200,7 @@
 }
 
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR: {
       relocate_poll_near(pc);
@@ -229,7 +230,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   if (jvmci_reg < RegisterImpl::number_of_registers) {
     return as_Register(jvmci_reg)->as_VMReg();
   } else {
--- a/src/hotspot/cpu/zero/globals_zero.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/cpu/zero/globals_zero.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,7 +33,6 @@
 // runtime system.  See globals.hpp for details of what they do.
 
 define_pd_global(bool,  ShareVtableStubs,     true);
-define_pd_global(bool,  NeedsDeoptSuspend,    false);
 
 define_pd_global(bool,  ImplicitNullChecks,   true);
 define_pd_global(bool,  TrapBasedNullChecks,  false);
--- a/src/hotspot/os/bsd/os_bsd.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os/bsd/os_bsd.cpp	Fri May 03 14:59:32 2019 -0400
@@ -678,7 +678,7 @@
 
   // handshaking with parent thread
   {
-    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(sync, Mutex::_no_safepoint_check_flag);
 
     // notify parent thread
     osthread->set_state(INITIALIZED);
@@ -686,7 +686,7 @@
 
     // wait until os::start_thread()
     while (osthread->get_state() == INITIALIZED) {
-      sync->wait(Mutex::_no_safepoint_check_flag);
+      sync->wait_without_safepoint_check();
     }
   }
 
@@ -766,9 +766,9 @@
     // Wait until child thread is either initialized or aborted
     {
       Monitor* sync_with_child = osthread->startThread_lock();
-      MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(sync_with_child, Mutex::_no_safepoint_check_flag);
       while ((state = osthread->get_state()) == ALLOCATED) {
-        sync_with_child->wait(Mutex::_no_safepoint_check_flag);
+        sync_with_child->wait_without_safepoint_check();
       }
     }
 
@@ -840,7 +840,7 @@
   OSThread * osthread = thread->osthread();
   assert(osthread->get_state() != INITIALIZED, "just checking");
   Monitor* sync_with_child = osthread->startThread_lock();
-  MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(sync_with_child, Mutex::_no_safepoint_check_flag);
   sync_with_child->notify();
 }
 
--- a/src/hotspot/os/linux/os_linux.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os/linux/os_linux.cpp	Fri May 03 14:59:32 2019 -0400
@@ -773,7 +773,7 @@
 
   // handshaking with parent thread
   {
-    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(sync, Mutex::_no_safepoint_check_flag);
 
     // notify parent thread
     osthread->set_state(INITIALIZED);
@@ -781,7 +781,7 @@
 
     // wait until os::start_thread()
     while (osthread->get_state() == INITIALIZED) {
-      sync->wait(Mutex::_no_safepoint_check_flag);
+      sync->wait_without_safepoint_check();
     }
   }
 
@@ -881,9 +881,9 @@
     // Wait until child thread is either initialized or aborted
     {
       Monitor* sync_with_child = osthread->startThread_lock();
-      MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(sync_with_child, Mutex::_no_safepoint_check_flag);
       while ((state = osthread->get_state()) == ALLOCATED) {
-        sync_with_child->wait(Mutex::_no_safepoint_check_flag);
+        sync_with_child->wait_without_safepoint_check();
       }
     }
   }
@@ -975,7 +975,7 @@
   OSThread * osthread = thread->osthread();
   assert(osthread->get_state() != INITIALIZED, "just checking");
   Monitor* sync_with_child = osthread->startThread_lock();
-  MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(sync_with_child, Mutex::_no_safepoint_check_flag);
   sync_with_child->notify();
 }
 
@@ -5158,13 +5158,16 @@
     return JNI_ERR;
   }
 
+#if defined(IA32)
+  // Need to ensure we've determined the process's initial stack to
+  // perform the workaround
+  Linux::capture_initial_stack(JavaThread::stack_size_at_create());
+  workaround_expand_exec_shield_cs_limit();
+#else
   suppress_primordial_thread_resolution = Arguments::created_by_java_launcher();
   if (!suppress_primordial_thread_resolution) {
     Linux::capture_initial_stack(JavaThread::stack_size_at_create());
   }
-
-#if defined(IA32)
-  workaround_expand_exec_shield_cs_limit();
 #endif
 
   Linux::libpthread_init();
--- a/src/hotspot/os/windows/os_windows.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os/windows/os_windows.cpp	Fri May 03 14:59:32 2019 -0400
@@ -3558,41 +3558,19 @@
   Sleep(ms);
 }
 
+// Windows does not provide sleep functionality with nanosecond resolution, so we
+// try to approximate this with spinning combined with yielding if another thread
+// is ready to run on the current processor.
 void os::naked_short_nanosleep(jlong ns) {
   assert(ns > -1 && ns < NANOUNITS, "Un-interruptable sleep, short time use only");
-  LARGE_INTEGER hundreds_nanos = { 0 };
-  HANDLE wait_timer = ::CreateWaitableTimer(NULL /* attributes*/,
-                                            true /* manual reset */,
-                                            NULL /* name */ );
-  if (wait_timer == NULL) {
-    log_warning(os)("Failed to CreateWaitableTimer: %u", GetLastError());
-    return;
-  }
-
-  // We need a minimum of one hundred nanos.
-  ns = ns > 100 ? ns : 100;
-
-  // Round ns to the nearst hundred of nanos.
-  // Negative values indicate relative time.
-  hundreds_nanos.QuadPart = -((ns + 50) / 100);
-
-  if (::SetWaitableTimer(wait_timer /* handle */,
-                         &hundreds_nanos /* due time */,
-                         0 /* period */,
-                         NULL /* comp func */,
-                         NULL /* comp func args */,
-                         FALSE /* resume */)) {
-    DWORD res = ::WaitForSingleObject(wait_timer /* handle */, INFINITE /* timeout */);
-    if (res != WAIT_OBJECT_0) {
-      if (res == WAIT_FAILED) {
-        log_warning(os)("Failed to WaitForSingleObject: %u", GetLastError());
-      } else {
-        log_warning(os)("Unexpected return from WaitForSingleObject: %s",
-                        res == WAIT_ABANDONED ? "WAIT_ABANDONED" : "WAIT_TIMEOUT");
-      }
+
+  int64_t start = os::javaTimeNanos();
+  do {
+    if (SwitchToThread() == 0) {
+      // Nothing else is ready to run on this cpu, spin a little
+      SpinPause();
     }
-  }
-  ::CloseHandle(wait_timer /* handle */);
+  } while (os::javaTimeNanos() - start < ns);
 }
 
 // Sleep forever; naked call to OS-specific sleep; use with CAUTION
--- a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -65,9 +65,7 @@
 #define inlasm_eieio()    __asm__ __volatile__ ("eieio"  : : : "memory");
 #define inlasm_isync()    __asm__ __volatile__ ("isync"  : : : "memory");
 // Use twi-isync for load_acquire (faster than lwsync).
-// ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"):
-// #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
-#define inlasm_acquire_reg(X) inlasm_lwsync();
+#define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
 
 inline void OrderAccess::loadload()   { inlasm_lwsync(); }
 inline void OrderAccess::storestore() { inlasm_lwsync(); }
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zAddress_linux_x86.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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.
- */
-
-#ifndef OS_CPU_LINUX_X86_GC_Z_ZADDRESS_LINUX_X86_INLINE_HPP
-#define OS_CPU_LINUX_X86_GC_Z_ZADDRESS_LINUX_X86_INLINE_HPP
-
-inline uintptr_t ZAddress::address(uintptr_t value) {
-  return value;
-}
-
-#endif // OS_CPU_LINUX_X86_GC_Z_ZADDRESS_LINUX_X86_INLINE_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.cpp	Fri May 03 14:59:32 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
@@ -23,11 +23,151 @@
 
 #include "precompiled.hpp"
 #include "gc/z/zGlobals.hpp"
+#include "gc/z/zUtils.inline.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
 
-uintptr_t ZAddressReservedStart() {
-  return ZAddressMetadataMarked0;
+//
+// The heap can have three different layouts, depending on the max heap size.
+//
+// Address Space & Pointer Layout 1
+// --------------------------------
+//
+//  +--------------------------------+ 0x00007FFFFFFFFFFF (127TB)
+//  .                                .
+//  .                                .
+//  .                                .
+//  +--------------------------------+ 0x0000014000000000 (20TB)
+//  |         Remapped View          |
+//  +--------------------------------+ 0x0000010000000000 (16TB)
+//  |     (Reserved, but unused)     |
+//  +--------------------------------+ 0x00000c0000000000 (12TB)
+//  |         Marked1 View           |
+//  +--------------------------------+ 0x0000080000000000 (8TB)
+//  |         Marked0 View           |
+//  +--------------------------------+ 0x0000040000000000 (4TB)
+//  .                                .
+//  +--------------------------------+ 0x0000000000000000
+//
+//   6                  4 4  4 4
+//   3                  6 5  2 1                                             0
+//  +--------------------+----+-----------------------------------------------+
+//  |00000000 00000000 00|1111|11 11111111 11111111 11111111 11111111 11111111|
+//  +--------------------+----+-----------------------------------------------+
+//  |                    |    |
+//  |                    |    * 41-0 Object Offset (42-bits, 4TB address space)
+//  |                    |
+//  |                    * 45-42 Metadata Bits (4-bits)  0001 = Marked0      (Address view 4-8TB)
+//  |                                                    0010 = Marked1      (Address view 8-12TB)
+//  |                                                    0100 = Remapped     (Address view 16-20TB)
+//  |                                                    1000 = Finalizable  (Address view N/A)
+//  |
+//  * 63-46 Fixed (18-bits, always zero)
+//
+//
+// Address Space & Pointer Layout 2
+// --------------------------------
+//
+//  +--------------------------------+ 0x00007FFFFFFFFFFF (127TB)
+//  .                                .
+//  .                                .
+//  .                                .
+//  +--------------------------------+ 0x0000280000000000 (40TB)
+//  |         Remapped View          |
+//  +--------------------------------+ 0x0000200000000000 (32TB)
+//  |     (Reserved, but unused)     |
+//  +--------------------------------+ 0x0000180000000000 (24TB)
+//  |         Marked1 View           |
+//  +--------------------------------+ 0x0000100000000000 (16TB)
+//  |         Marked0 View           |
+//  +--------------------------------+ 0x0000080000000000 (8TB)
+//  .                                .
+//  +--------------------------------+ 0x0000000000000000
+//
+//   6                 4 4  4 4
+//   3                 7 6  3 2                                              0
+//  +------------------+-----+------------------------------------------------+
+//  |00000000 00000000 0|1111|111 11111111 11111111 11111111 11111111 11111111|
+//  +-------------------+----+------------------------------------------------+
+//  |                   |    |
+//  |                   |    * 42-0 Object Offset (43-bits, 8TB address space)
+//  |                   |
+//  |                   * 46-43 Metadata Bits (4-bits)  0001 = Marked0      (Address view 8-16TB)
+//  |                                                   0010 = Marked1      (Address view 16-24TB)
+//  |                                                   0100 = Remapped     (Address view 32-40TB)
+//  |                                                   1000 = Finalizable  (Address view N/A)
+//  |
+//  * 63-47 Fixed (17-bits, always zero)
+//
+//
+// Address Space & Pointer Layout 3
+// --------------------------------
+//
+//  +--------------------------------+ 0x00007FFFFFFFFFFF (127TB)
+//  .                                .
+//  .                                .
+//  .                                .
+//  +--------------------------------+ 0x0000500000000000 (80TB)
+//  |         Remapped View          |
+//  +--------------------------------+ 0x0000400000000000 (64TB)
+//  |     (Reserved, but unused)     |
+//  +--------------------------------+ 0x0000300000000000 (48TB)
+//  |         Marked1 View           |
+//  +--------------------------------+ 0x0000200000000000 (32TB)
+//  |         Marked0 View           |
+//  +--------------------------------+ 0x0000100000000000 (16TB)
+//  .                                .
+//  +--------------------------------+ 0x0000000000000000
+//
+//   6               4  4  4 4
+//   3               8  7  4 3                                               0
+//  +------------------+----+-------------------------------------------------+
+//  |00000000 00000000 |1111|1111 11111111 11111111 11111111 11111111 11111111|
+//  +------------------+----+-------------------------------------------------+
+//  |                  |    |
+//  |                  |    * 43-0 Object Offset (44-bits, 16TB address space)
+//  |                  |
+//  |                  * 47-44 Metadata Bits (4-bits)  0001 = Marked0      (Address view 16-32TB)
+//  |                                                  0010 = Marked1      (Address view 32-48TB)
+//  |                                                  0100 = Remapped     (Address view 64-80TB)
+//  |                                                  1000 = Finalizable  (Address view N/A)
+//  |
+//  * 63-48 Fixed (16-bits, always zero)
+//
+
+uintptr_t ZPlatformAddressSpaceStart() {
+  const uintptr_t first_heap_view_address = (uintptr_t)1 << (ZPlatformAddressMetadataShift() + 0);
+  const size_t min_address_offset = 0;
+  return first_heap_view_address + min_address_offset;
 }
 
-uintptr_t ZAddressReservedEnd() {
-  return ZAddressMetadataRemapped + ZAddressOffsetMax;
+uintptr_t ZPlatformAddressSpaceEnd() {
+  const uintptr_t last_heap_view_address = (uintptr_t)1 << (ZPlatformAddressMetadataShift() + 2);
+  const size_t max_address_offset = (size_t)1 << ZPlatformAddressOffsetBits();
+  return last_heap_view_address + max_address_offset;
+}
+
+uintptr_t ZPlatformAddressReservedStart() {
+  return ZPlatformAddressSpaceStart();
+}
+
+uintptr_t ZPlatformAddressReservedEnd() {
+  return ZPlatformAddressSpaceEnd();
 }
+
+uintptr_t ZPlatformAddressBase() {
+  return 0;
+}
+
+size_t ZPlatformAddressOffsetBits() {
+  const size_t min_address_offset_bits = 42; // 4TB
+  const size_t max_address_offset_bits = 44; // 16TB
+  const size_t virtual_to_physical_ratio = 7; // 7:1
+  const size_t address_offset = ZUtils::round_up_power_of_2(MaxHeapSize * virtual_to_physical_ratio);
+  const size_t address_offset_bits = log2_intptr(address_offset);
+  return MIN2(MAX2(address_offset_bits, min_address_offset_bits), max_address_offset_bits);
+}
+
+size_t ZPlatformAddressMetadataShift() {
+  return ZPlatformAddressOffsetBits();
+}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp	Fri May 03 14:59:32 2019 -0400
@@ -35,56 +35,17 @@
 //  Large         X*M           > 4M                  2M
 //  ------------------------------------------------------------------
 //
-//
-// Address Space & Pointer Layout
-// ------------------------------
-//
-//  +--------------------------------+ 0x00007FFFFFFFFFFF (127TB)
-//  .                                .
-//  .                                .
-//  .                                .
-//  +--------------------------------+ 0x0000140000000000 (20TB)
-//  |         Remapped View          |
-//  +--------------------------------+ 0x0000100000000000 (16TB)
-//  |     (Reserved, but unused)     |
-//  +--------------------------------+ 0x00000c0000000000 (12TB)
-//  |         Marked1 View           |
-//  +--------------------------------+ 0x0000080000000000 (8TB)
-//  |         Marked0 View           |
-//  +--------------------------------+ 0x0000040000000000 (4TB)
-//  .                                .
-//  +--------------------------------+ 0x0000000000000000
-//
-//
-//   6                 4 4 4  4 4                                             0
-//   3                 7 6 5  2 1                                             0
-//  +-------------------+-+----+-----------------------------------------------+
-//  |00000000 00000000 0|0|1111|11 11111111 11111111 11111111 11111111 11111111|
-//  +-------------------+-+----+-----------------------------------------------+
-//  |                   | |    |
-//  |                   | |    * 41-0 Object Offset (42-bits, 4TB address space)
-//  |                   | |
-//  |                   | * 45-42 Metadata Bits (4-bits)  0001 = Marked0      (Address view 4-8TB)
-//  |                   |                                 0010 = Marked1      (Address view 8-12TB)
-//  |                   |                                 0100 = Remapped     (Address view 16-20TB)
-//  |                   |                                 1000 = Finalizable  (Address view N/A)
-//  |                   |
-//  |                   * 46-46 Unused (1-bit, always zero)
-//  |
-//  * 63-47 Fixed (17-bits, always zero)
-//
+const size_t ZPlatformGranuleSizeShift      = 21; // 2MB
+const size_t ZPlatformMaxHeapSizeShift      = 46; // 16TB
+const size_t ZPlatformNMethodDisarmedOffset = 4;
+const size_t ZPlatformCacheLineSize         = 64;
 
-const size_t    ZPlatformGranuleSizeShift      = 21; // 2M
-
-const size_t    ZPlatformAddressOffsetBits     = 42; // 4TB
-
-const uintptr_t ZPlatformAddressMetadataShift  = ZPlatformAddressOffsetBits;
-
-const uintptr_t ZPlatformAddressSpaceStart     = (uintptr_t)1 << ZPlatformAddressOffsetBits;
-const uintptr_t ZPlatformAddressSpaceSize      = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4;
-
-const size_t    ZPlatformNMethodDisarmedOffset = 4;
-
-const size_t    ZPlatformCacheLineSize         = 64;
+uintptr_t    ZPlatformAddressSpaceStart();
+uintptr_t    ZPlatformAddressSpaceEnd();
+uintptr_t    ZPlatformAddressReservedStart();
+uintptr_t    ZPlatformAddressReservedEnd();
+uintptr_t    ZPlatformAddressBase();
+size_t       ZPlatformAddressOffsetBits();
+size_t       ZPlatformAddressMetadataShift();
 
 #endif // OS_CPU_LINUX_X86_GC_Z_ZGLOBALS_LINUX_X86_HPP
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri May 03 14:59:32 2019 -0400
@@ -827,6 +827,7 @@
  */
 void os::workaround_expand_exec_shield_cs_limit() {
 #if defined(IA32)
+  assert(Linux::initial_thread_stack_bottom() != NULL, "sanity");
   size_t page_size = os::vm_page_size();
 
   /*
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Fri May 03 14:59:32 2019 -0400
@@ -32,8 +32,6 @@
 #include "compiler/compilerOracle.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "jvmci/compilerRuntime.hpp"
-#include "jvmci/jvmciRuntime.hpp"
 #include "oops/method.inline.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
@@ -167,7 +165,7 @@
 
   {
     // Enter critical section.  Does not block for safepoint.
-    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
 
     if (*_state_adr == new_state) {
       // another thread already performed this transition so nothing
@@ -218,7 +216,7 @@
 
   {
     // Enter critical section.  Does not block for safepoint.
-    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
 
     if (*_state_adr == in_use) {
       // another thread already performed this transition so nothing
--- a/src/hotspot/share/aot/aotLoader.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/aot/aotLoader.cpp	Fri May 03 14:59:32 2019 -0400
@@ -26,8 +26,8 @@
 
 #include "aot/aotCodeHeap.hpp"
 #include "aot/aotLoader.inline.hpp"
-#include "jvmci/jvmciRuntime.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/os.inline.hpp"
@@ -200,7 +200,7 @@
       if ((*lib)->is_valid()) {
         AOTCodeHeap* heap = new AOTCodeHeap(*lib);
         {
-          MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+          MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
           add_heap(heap);
           CodeCache::add_heap(heap);
         }
--- a/src/hotspot/share/c1/c1_Runtime1.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1046,7 +1046,7 @@
   // Now copy code back
 
   {
-    MutexLockerEx ml_patch (Patching_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml_patch (Patching_lock, Mutex::_no_safepoint_check_flag);
     //
     // Deoptimization may have happened while we waited for the lock.
     // In that case we don't bother to do any patching we just return
@@ -1265,7 +1265,7 @@
   // If we are patching in a non-perm oop, make sure the nmethod
   // is on the right list.
   {
-    MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker 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/classfile/classFileParser.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Fri May 03 14:59:32 2019 -0400
@@ -126,7 +126,8 @@
 #define JAVA_13_VERSION                   57
 
 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
-  assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION,
+  assert((bad_constant == JVM_CONSTANT_Module ||
+          bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,
          "Unexpected bad constant pool entry");
   if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant;
 }
@@ -343,8 +344,8 @@
         }
         break;
       }
-      case 19:
-      case 20: {
+      case JVM_CONSTANT_Module:
+      case JVM_CONSTANT_Package: {
         // Record that an error occurred in these two cases but keep parsing so
         // that ACC_Module can be checked for in the access_flags.  Need to
         // throw NoClassDefFoundError in that case.
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Fri May 03 14:59:32 2019 -0400
@@ -449,7 +449,7 @@
 
 void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) {
   {
-    MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
     Klass* old_value = _klasses;
     k->set_next_link(old_value);
     // Link the new item into the list, making sure the linked class is stable
@@ -549,7 +549,7 @@
       modules = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size);
 
       {
-        MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+        MutexLocker m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
         // Ensure _modules is stable, since it is examined without a lock
         OrderAccess::release_store(&_modules, modules);
       }
@@ -743,7 +743,7 @@
   // Lock-free access requires load_acquire.
   ClassLoaderMetaspace* metaspace = OrderAccess::load_acquire(&_metaspace);
   if (metaspace == NULL) {
-    MutexLockerEx ml(_metaspace_lock,  Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(_metaspace_lock,  Mutex::_no_safepoint_check_flag);
     // Check if _metaspace got allocated while we were waiting for this lock.
     if ((metaspace = _metaspace) == NULL) {
       if (this == the_null_class_loader_data()) {
@@ -764,7 +764,7 @@
 }
 
 OopHandle ClassLoaderData::add_handle(Handle h) {
-  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
   record_modified_oops();
   return OopHandle(_handles.add(h()));
 }
@@ -779,7 +779,7 @@
 }
 
 void ClassLoaderData::init_handle_locked(OopHandle& dest, Handle h) {
-  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
   if (dest.resolve() != NULL) {
     return;
   } else {
@@ -792,7 +792,7 @@
 void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
   // Metadata in shared region isn't deleted.
   if (!m->is_shared()) {
-    MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
     if (_deallocate_list == NULL) {
       _deallocate_list = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(100, true);
     }
--- a/src/hotspot/share/classfile/dictionary.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/dictionary.cpp	Fri May 03 14:59:32 2019 -0400
@@ -151,7 +151,7 @@
 bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
   // Lock the pd_set list.  This lock cannot safepoint since the caller holds
   // a Dictionary entry, which can be moved if the Dictionary is resized.
-  MutexLockerEx ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
 #ifdef ASSERT
   if (oopDesc::equals(protection_domain, instance_klass()->protection_domain())) {
     // Ensure this doesn't show up in the pd_set (invariant)
@@ -191,7 +191,7 @@
     ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
     // The pd_set in the dictionary entry is protected by a low level lock.
     // With concurrent PD table cleanup, these links could be broken.
-    MutexLockerEx ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
     ProtectionDomainEntry* new_head =
                 new ProtectionDomainEntry(entry, pd_set());
     set_pd_set(new_head);
@@ -369,7 +369,7 @@
                           probe = probe->next()) {
       Klass* e = probe->instance_klass();
 
-      MutexLockerEx ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
       ProtectionDomainEntry* current = probe->pd_set();
       ProtectionDomainEntry* prev = NULL;
       while (current != NULL) {
@@ -460,7 +460,7 @@
 }
 
 void DictionaryEntry::verify_protection_domain_set() {
-  MutexLockerEx ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
   for (ProtectionDomainEntry* current = pd_set(); // accessed at a safepoint
                               current != NULL;
                               current = current->_next) {
@@ -469,7 +469,7 @@
 }
 
 void DictionaryEntry::print_count(outputStream *st) {
-  MutexLockerEx ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
   int count = 0;
   for (ProtectionDomainEntry* current = pd_set();  // accessed inside SD lock
                               current != NULL;
--- a/src/hotspot/share/classfile/javaClasses.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1613,7 +1613,6 @@
 int java_lang_Thread::_tid_offset = 0;
 int java_lang_Thread::_thread_status_offset = 0;
 int java_lang_Thread::_park_blocker_offset = 0;
-int java_lang_Thread::_park_event_offset = 0 ;
 
 #define THREAD_FIELDS_DO(macro) \
   macro(_name_offset,          k, vmSymbols::name_name(), string_signature, false); \
@@ -1627,8 +1626,7 @@
   macro(_stackSize_offset,     k, "stackSize", long_signature, false); \
   macro(_tid_offset,           k, "tid", long_signature, false); \
   macro(_thread_status_offset, k, "threadStatus", int_signature, false); \
-  macro(_park_blocker_offset,  k, "parkBlocker", object_signature, false); \
-  macro(_park_event_offset,    k, "nativeParkEventPointer", long_signature, false)
+  macro(_park_blocker_offset,  k, "parkBlocker", object_signature, false)
 
 void java_lang_Thread::compute_offsets() {
   assert(_group_offset == 0, "offsets should be initialized only once");
@@ -1745,15 +1743,6 @@
   return java_thread->obj_field(_park_blocker_offset);
 }
 
-jlong java_lang_Thread::park_event(oop java_thread) {
-  return java_thread->long_field(_park_event_offset);
-}
-
-bool java_lang_Thread::set_park_event(oop java_thread, jlong ptr) {
-  java_thread->long_field_put(_park_event_offset, ptr);
-  return true;
-}
-
 const char* java_lang_Thread::thread_status_name(oop java_thread) {
   ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
   switch (status) {
@@ -2618,6 +2607,45 @@
   }
 }
 
+#if INCLUDE_JVMCI
+void java_lang_StackTraceElement::decode(Handle mirror, methodHandle method, int bci, Symbol*& methodname, Symbol*& filename, int& line_number) {
+  int method_id = method->orig_method_idnum();
+  int cpref = method->name_index();
+  decode(mirror, method_id, method->constants()->version(), bci, cpref, methodname, filename, line_number);
+}
+
+void java_lang_StackTraceElement::decode(Handle mirror, int method_id, int version, int bci, int cpref, Symbol*& methodname, Symbol*& filename, int& line_number) {
+  // Fill in class name
+  InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
+  Method* method = holder->method_with_orig_idnum(method_id, version);
+
+  // The method can be NULL if the requested class version is gone
+  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
+
+  // Fill in method name
+  methodname = sym;
+
+  if (!version_matches(method, version)) {
+    // If the method was redefined, accurate line number information isn't available
+    filename = NULL;
+    line_number = -1;
+  } else {
+    // Fill in source file name and line number.
+    // Use a specific ik version as a holder since the mirror might
+    // refer to a version that is now obsolete and no longer accessible
+    // via the previous versions list.
+    holder = holder->get_klass_version(version);
+    assert(holder != NULL, "sanity check");
+    Symbol* source = holder->source_file_name();
+    if (ShowHiddenFrames && source == NULL) {
+      source = vmSymbols::unknown_class_name();
+    }
+    filename = source;
+    line_number = Backtrace::get_line_number(method, bci);
+  }
+}
+#endif // INCLUDE_JVMCI
+
 Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
   HandleMark hm(THREAD);
   Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
--- a/src/hotspot/share/classfile/javaClasses.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Fri May 03 14:59:32 2019 -0400
@@ -371,7 +371,6 @@
   static int _tid_offset;
   static int _thread_status_offset;
   static int _park_blocker_offset;
-  static int _park_event_offset ;
 
   static void compute_offsets();
 
@@ -413,12 +412,6 @@
   // Blocker object responsible for thread parking
   static oop park_blocker(oop java_thread);
 
-  // Pointer to type-stable park handler, encoded as jlong.
-  // Should be set when apparently null
-  // For details, see unsafe.cpp Unsafe_Unpark
-  static jlong park_event(oop java_thread);
-  static bool set_park_event(oop java_thread, jlong ptr);
-
   // Java Thread Status for JVMTI and M&M use.
   // This thread status info is saved in threadStatus field of
   // java.lang.Thread java class.
@@ -1375,6 +1368,11 @@
   static void compute_offsets();
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
 
+#if INCLUDE_JVMCI
+  static void decode(Handle mirror, int method, int version, int bci, int cpref, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
+  static void decode(Handle mirror, methodHandle method, int bci, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
+#endif
+
   // Debugging
   friend class JavaClasses;
 };
--- a/src/hotspot/share/classfile/metadataOnStackMark.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/metadataOnStackMark.cpp	Fri May 03 14:59:32 2019 -0400
@@ -33,7 +33,7 @@
 #include "services/threadService.hpp"
 #include "utilities/chunkedList.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 
 MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
@@ -73,7 +73,7 @@
     JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
     ThreadService::metadata_do(Metadata::mark_on_stack);
 #if INCLUDE_JVMCI
-    JVMCIRuntime::metadata_do(Metadata::mark_on_stack);
+    JVMCI::metadata_do(Metadata::mark_on_stack);
 #endif
   }
 }
--- a/src/hotspot/share/classfile/packageEntry.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/packageEntry.cpp	Fri May 03 14:59:32 2019 -0400
@@ -245,7 +245,7 @@
 
 PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
   assert(!Module_lock->owned_by_self(), "should not have the Module_lock - use locked_lookup_only");
-  MutexLockerEx ml(Module_lock);
+  MutexLocker ml(Module_lock);
   return locked_lookup_only(name);
 }
 
--- a/src/hotspot/share/classfile/protectionDomainCache.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/protectionDomainCache.cpp	Fri May 03 14:59:32 2019 -0400
@@ -51,7 +51,7 @@
 }
 
 void ProtectionDomainCacheTable::trigger_cleanup() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   _dead_entries = true;
   Service_lock->notify_all();
 }
--- a/src/hotspot/share/classfile/stringTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/stringTable.cpp	Fri May 03 14:59:32 2019 -0400
@@ -242,7 +242,7 @@
 }
 
 void StringTable::trigger_concurrent_work() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   the_table()->_has_work = true;
   Service_lock->notify_all();
 }
--- a/src/hotspot/share/classfile/symbolTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/symbolTable.cpp	Fri May 03 14:59:32 2019 -0400
@@ -150,7 +150,7 @@
 
 void SymbolTable::delete_symbol(Symbol* sym) {
   if (sym->refcount() == PERM_REFCOUNT) {
-    MutexLockerEx ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
+    MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
     // Deleting permanent symbol should not occur very often (insert race condition),
     // so log it.
     log_trace_symboltable_helper(sym, "Freeing permanent symbol");
@@ -190,7 +190,7 @@
 }
 
 void SymbolTable::trigger_cleanup() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   SymbolTable::the_table()->_has_work = true;
   Service_lock->notify_all();
 }
@@ -208,7 +208,7 @@
     assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
   } else {
     // Allocate to global arena
-    MutexLockerEx ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
+    MutexLocker ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
     sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT);
   }
   return sym;
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Fri May 03 14:59:32 2019 -0400
@@ -86,9 +86,6 @@
 #if INCLUDE_CDS
 #include "classfile/systemDictionaryShared.hpp"
 #endif
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 #if INCLUDE_JFR
 #include "jfr/jfr.hpp"
 #endif
@@ -1824,10 +1821,10 @@
     // First, mark for unload all ClassLoaderData referencing a dead class loader.
     unloading_occurred = ClassLoaderDataGraph::do_unloading();
     if (unloading_occurred) {
-      MutexLockerEx ml2(is_concurrent ? Module_lock : NULL);
+      MutexLocker ml2(is_concurrent ? Module_lock : NULL);
       JFR_ONLY(Jfr::on_unloading_classes();)
 
-      MutexLockerEx ml1(is_concurrent ? SystemDictionary_lock : NULL);
+      MutexLocker ml1(is_concurrent ? SystemDictionary_lock : NULL);
       ClassLoaderDataGraph::clean_module_and_package_info();
       constraints()->purge_loader_constraints();
       resolution_errors()->purge_resolution_errors();
@@ -1922,13 +1919,6 @@
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   InstanceKlass** klassp = &_well_known_klasses[id];
 
-
-#if INCLUDE_JVMCI
-  if (id >= FIRST_JVMCI_WKID) {
-    assert(EnableJVMCI, "resolve JVMCI classes only when EnableJVMCI is true");
-  }
-#endif
-
   if ((*klassp) == NULL) {
     Klass* k = resolve_or_fail(symbol, true, CHECK_0);
     (*klassp) = InstanceKlass::cast(k);
@@ -2017,7 +2007,7 @@
   WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
   resolve_wk_klasses_until(jsr292_group_start, scan, CHECK);
   resolve_wk_klasses_through(jsr292_group_end, scan, CHECK);
-  WKID last = NOT_JVMCI(WKID_LIMIT) JVMCI_ONLY(FIRST_JVMCI_WKID);
+  WKID last = WKID_LIMIT;
   resolve_wk_klasses_until(last, scan, CHECK);
 
   _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
@@ -2750,106 +2740,61 @@
   return Handle(THREAD, (oop) result.get_jobject());
 }
 
-// Ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry
-Handle SystemDictionary::link_dynamic_constant(Klass* caller,
-                                               int condy_index,
-                                               Handle bootstrap_specifier,
-                                               Symbol* name,
-                                               Symbol* type,
-                                               TRAPS) {
-  Handle empty;
-  Handle bsm, info;
-  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
-    bsm = bootstrap_specifier;
-  } else {
-    assert(bootstrap_specifier->is_objArray(), "");
-    objArrayOop args = (objArrayOop) bootstrap_specifier();
-    assert(args->length() == 2, "");
-    bsm  = Handle(THREAD, args->obj_at(0));
-    info = Handle(THREAD, args->obj_at(1));
-  }
-  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
-            "caller must supply a valid BSM");
+// Ask Java to run a bootstrap method, in order to create a dynamic call site
+// while linking an invokedynamic op, or compute a constant for Dynamic_info CP entry
+// with linkage results being stored back into the bootstrap specifier.
+void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS) {
+  // Resolve the bootstrap specifier, its name, type, and static arguments
+  bootstrap_specifier.resolve_bsm(CHECK);
 
   // This should not happen.  JDK code should take care of that.
-  if (caller == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty);
+  if (bootstrap_specifier.caller() == NULL || bootstrap_specifier.type_arg().is_null()) {
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "Invalid bootstrap method invocation with no caller or type argument");
+  }
+
+  bool is_indy = bootstrap_specifier.is_method_call();
+  objArrayHandle appendix_box;
+  if (is_indy) {
+    // Some method calls may require an appendix argument.  Arrange to receive it.
+    appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK);
+    assert(appendix_box->obj_at(0) == NULL, "");
   }
 
-  Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
-
-  // Resolve the constant type in the context of the caller class
-  Handle type_mirror = find_java_mirror_for_type(type, caller, SignatureStream::NCDFError,
-                                                 CHECK_(empty));
-
-  // call java.lang.invoke.MethodHandleNatives::linkConstantDyanmic(caller, condy_index, bsm, type, info)
+  // call condy: java.lang.invoke.MethodHandleNatives::linkDynamicConstant(caller, condy_index, bsm, type, info)
+  //       indy: java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix)
   JavaCallArguments args;
-  args.push_oop(Handle(THREAD, caller->java_mirror()));
-  args.push_int(condy_index);
-  args.push_oop(bsm);
-  args.push_oop(constant_name);
-  args.push_oop(type_mirror);
-  args.push_oop(info);
+  args.push_oop(Handle(THREAD, bootstrap_specifier.caller_mirror()));
+  args.push_int(bootstrap_specifier.bss_index());
+  args.push_oop(bootstrap_specifier.bsm());
+  args.push_oop(bootstrap_specifier.name_arg());
+  args.push_oop(bootstrap_specifier.type_arg());
+  args.push_oop(bootstrap_specifier.arg_values());
+  if (is_indy) {
+    args.push_oop(appendix_box);
+  }
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result,
                          SystemDictionary::MethodHandleNatives_klass(),
-                         vmSymbols::linkDynamicConstant_name(),
-                         vmSymbols::linkDynamicConstant_signature(),
-                         &args, CHECK_(empty));
-
-  return Handle(THREAD, (oop) result.get_jobject());
-}
+                         is_indy ? vmSymbols::linkCallSite_name() : vmSymbols::linkDynamicConstant_name(),
+                         is_indy ? vmSymbols::linkCallSite_signature() : vmSymbols::linkDynamicConstant_signature(),
+                         &args, CHECK);
 
-// Ask Java code to find or construct a java.lang.invoke.CallSite for the given
-// name and signature, as interpreted relative to the given class loader.
-methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller,
-                                                              int indy_index,
-                                                              Handle bootstrap_specifier,
-                                                              Symbol* name,
-                                                              Symbol* type,
-                                                              Handle *appendix_result,
-                                                              TRAPS) {
-  methodHandle empty;
-  Handle bsm, info;
-  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
-    bsm = bootstrap_specifier;
+  Handle value(THREAD, (oop) result.get_jobject());
+  if (is_indy) {
+    Handle appendix;
+    methodHandle method = unpack_method_and_appendix(value,
+                                                     bootstrap_specifier.caller(),
+                                                     appendix_box,
+                                                     &appendix, CHECK);
+    bootstrap_specifier.set_resolved_method(method, appendix);
   } else {
-    objArrayOop args = (objArrayOop) bootstrap_specifier();
-    assert(args->length() == 2, "");
-    bsm  = Handle(THREAD, args->obj_at(0));
-    info = Handle(THREAD, args->obj_at(1));
-  }
-  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
-            "caller must supply a valid BSM");
-
-  Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
-  Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
-
-  // This should not happen.  JDK code should take care of that.
-  if (caller == NULL || method_type.is_null()) {
-    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
+    bootstrap_specifier.set_resolved_value(value);
   }
 
-  objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty));
-  assert(appendix_box->obj_at(0) == NULL, "");
-
-  // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix)
-  JavaCallArguments args;
-  args.push_oop(Handle(THREAD, caller->java_mirror()));
-  args.push_int(indy_index);
-  args.push_oop(bsm);
-  args.push_oop(method_name);
-  args.push_oop(method_type);
-  args.push_oop(info);
-  args.push_oop(appendix_box);
-  JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result,
-                         SystemDictionary::MethodHandleNatives_klass(),
-                         vmSymbols::linkCallSite_name(),
-                         vmSymbols::linkCallSite_signature(),
-                         &args, CHECK_(empty));
-  Handle mname(THREAD, (oop) result.get_jobject());
-  return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
+  // sanity check
+  assert(bootstrap_specifier.is_resolved() ||
+         (bootstrap_specifier.is_method_call() &&
+          bootstrap_specifier.resolved_method().not_null()), "bootstrap method call failed");
 }
 
 // Protection domain cache table handling
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,6 @@
 #define SHARE_CLASSFILE_SYSTEMDICTIONARY_HPP
 
 #include "classfile/classLoaderData.hpp"
-#include "jvmci/systemDictionary_jvmci.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/java.hpp"
@@ -74,6 +73,7 @@
 // of placeholders must hold the SystemDictionary_lock.
 //
 
+class BootstrapInfo;
 class ClassFileStream;
 class Dictionary;
 class PlaceholderTable;
@@ -214,13 +214,11 @@
   do_klass(Integer_klass,                               java_lang_Integer                                     ) \
   do_klass(Long_klass,                                  java_lang_Long                                        ) \
                                                                                                                 \
-  /* JVMCI classes. These are loaded on-demand. */                                                              \
-  JVMCI_WK_KLASSES_DO(do_klass)                                                                                 \
-                                                                                                                \
   /*end*/
 
 
 class SystemDictionary : AllStatic {
+  friend class BootstrapInfo;
   friend class VMStructs;
   friend class SystemDictionaryHandles;
 
@@ -234,11 +232,6 @@
 
     WKID_LIMIT,
 
-#if INCLUDE_JVMCI
-    FIRST_JVMCI_WKID = WK_KLASS_ENUM_NAME(JVMCI_klass),
-    LAST_JVMCI_WKID  = WK_KLASS_ENUM_NAME(Value_klass),
-#endif
-
     FIRST_WKID = NO_WKID + 1
   };
 
@@ -531,21 +524,7 @@
                                                TRAPS);
 
   // ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry
-  static Handle    link_dynamic_constant(Klass* caller,
-                                         int condy_index,
-                                         Handle bootstrap_specifier,
-                                         Symbol* name,
-                                         Symbol* type,
-                                         TRAPS);
-
-  // ask Java to create a dynamic call site, while linking an invokedynamic op
-  static methodHandle find_dynamic_call_site_invoker(Klass* caller,
-                                                     int indy_index,
-                                                     Handle bootstrap_method,
-                                                     Symbol* name,
-                                                     Symbol* type,
-                                                     Handle *appendix_result,
-                                                     TRAPS);
+  static void      invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS);
 
   // Record the error when the first attempt to resolve a reference from a constant
   // pool entry to a class fails.
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Fri May 03 14:59:32 2019 -0400
@@ -358,8 +358,7 @@
   template(destroyed_name,                            "destroyed")                                \
   template(nthreads_name,                             "nthreads")                                 \
   template(ngroups_name,                              "ngroups")                                  \
-  template(shutdown_method_name,                      "shutdown")                                 \
-  template(bootstrapFinished_method_name,             "bootstrapFinished")                        \
+  template(shutdown_name,                             "shutdown")                                 \
   template(finalize_method_name,                      "finalize")                                 \
   template(reference_lock_name,                       "lock")                                     \
   template(reference_discovered_name,                 "discovered")                               \
--- a/src/hotspot/share/code/codeBlob.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/codeBlob.cpp	Fri May 03 14:59:32 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
@@ -227,7 +227,7 @@
   size += align_up(buffer_size, oopSize);
   assert(name != NULL, "must provide a name");
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) BufferBlob(name, size);
   }
   // Track memory usage statistic after releasing CodeCache_lock
@@ -248,7 +248,7 @@
   unsigned int size = CodeBlob::allocation_size(cb, sizeof(BufferBlob));
   assert(name != NULL, "must provide a name");
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) BufferBlob(name, size, cb);
   }
   // Track memory usage statistic after releasing CodeCache_lock
@@ -265,7 +265,7 @@
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   blob->flush();
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::free((RuntimeBlob*)blob);
   }
   // Track memory usage statistic after releasing CodeCache_lock
@@ -287,7 +287,7 @@
   AdapterBlob* blob = NULL;
   unsigned int size = CodeBlob::allocation_size(cb, sizeof(AdapterBlob));
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) AdapterBlob(size, cb);
   }
   // Track memory usage statistic after releasing CodeCache_lock
@@ -310,7 +310,7 @@
   size += align_up(buffer_size, oopSize);
   assert(name != NULL, "must provide a name");
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) VtableBlob(name, size);
   }
   // Track memory usage statistic after releasing CodeCache_lock
@@ -331,7 +331,7 @@
   size = CodeBlob::align_code_offset(size);
   size += align_up(buffer_size, oopSize);
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) MethodHandlesAdapterBlob(size);
     if (blob == NULL) {
       vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for method handle adapter blob");
@@ -369,7 +369,7 @@
   RuntimeStub* stub = NULL;
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     unsigned int size = CodeBlob::allocation_size(cb, sizeof(RuntimeStub));
     stub = new (size) RuntimeStub(stub_name, cb, size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments);
   }
@@ -428,7 +428,7 @@
   DeoptimizationBlob* blob = NULL;
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     unsigned int size = CodeBlob::allocation_size(cb, sizeof(DeoptimizationBlob));
     blob = new (size) DeoptimizationBlob(cb,
                                          size,
@@ -467,7 +467,7 @@
   UncommonTrapBlob* blob = NULL;
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     unsigned int size = CodeBlob::allocation_size(cb, sizeof(UncommonTrapBlob));
     blob = new (size) UncommonTrapBlob(cb, size, oop_maps, frame_size);
   }
@@ -503,7 +503,7 @@
   ExceptionBlob* blob = NULL;
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     unsigned int size = CodeBlob::allocation_size(cb, sizeof(ExceptionBlob));
     blob = new (size) ExceptionBlob(cb, size, oop_maps, frame_size);
   }
@@ -538,7 +538,7 @@
   SafepointBlob* blob = NULL;
   ThreadInVMfromUnknown __tiv;  // get to VM state in case we block on CodeCache_lock
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     unsigned int size = CodeBlob::allocation_size(cb, sizeof(SafepointBlob));
     blob = new (size) SafepointBlob(cb, size, oop_maps, frame_size);
   }
--- a/src/hotspot/share/code/codeCache.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/codeCache.cpp	Fri May 03 14:59:32 2019 -0400
@@ -531,7 +531,7 @@
           return allocate(size, type, orig_code_blob_type);
         }
       }
-      MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexUnlocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       CompileBroker::handle_full_code_cache(orig_code_blob_type);
       return NULL;
     }
@@ -792,7 +792,7 @@
 }
 
 void CodeCache::verify_oops() {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   VerifyOopClosure voc;
   NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
   while(iter.next()) {
@@ -989,7 +989,7 @@
 NOT_PRODUCT(static elapsedTimer dependentCheckTime;)
 
 int CodeCache::mark_for_deoptimization(KlassDepChange& changes) {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   int number_of_marked_CodeBlobs = 0;
 
   // search the hierarchy looking for nmethods which are affected by the loading of this class
@@ -1154,7 +1154,7 @@
 
 // Deoptimize all methods
 void CodeCache::mark_all_nmethods_for_deoptimization() {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   CompiledMethodIterator iter(CompiledMethodIterator::only_alive_and_not_unloading);
   while(iter.next()) {
     CompiledMethod* nm = iter.method();
@@ -1165,7 +1165,7 @@
 }
 
 int CodeCache::mark_for_deoptimization(Method* dependee) {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   int number_of_marked_CodeBlobs = 0;
 
   CompiledMethodIterator iter(CompiledMethodIterator::only_alive_and_not_unloading);
@@ -1289,7 +1289,7 @@
     stringStream s;
     // Dump code cache into a buffer before locking the tty.
     {
-      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       print_summary(&s);
     }
     {
@@ -1557,7 +1557,7 @@
 }
 
 void CodeCache::print_codelist(outputStream* st) {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
   CompiledMethodIterator iter(CompiledMethodIterator::only_alive_and_not_unloading);
   while (iter.next()) {
@@ -1572,7 +1572,7 @@
 }
 
 void CodeCache::print_layout(outputStream* st) {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   ResourceMark rm;
   print_summary(st, true);
 }
--- a/src/hotspot/share/code/icBuffer.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/icBuffer.cpp	Fri May 03 14:59:32 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
@@ -258,7 +258,7 @@
 // not safe to free them until them since they might be visible to
 // another thread.
 void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {
-  MutexLockerEx mex(InlineCacheBuffer_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mex(InlineCacheBuffer_lock, Mutex::_no_safepoint_check_flag);
   icholder->set_next(_pending_released);
   _pending_released = icholder;
   _pending_count++;
--- a/src/hotspot/share/code/nmethod.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/nmethod.cpp	Fri May 03 14:59:32 2019 -0400
@@ -64,7 +64,7 @@
 #include "utilities/resourceHash.hpp"
 #include "utilities/xmlstream.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #endif
 
 #ifdef DTRACE_ENABLED
@@ -112,6 +112,10 @@
   int dependencies_size;
   int handler_table_size;
   int nul_chk_table_size;
+#if INCLUDE_JVMCI
+  int speculations_size;
+  int jvmci_data_size;
+#endif
   int oops_size;
   int metadata_size;
 
@@ -129,6 +133,10 @@
     dependencies_size   += nm->dependencies_size();
     handler_table_size  += nm->handler_table_size();
     nul_chk_table_size  += nm->nul_chk_table_size();
+#if INCLUDE_JVMCI
+    speculations_size   += nm->speculations_size();
+    jvmci_data_size     += nm->jvmci_data_size();
+#endif
   }
   void print_nmethod_stats(const char* name) {
     if (nmethod_count == 0)  return;
@@ -146,6 +154,10 @@
     if (dependencies_size != 0)   tty->print_cr(" dependencies   = %d", dependencies_size);
     if (handler_table_size != 0)  tty->print_cr(" handler table  = %d", handler_table_size);
     if (nul_chk_table_size != 0)  tty->print_cr(" nul chk table  = %d", nul_chk_table_size);
+#if INCLUDE_JVMCI
+    if (speculations_size != 0)   tty->print_cr(" speculations   = %d", speculations_size);
+    if (jvmci_data_size != 0)     tty->print_cr(" JVMCI data     = %d", jvmci_data_size);
+#endif
   }
 };
 
@@ -426,11 +438,6 @@
 #if INCLUDE_RTM_OPT
   _rtm_state               = NoRTM;
 #endif
-#if INCLUDE_JVMCI
-  _jvmci_installed_code   = NULL;
-  _speculation_log        = NULL;
-  _jvmci_installed_code_triggers_invalidation = false;
-#endif
 }
 
 nmethod* nmethod::new_native_nmethod(const methodHandle& method,
@@ -446,7 +453,7 @@
   // create nmethod
   nmethod* nm = NULL;
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     int native_nmethod_size = CodeBlob::allocation_size(code_buffer, sizeof(nmethod));
     CodeOffsets offsets;
     offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
@@ -483,8 +490,11 @@
   AbstractCompiler* compiler,
   int comp_level
 #if INCLUDE_JVMCI
-  , jweak installed_code,
-  jweak speculationLog
+  , char* speculations,
+  int speculations_len,
+  int nmethod_mirror_index,
+  const char* nmethod_mirror_name,
+  FailedSpeculation** failed_speculations
 #endif
 )
 {
@@ -492,13 +502,20 @@
   code_buffer->finalize_oop_references(method);
   // create nmethod
   nmethod* nm = NULL;
-  { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+#if INCLUDE_JVMCI
+    int jvmci_data_size = !compiler->is_jvmci() ? 0 : JVMCINMethodData::compute_size(nmethod_mirror_name);
+#endif
     int nmethod_size =
       CodeBlob::allocation_size(code_buffer, sizeof(nmethod))
       + adjust_pcs_size(debug_info->pcs_size())
       + align_up((int)dependencies->size_in_bytes(), oopSize)
       + align_up(handler_table->size_in_bytes()    , oopSize)
       + align_up(nul_chk_table->size_in_bytes()    , oopSize)
+#if INCLUDE_JVMCI
+      + align_up(speculations_len                  , oopSize)
+      + align_up(jvmci_data_size                   , oopSize)
+#endif
       + align_up(debug_info->data_size()           , oopSize);
 
     nm = new (nmethod_size, comp_level)
@@ -510,12 +527,19 @@
             compiler,
             comp_level
 #if INCLUDE_JVMCI
-            , installed_code,
-            speculationLog
+            , speculations,
+            speculations_len,
+            jvmci_data_size
 #endif
             );
 
     if (nm != NULL) {
+#if INCLUDE_JVMCI
+      if (compiler->is_jvmci()) {
+        // Initialize the JVMCINMethodData object inlined into nm
+        nm->jvmci_nmethod_data()->initialize(nmethod_mirror_index, nmethod_mirror_name, failed_speculations);
+      }
+#endif
       // To make dependency checking during class loading fast, record
       // the nmethod dependencies in the classes it is dependent on.
       // This allows the dependency checking code to simply walk the
@@ -591,7 +615,13 @@
     _dependencies_offset     = _scopes_pcs_offset;
     _handler_table_offset    = _dependencies_offset;
     _nul_chk_table_offset    = _handler_table_offset;
+#if INCLUDE_JVMCI
+    _speculations_offset     = _nul_chk_table_offset;
+    _jvmci_data_offset       = _speculations_offset;
+    _nmethod_end_offset      = _jvmci_data_offset;
+#else
     _nmethod_end_offset      = _nul_chk_table_offset;
+#endif
     _compile_id              = compile_id;
     _comp_level              = CompLevel_none;
     _entry_point             = code_begin()          + offsets->value(CodeOffsets::Entry);
@@ -667,8 +697,9 @@
   AbstractCompiler* compiler,
   int comp_level
 #if INCLUDE_JVMCI
-  , jweak installed_code,
-  jweak speculation_log
+  , char* speculations,
+  int speculations_len,
+  int jvmci_data_size
 #endif
   )
   : CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
@@ -697,15 +728,6 @@
     set_ctable_begin(header_begin() + _consts_offset);
 
 #if INCLUDE_JVMCI
-    _jvmci_installed_code = installed_code;
-    _speculation_log = speculation_log;
-    oop obj = JNIHandles::resolve(installed_code);
-    if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
-      _jvmci_installed_code_triggers_invalidation = false;
-    } else {
-      _jvmci_installed_code_triggers_invalidation = true;
-    }
-
     if (compiler->is_jvmci()) {
       // JVMCI might not produce any stub sections
       if (offsets->value(CodeOffsets::Exceptions) != -1) {
@@ -735,10 +757,10 @@
       _deopt_mh_handler_begin  = (address) this + _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
     } else {
       _deopt_mh_handler_begin  = NULL;
+    }
 #if INCLUDE_JVMCI
     }
 #endif
-    }
     if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
       _unwind_handler_offset = code_offset()         + offsets->value(CodeOffsets::UnwindHandler);
     } else {
@@ -753,7 +775,13 @@
     _dependencies_offset     = _scopes_pcs_offset    + adjust_pcs_size(debug_info->pcs_size());
     _handler_table_offset    = _dependencies_offset  + align_up((int)dependencies->size_in_bytes (), oopSize);
     _nul_chk_table_offset    = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize);
+#if INCLUDE_JVMCI
+    _speculations_offset     = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize);
+    _jvmci_data_offset       = _speculations_offset  + align_up(speculations_len, oopSize);
+    _nmethod_end_offset      = _jvmci_data_offset    + align_up(jvmci_data_size, oopSize);
+#else
     _nmethod_end_offset      = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize);
+#endif
     _entry_point             = code_begin()          + offsets->value(CodeOffsets::Entry);
     _verified_entry_point    = code_begin()          + offsets->value(CodeOffsets::Verified_Entry);
     _osr_entry_point         = code_begin()          + offsets->value(CodeOffsets::OSR_Entry);
@@ -779,6 +807,13 @@
     handler_table->copy_to(this);
     nul_chk_table->copy_to(this);
 
+#if INCLUDE_JVMCI
+    // Copy speculations to nmethod
+    if (speculations_size() != 0) {
+      memcpy(speculations_begin(), speculations, speculations_len);
+    }
+#endif
+
     // we use the information of entry points to find out if a method is
     // static or non static
     assert(compiler->is_c2() || compiler->is_jvmci() ||
@@ -798,13 +833,14 @@
     log->print(" level='%d'", comp_level());
   }
 #if INCLUDE_JVMCI
-    char buffer[O_BUFLEN];
-    char* jvmci_name = jvmci_installed_code_name(buffer, O_BUFLEN);
+  if (jvmci_nmethod_data() != NULL) {
+    const char* jvmci_name = jvmci_nmethod_data()->name();
     if (jvmci_name != NULL) {
-      log->print(" jvmci_installed_code_name='");
+      log->print(" jvmci_mirror_name='");
       log->text("%s", jvmci_name);
       log->print("'");
     }
+  }
 #endif
 }
 
@@ -1103,7 +1139,7 @@
 
   // Unregister must be done before the state change
   {
-    MutexLockerEx ml(SafepointSynchronize::is_at_safepoint() ? NULL : CodeCache_lock,
+    MutexLocker ml(SafepointSynchronize::is_at_safepoint() ? NULL : CodeCache_lock,
                      Mutex::_no_safepoint_check_flag);
     Universe::heap()->unregister_nmethod(this);
     CodeCache::unregister_old_nmethod(this);
@@ -1115,13 +1151,6 @@
   // Log the unloading.
   log_state_change();
 
-#if INCLUDE_JVMCI
-  // The method can only be unloaded after the pointer to the installed code
-  // Java wrapper is no longer alive. Here we need to clear out this weak
-  // reference to the dead object.
-  maybe_invalidate_installed_code();
-#endif
-
   // The Method* is gone at this point
   assert(_method == NULL, "Tautology");
 
@@ -1134,6 +1163,15 @@
   // concurrent nmethod unloading. Therefore, there is no need for
   // acquire on the loader side.
   OrderAccess::release_store(&_state, (signed char)unloaded);
+
+#if INCLUDE_JVMCI
+  // Clear the link between this nmethod and a HotSpotNmethod mirror
+  JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
+  if (nmethod_data != NULL) {
+    nmethod_data->invalidate_nmethod_mirror(this);
+    nmethod_data->clear_nmethod_mirror(this);
+  }
+#endif
 }
 
 void nmethod::invalidate_osr_method() {
@@ -1222,7 +1260,7 @@
     }
 
     // Enter critical section.  Does not block for safepoint.
-    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
 
     if (_state == state) {
       // another thread already performed this transition so nothing
@@ -1265,13 +1303,18 @@
     // Log the transition once
     log_state_change();
 
-    // Invalidate while holding the patching lock
-    JVMCI_ONLY(maybe_invalidate_installed_code());
-
     // Remove nmethod from method.
     unlink_from_method(false /* already owns Patching_lock */);
   } // leave critical region under Patching_lock
 
+#if INCLUDE_JVMCI
+  // Invalidate can't occur while holding the Patching lock
+  JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
+  if (nmethod_data != NULL) {
+    nmethod_data->invalidate_nmethod_mirror(this);
+  }
+#endif
+
 #ifdef ASSERT
   if (is_osr_method() && method() != NULL) {
     // Make sure osr nmethod is invalidated, i.e. not on the list
@@ -1289,7 +1332,7 @@
       // Flushing dependencies must be done before any possible
       // safepoint can sneak in, otherwise the oops used by the
       // dependency logic could have become stale.
-      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       if (nmethod_needs_unregister) {
         Universe::heap()->unregister_nmethod(this);
         CodeCache::unregister_old_nmethod(this);
@@ -1297,6 +1340,14 @@
       flush_dependencies(/*delete_immediately*/true);
     }
 
+#if INCLUDE_JVMCI
+    // Now that the nmethod has been unregistered, it's
+    // safe to clear the HotSpotNmethod mirror oop.
+    if (nmethod_data != NULL) {
+      nmethod_data->clear_nmethod_mirror(this);
+    }
+#endif
+
     // Clear ICStubs to prevent back patching stubs of zombie or flushed
     // nmethods during the next safepoint (see ICStub::finalize), as well
     // as to free up CompiledICHolder resources.
@@ -1324,7 +1375,7 @@
     assert(state == not_entrant, "other cases may need to be handled differently");
   }
 
-  if (TraceCreateZombies) {
+  if (TraceCreateZombies && state == zombie) {
     ResourceMark m;
     tty->print_cr("nmethod <" INTPTR_FORMAT "> %s code made %s", p2i(this), this->method() ? this->method()->name_and_sig_as_C_string() : "null", (state == not_entrant) ? "not entrant" : "zombie");
   }
@@ -1334,7 +1385,7 @@
 }
 
 void nmethod::flush() {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   // Note that there are no valid oops in the nmethod anymore.
   assert(!is_osr_method() || is_unloaded() || is_zombie(),
          "osr nmethod must be unloaded or zombie before flushing");
@@ -1362,11 +1413,6 @@
     ec = next;
   }
 
-#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");
-#endif
-
   Universe::heap()->flush_nmethod(this);
 
   CodeBlob::flush();
@@ -1452,7 +1498,7 @@
 
   if (JvmtiExport::should_post_compiled_method_load()) {
     // Let the Service thread (which is a real Java thread) post the event
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     JvmtiDeferredEventQueue::enqueue(
       JvmtiDeferredEvent::compiled_method_load_event(this));
   }
@@ -1490,7 +1536,7 @@
     JvmtiDeferredEvent event =
       JvmtiDeferredEvent::compiled_method_unload_event(this,
           _jmethod_id, insts_begin());
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     JvmtiDeferredEventQueue::enqueue(event);
   }
 
@@ -1660,17 +1706,6 @@
   if (is_unloading()) {
     make_unloaded();
   } else {
-#if INCLUDE_JVMCI
-    if (_jvmci_installed_code != NULL) {
-      if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
-        if (_jvmci_installed_code_triggers_invalidation) {
-          make_not_entrant();
-        }
-        clear_jvmci_installed_code();
-      }
-    }
-#endif
-
     guarantee(unload_nmethod_caches(unloading_occurred),
               "Should not need transition stubs");
   }
@@ -2066,7 +2101,7 @@
   if (cm->is_aot()) return;  // FIXME: Revisit once _lock_count is added to aot_method
   nmethod* nm = cm->as_nmethod();
   Atomic::inc(&nm->_lock_count);
-  assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method");
+  assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method: %p", nm);
 }
 
 void nmethodLocker::unlock_nmethod(CompiledMethod* cm) {
@@ -2275,6 +2310,16 @@
                                               p2i(nul_chk_table_begin()),
                                               p2i(nul_chk_table_end()),
                                               nul_chk_table_size());
+#if INCLUDE_JVMCI
+  if (speculations_size () > 0) tty->print_cr(" speculations   [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
+                                              p2i(speculations_begin()),
+                                              p2i(speculations_end()),
+                                              speculations_size());
+  if (jvmci_data_size   () > 0) tty->print_cr(" JVMCI data     [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
+                                              p2i(jvmci_data_begin()),
+                                              p2i(jvmci_data_end()),
+                                              jvmci_data_size());
+#endif
 }
 
 #ifndef PRODUCT
@@ -2857,115 +2902,18 @@
 #endif // !PRODUCT
 
 #if INCLUDE_JVMCI
-void nmethod::clear_jvmci_installed_code() {
-  assert_locked_or_safepoint(Patching_lock);
-  if (_jvmci_installed_code != NULL) {
-    JNIHandles::destroy_weak_global(_jvmci_installed_code);
-    _jvmci_installed_code = NULL;
-  }
-}
-
-void nmethod::clear_speculation_log() {
-  assert_locked_or_safepoint(Patching_lock);
-  if (_speculation_log != NULL) {
-    JNIHandles::destroy_weak_global(_speculation_log);
-    _speculation_log = NULL;
-  }
-}
-
-void nmethod::maybe_invalidate_installed_code() {
-  if (!is_compiled_by_jvmci()) {
-    return;
-  }
-
-  assert(Patching_lock->is_locked() ||
-         SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
-  oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
-  if (installed_code != NULL) {
-    // Update the values in the InstalledCode instance if it still refers to this nmethod
-    nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
-    if (nm == this) {
-      if (!is_alive() || is_unloading()) {
-        // Break the link between nmethod and InstalledCode such that the nmethod
-        // can subsequently be flushed safely.  The link must be maintained while
-        // the method could have live activations since invalidateInstalledCode
-        // might want to invalidate all existing activations.
-        InstalledCode::set_address(installed_code, 0);
-        InstalledCode::set_entryPoint(installed_code, 0);
-      } else if (is_not_entrant()) {
-        // Remove the entry point so any invocation will fail but keep
-        // the address link around that so that existing activations can
-        // be invalidated.
-        InstalledCode::set_entryPoint(installed_code, 0);
-      }
-    }
-  }
-  if (!is_alive() || is_unloading()) {
-    // Clear these out after the nmethod has been unregistered and any
-    // updates to the InstalledCode instance have been performed.
-    clear_jvmci_installed_code();
-    clear_speculation_log();
+void nmethod::update_speculation(JavaThread* thread) {
+  jlong speculation = thread->pending_failed_speculation();
+  if (speculation != 0) {
+    guarantee(jvmci_nmethod_data() != NULL, "failed speculation in nmethod without failed speculation list");
+    jvmci_nmethod_data()->add_failed_speculation(this, speculation);
+    thread->set_pending_failed_speculation(0);
   }
 }
 
-void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
-  if (installedCode() == NULL) {
-    THROW(vmSymbols::java_lang_NullPointerException());
-  }
-  jlong nativeMethod = InstalledCode::address(installedCode);
-  nmethod* nm = (nmethod*)nativeMethod;
-  if (nm == NULL) {
-    // Nothing to do
-    return;
-  }
-
-  nmethodLocker nml(nm);
-#ifdef ASSERT
-  {
-    MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-    // This relationship can only be checked safely under a lock
-    assert(!nm->is_alive() || nm->is_unloading() || nm->jvmci_installed_code() == installedCode(), "sanity check");
-  }
-#endif
-
-  if (nm->is_alive()) {
-    // Invalidating the InstalledCode means we want the nmethod
-    // to be deoptimized.
-    nm->mark_for_deoptimization();
-    VM_Deoptimize op;
-    VMThread::execute(&op);
-  }
-
-  // Multiple threads could reach this point so we now need to
-  // lock and re-check the link to the nmethod so that only one
-  // thread clears it.
-  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-  if (InstalledCode::address(installedCode) == nativeMethod) {
-      InstalledCode::set_address(installedCode, 0);
-  }
-}
-
-oop nmethod::jvmci_installed_code() {
-  return JNIHandles::resolve(_jvmci_installed_code);
-}
-
-oop nmethod::speculation_log() {
-  return JNIHandles::resolve(_speculation_log);
-}
-
-char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) const {
-  if (!this->is_compiled_by_jvmci()) {
-    return NULL;
-  }
-  oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
-  if (installed_code != NULL) {
-    oop installed_code_name = NULL;
-    if (installed_code->is_a(InstalledCode::klass())) {
-      installed_code_name = InstalledCode::name(installed_code);
-    }
-    if (installed_code_name != NULL) {
-      return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen);
-    }
+const char* nmethod::jvmci_name() {
+  if (jvmci_nmethod_data() != NULL) {
+    return jvmci_nmethod_data()->name();
   }
   return NULL;
 }
--- a/src/hotspot/share/code/nmethod.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/nmethod.hpp	Fri May 03 14:59:32 2019 -0400
@@ -51,37 +51,28 @@
 //  - handler entry point array
 //  [Implicit Null Pointer exception table]
 //  - implicit null table array
+//  [Speculations]
+//  - encoded speculations array
+//  [JVMCINMethodData]
+//  - meta data for JVMCI compiled nmethod
+
+#if INCLUDE_JVMCI
+class FailedSpeculation;
+class JVMCINMethodData;
+#endif
 
 class nmethod : public CompiledMethod {
   friend class VMStructs;
   friend class JVMCIVMStructs;
   friend class NMethodSweeper;
   friend class CodeCache;  // scavengable oops
+  friend class JVMCINMethodData;
  private:
 
   // Shared fields for all nmethod's
   int       _entry_bci;        // != InvocationEntryBci if this nmethod is an on-stack replacement method
   jmethodID _jmethod_id;       // Cache of method()->jmethod_id()
 
-#if INCLUDE_JVMCI
-  // A weak reference to an InstalledCode object associated with
-  // this nmethod.
-  jweak     _jvmci_installed_code;
-
-  // A weak reference to a SpeculationLog object associated with
-  // this nmethod.
-  jweak     _speculation_log;
-
-  // Determines whether this nmethod is unloaded when the
-  // referent in _jvmci_installed_code is cleared. This
-  // will be false if the referent is initialized to a
-  // HotSpotNMethod object whose isDefault field is true.
-  // That is, installed code other than a "default"
-  // HotSpotNMethod causes nmethod unloading.
-  // This field is ignored once _jvmci_installed_code is NULL.
-  bool _jvmci_installed_code_triggers_invalidation;
-#endif
-
   // To support simple linked-list chaining of nmethods:
   nmethod*  _osr_link;         // from InstanceKlass::osr_nmethods_head
 
@@ -107,6 +98,10 @@
   int _dependencies_offset;
   int _handler_table_offset;
   int _nul_chk_table_offset;
+#if INCLUDE_JVMCI
+  int _speculations_offset;
+  int _jvmci_data_offset;
+#endif
   int _nmethod_end_offset;
 
   int code_offset() const { return (address) code_begin() - header_begin(); }
@@ -207,8 +202,9 @@
           AbstractCompiler* compiler,
           int comp_level
 #if INCLUDE_JVMCI
-          , jweak installed_code,
-          jweak speculation_log
+          , char* speculations,
+          int speculations_len,
+          int jvmci_data_size
 #endif
           );
 
@@ -251,8 +247,11 @@
                               AbstractCompiler* compiler,
                               int comp_level
 #if INCLUDE_JVMCI
-                              , jweak installed_code = NULL,
-                              jweak speculation_log = NULL
+                              , char* speculations = NULL,
+                              int speculations_len = 0,
+                              int nmethod_mirror_index = -1,
+                              const char* nmethod_mirror_name = NULL,
+                              FailedSpeculation** failed_speculations = NULL
 #endif
   );
 
@@ -299,12 +298,24 @@
   address handler_table_begin   () const          { return           header_begin() + _handler_table_offset ; }
   address handler_table_end     () const          { return           header_begin() + _nul_chk_table_offset ; }
   address nul_chk_table_begin   () const          { return           header_begin() + _nul_chk_table_offset ; }
+#if INCLUDE_JVMCI
+  address nul_chk_table_end     () const          { return           header_begin() + _speculations_offset  ; }
+  address speculations_begin    () const          { return           header_begin() + _speculations_offset  ; }
+  address speculations_end      () const          { return           header_begin() + _jvmci_data_offset   ; }
+  address jvmci_data_begin      () const          { return           header_begin() + _jvmci_data_offset    ; }
+  address jvmci_data_end        () const          { return           header_begin() + _nmethod_end_offset   ; }
+#else
   address nul_chk_table_end     () const          { return           header_begin() + _nmethod_end_offset   ; }
+#endif
 
   // Sizes
   int oops_size         () const                  { return (address)  oops_end         () - (address)  oops_begin         (); }
   int metadata_size     () const                  { return (address)  metadata_end     () - (address)  metadata_begin     (); }
   int dependencies_size () const                  { return            dependencies_end () -            dependencies_begin (); }
+#if INCLUDE_JVMCI
+  int speculations_size () const                  { return            speculations_end () -            speculations_begin (); }
+  int jvmci_data_size   () const                  { return            jvmci_data_end   () -            jvmci_data_begin   (); }
+#endif
 
   int     oops_count() const { assert(oops_size() % oopSize == 0, "");  return (oops_size() / oopSize) + 1; }
   int metadata_count() const { assert(metadata_size() % wordSize == 0, ""); return (metadata_size() / wordSize) + 1; }
@@ -446,39 +457,19 @@
   void set_method(Method* method) { _method = method; }
 
 #if INCLUDE_JVMCI
-  // Gets the InstalledCode object associated with this nmethod
-  // which may be NULL if this nmethod was not compiled by JVMCI
-  // or the weak reference has been cleared.
-  oop jvmci_installed_code();
+  // Gets the JVMCI name of this nmethod.
+  const char* jvmci_name();
 
-  // Copies the value of the name field in the InstalledCode
-  // object (if any) associated with this nmethod into buf.
-  // Returns the value of buf if it was updated otherwise NULL.
-  char* jvmci_installed_code_name(char* buf, size_t buflen) const;
-
-  // Updates the state of the InstalledCode (if any) associated with
-  // this nmethod based on the current value of _state.
-  void maybe_invalidate_installed_code();
+  // Records the pending failed speculation in the
+  // JVMCI speculation log associated with this nmethod.
+  void update_speculation(JavaThread* thread);
 
-  // Deoptimizes the nmethod (if any) in the address field of a given
-  // InstalledCode object. The address field is zeroed upon return.
-  static void invalidate_installed_code(Handle installed_code, TRAPS);
-
-  // Gets the SpeculationLog object associated with this nmethod
-  // which may be NULL if this nmethod was not compiled by JVMCI
-  // or the weak reference has been cleared.
-  oop speculation_log();
-
- private:
-  // Deletes the weak reference (if any) to the InstalledCode object
-  // associated with this nmethod.
-  void clear_jvmci_installed_code();
-
-  // Deletes the weak reference (if any) to the SpeculationLog object
-  // associated with this nmethod.
-  void clear_speculation_log();
-
- public:
+  // Gets the data specific to a JVMCI compiled method.
+  // This returns a non-NULL value iff this nmethod was
+  // compiled by the JVMCI compiler.
+  JVMCINMethodData* jvmci_nmethod_data() const {
+    return jvmci_data_size() == 0 ? NULL : (JVMCINMethodData*) jvmci_data_begin();
+  }
 #endif
 
  public:
--- a/src/hotspot/share/code/stubs.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/stubs.cpp	Fri May 03 14:59:32 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
@@ -207,7 +207,7 @@
 void StubQueue::verify() {
   // verify only if initialized
   if (_stub_buffer == NULL) return;
-  MutexLockerEx lock(_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(_mutex, Mutex::_no_safepoint_check_flag);
   // verify index boundaries
   guarantee(0 <= _buffer_size, "buffer size must be positive");
   guarantee(0 <= _buffer_limit && _buffer_limit <= _buffer_size , "_buffer_limit out of bounds");
@@ -234,7 +234,7 @@
 
 
 void StubQueue::print() {
-  MutexLockerEx lock(_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(_mutex, Mutex::_no_safepoint_check_flag);
   for (Stub* s = first(); s != NULL; s = next(s)) {
     stub_print(s);
   }
--- a/src/hotspot/share/code/vtableStubs.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/code/vtableStubs.cpp	Fri May 03 14:59:32 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
@@ -125,7 +125,7 @@
 void VtableStubs::initialize() {
   VtableStub::_receiver_location = SharedRuntime::name_for_receiver();
   {
-    MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
     assert(_number_of_vtable_stubs == 0, "potential performance bug: VtableStubs initialized more than once");
     assert(is_power_of_2(N), "N must be a power of 2");
     for (int i = 0; i < N; i++) {
@@ -211,7 +211,7 @@
 
   VtableStub* s;
   {
-    MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
     s = ShareVtableStubs ? lookup(is_vtable_stub, vtable_index) : NULL;
     if (s == NULL) {
       if (is_vtable_stub) {
@@ -271,7 +271,7 @@
 }
 
 VtableStub* VtableStubs::entry_point(address pc) {
-  MutexLockerEx ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(VtableStubs_lock, Mutex::_no_safepoint_check_flag);
   VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset());
   uint hash = VtableStubs::hash(stub->is_vtable_stub(), stub->index());
   VtableStub* s;
--- a/src/hotspot/share/compiler/abstractCompiler.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/abstractCompiler.cpp	Fri May 03 14:59:32 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
@@ -28,14 +28,14 @@
 
 bool AbstractCompiler::should_perform_init() {
   if (_compiler_state != initialized) {
-    MutexLocker only_one(CompileThread_lock);
+    MonitorLocker only_one(CompileThread_lock);
 
     if (_compiler_state == uninitialized) {
       _compiler_state = initializing;
       return true;
     } else {
       while (_compiler_state == initializing) {
-        CompileThread_lock->wait();
+        only_one.wait();
       }
     }
   }
--- a/src/hotspot/share/compiler/abstractCompiler.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/abstractCompiler.hpp	Fri May 03 14:59:32 2019 -0400
@@ -154,9 +154,6 @@
   const bool is_jvmci()                          { return _type == compiler_jvmci; }
   const CompilerType type()                      { return _type; }
 
-  // Extra tests to identify trivial methods for the tiered compilation policy.
-  virtual bool is_trivial(Method* method) { return false; }
-
   // Customization
   virtual void initialize () = 0;
 
--- a/src/hotspot/share/compiler/compileBroker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Fri May 03 14:59:32 2019 -0400
@@ -68,9 +68,8 @@
 #include "c1/c1_Compiler.hpp"
 #endif
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 #include "runtime/vframe.hpp"
 #endif
 #ifdef COMPILER2
@@ -402,7 +401,7 @@
   methodHandle save_method;
   methodHandle save_hot_method;
 
-  MutexLocker locker(MethodCompileQueue_lock);
+  MonitorLocker locker(MethodCompileQueue_lock);
   // If _first is NULL we have no more compile jobs. There are two reasons for
   // having no compile jobs: First, we compiled everything we wanted. Second,
   // we ran out of code cache so compilation has been disabled. In the latter
@@ -423,7 +422,7 @@
     // We need a timed wait here, since compiler threads can exit if compilation
     // is disabled forever. We use 5 seconds wait time; the exiting of compiler threads
     // is not critical and we do not want idle compiler threads to wake up too often.
-    MethodCompileQueue_lock->wait(!Mutex::_no_safepoint_check_flag, 5*1000);
+    locker.wait(5*1000);
 
     if (UseDynamicNumberOfCompilerThreads && _first == NULL) {
       // Still nothing to compile. Give caller a chance to stop this thread.
@@ -1064,36 +1063,34 @@
     }
 
 #if INCLUDE_JVMCI
-    if (UseJVMCICompiler) {
-      if (blocking) {
-        // Don't allow blocking compiles for requests triggered by JVMCI.
-        if (thread->is_Compiler_thread()) {
-          blocking = false;
-        }
+    if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
+      // Don't allow blocking compiles for requests triggered by JVMCI.
+      if (thread->is_Compiler_thread()) {
+        blocking = false;
+      }
 
-        // Don't allow blocking compiles if inside a class initializer or while performing class loading
-        vframeStream vfst((JavaThread*) thread);
-        for (; !vfst.at_end(); vfst.next()) {
-          if (vfst.method()->is_static_initializer() ||
-              (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
-                  vfst.method()->name() == vmSymbols::loadClass_name())) {
-            blocking = false;
-            break;
-          }
+      // Don't allow blocking compiles if inside a class initializer or while performing class loading
+      vframeStream vfst((JavaThread*) thread);
+      for (; !vfst.at_end(); vfst.next()) {
+        if (vfst.method()->is_static_initializer() ||
+            (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+                vfst.method()->name() == vmSymbols::loadClass_name())) {
+          blocking = false;
+          break;
         }
+      }
 
-        // Don't allow blocking compilation requests to JVMCI
-        // if JVMCI itself is not yet initialized
-        if (!JVMCIRuntime::is_HotSpotJVMCIRuntime_initialized() && compiler(comp_level)->is_jvmci()) {
-          blocking = false;
-        }
+      // Don't allow blocking compilation requests to JVMCI
+      // if JVMCI itself is not yet initialized
+      if (!JVMCI::is_compiler_initialized() && compiler(comp_level)->is_jvmci()) {
+        blocking = false;
+      }
 
-        // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
-        // to avoid deadlock between compiler thread(s) and threads run at shutdown
-        // such as the DestroyJavaVM thread.
-        if (JVMCIRuntime::shutdown_called()) {
-          blocking = false;
-        }
+      // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
+      // to avoid deadlock between compiler thread(s) and threads run at shutdown
+      // such as the DestroyJavaVM thread.
+      if (JVMCI::shutdown_called()) {
+        blocking = false;
       }
     }
 #endif // INCLUDE_JVMCI
@@ -1193,7 +1190,7 @@
   }
 
 #if INCLUDE_JVMCI
-  if (comp->is_jvmci() && !JVMCIRuntime::can_initialize_JVMCI()) {
+  if (comp->is_jvmci() && !JVMCI::can_initialize_JVMCI()) {
     return NULL;
   }
 #endif
@@ -1496,11 +1493,11 @@
  * @return true if this thread needs to free/recycle the task
  */
 bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* task, JavaThread* thread) {
-  MutexLocker waiter(task->lock(), thread);
+  MonitorLocker ml(task->lock(), thread);
   int progress_wait_attempts = 0;
   int methods_compiled = jvmci->methods_compiled();
   while (!task->is_complete() && !is_compilation_disabled_forever() &&
-         task->lock()->wait(!Mutex::_no_safepoint_check_flag, JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) {
+         ml.wait(JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) {
     CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread();
 
     bool progress;
@@ -1558,10 +1555,10 @@
   } else
 #endif
   {
-    MutexLocker waiter(task->lock(), thread);
+    MonitorLocker ml(task->lock(), thread);
     free_task = true;
     while (!task->is_complete() && !is_compilation_disabled_forever()) {
-      task->lock()->wait();
+      ml.wait();
     }
   }
 
@@ -1644,7 +1641,7 @@
 void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread) {
   // Free buffer blob, if allocated
   if (thread->get_buffer_blob() != NULL) {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::free(thread->get_buffer_blob());
   }
 
@@ -1780,7 +1777,7 @@
           }
           // Free buffer blob, if allocated
           if (thread->get_buffer_blob() != NULL) {
-            MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+            MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
             CodeCache::free(thread->get_buffer_blob());
           }
           return; // Stop this thread.
@@ -1910,7 +1907,7 @@
   stringStream s;
   // Dump code cache  into a buffer before locking the tty,
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print_summary(&s, detailed);
   }
   ttyLocker ttyl;
@@ -1924,7 +1921,7 @@
 
   // Dump code cache into a buffer
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print_summary(&s, detailed);
   }
 
@@ -2061,20 +2058,24 @@
 
     // Skip redefined methods
     if (target_handle->is_old()) {
-        failure_reason = "redefined method";
-        retry_message = "not retryable";
-        compilable = ciEnv::MethodCompilable_never;
+      failure_reason = "redefined method";
+      retry_message = "not retryable";
+      compilable = ciEnv::MethodCompilable_never;
     } else {
-        JVMCIEnv env(task, system_dictionary_modification_counter);
-        methodHandle method(thread, target_handle);
-        jvmci->compile_method(method, osr_bci, &env);
+      JVMCICompileState compile_state(task, system_dictionary_modification_counter);
+      JVMCIEnv env(&compile_state, __FILE__, __LINE__);
+      methodHandle method(thread, target_handle);
+      env.runtime()->compile_method(&env, jvmci, method, osr_bci);
 
-        failure_reason = env.failure_reason();
-        failure_reason_on_C_heap = env.failure_reason_on_C_heap();
-        if (!env.retryable()) {
-          retry_message = "not retryable";
-          compilable = ciEnv::MethodCompilable_not_at_tier;
-        }
+      failure_reason = compile_state.failure_reason();
+      failure_reason_on_C_heap = compile_state.failure_reason_on_C_heap();
+      if (!compile_state.retryable()) {
+        retry_message = "not retryable";
+        compilable = ciEnv::MethodCompilable_not_at_tier;
+      }
+      if (task->code() == NULL) {
+        assert(failure_reason != NULL, "must specify failure_reason");
+      }
     }
     post_compile(thread, task, task->code() != NULL, NULL, compilable, failure_reason);
     if (event.should_commit()) {
@@ -2112,9 +2113,9 @@
       ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
     } else {
       if (WhiteBoxAPI && WhiteBox::compilation_locked) {
-        MonitorLockerEx locker(Compilation_lock, Mutex::_no_safepoint_check_flag);
+        MonitorLocker locker(Compilation_lock, Mutex::_no_safepoint_check_flag);
         while (WhiteBox::compilation_locked) {
-          locker.wait(Mutex::_no_safepoint_check_flag);
+          locker.wait();
         }
       }
       comp->compile_method(&ci_env, target, osr_bci, directive);
@@ -2678,7 +2679,7 @@
   // CodeHeapStateAnalytics_lock could be held by a concurrent thread for a long time,
   // leading to an unnecessarily long hold time of the CodeCache_lock.
   ts.update(); // record starting point
-  MutexLockerEx mu1(CodeHeapStateAnalytics_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu1(CodeHeapStateAnalytics_lock, Mutex::_no_safepoint_check_flag);
   out->print_cr("\n__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________\n", ts.seconds());
 
   // If we serve an "allFun" call, it is beneficial to hold the CodeCache_lock
@@ -2688,7 +2689,7 @@
   Monitor* global_lock   = allFun ? CodeCache_lock : NULL;
   Monitor* function_lock = allFun ? NULL : CodeCache_lock;
   ts_global.update(); // record starting point
-  MutexLockerEx mu2(global_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu2(global_lock, Mutex::_no_safepoint_check_flag);
   if (global_lock != NULL) {
     out->print_cr("\n__ CodeCache (global) lock wait took %10.3f seconds _________\n", ts_global.seconds());
     ts_global.update(); // record starting point
@@ -2696,7 +2697,7 @@
 
   if (aggregate) {
     ts.update(); // record starting point
-    MutexLockerEx mu3(function_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu3(function_lock, Mutex::_no_safepoint_check_flag);
     if (function_lock != NULL) {
       out->print_cr("\n__ CodeCache (function) lock wait took %10.3f seconds _________\n", ts.seconds());
     }
@@ -2716,7 +2717,7 @@
   if (methodNames) {
     // print_names() has shown to be sensitive to concurrent CodeHeap modifications.
     // Therefore, request  the CodeCache_lock before calling...
-    MutexLockerEx mu3(function_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu3(function_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print_names(out);
   }
   if (discard) CodeCache::discard(out);
--- a/src/hotspot/share/compiler/compileTask.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/compileTask.cpp	Fri May 03 14:59:32 2019 -0400
@@ -396,6 +396,7 @@
   ResourceMark rm(thread);
 
   if (!_is_success) {
+    assert(_failure_reason != NULL, "missing");
     const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
     log->elem("failure reason='%s'", reason);
   }
--- a/src/hotspot/share/compiler/compilerDefinitions.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/compilerDefinitions.cpp	Fri May 03 14:59:32 2019 -0400
@@ -253,22 +253,6 @@
     if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
       FLAG_SET_DEFAULT(TypeProfileWidth, 8);
     }
-    if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
-      FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
-    }
-    // JVMCI needs values not less than defaults
-    if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
-      FLAG_SET_DEFAULT(ReservedCodeCacheSize, MAX2(64*M, ReservedCodeCacheSize));
-    }
-    if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
-      FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize));
-    }
-    if (FLAG_IS_DEFAULT(MetaspaceSize)) {
-      FLAG_SET_DEFAULT(MetaspaceSize, MIN2(MAX2(12*M, MetaspaceSize), MaxMetaspaceSize));
-    }
-    if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
-      FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease));
-    }
     if (TieredStopAtLevel != CompLevel_full_optimization) {
       // Currently JVMCI compiler can only work at the full optimization level
       warning("forcing TieredStopAtLevel to full optimization because JVMCI is enabled");
@@ -277,7 +261,43 @@
     if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
       FLAG_SET_DEFAULT(TypeProfileLevel, 0);
     }
-  }
+
+    if (UseJVMCINativeLibrary) {
+      // SVM compiled code requires more stack space
+      if (FLAG_IS_DEFAULT(CompilerThreadStackSize)) {
+        // Duplicate logic in the implementations of os::create_thread
+        // so that we can then double the computed stack size. Once
+        // the stack size requirements of SVM are better understood,
+        // this logic can be pushed down into os::create_thread.
+        int stack_size = CompilerThreadStackSize;
+        if (stack_size == 0) {
+          stack_size = VMThreadStackSize;
+        }
+        if (stack_size != 0) {
+          FLAG_SET_DEFAULT(CompilerThreadStackSize, stack_size * 2);
+        }
+      }
+    } else {
+      // Adjust the on stack replacement percentage to avoid early
+      // OSR compilations while JVMCI itself is warming up
+      if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+        FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
+      }
+      // JVMCI needs values not less than defaults
+      if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+        FLAG_SET_DEFAULT(ReservedCodeCacheSize, MAX2(64*M, ReservedCodeCacheSize));
+      }
+      if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+        FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize));
+      }
+      if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+        FLAG_SET_DEFAULT(MetaspaceSize, MIN2(MAX2(12*M, MetaspaceSize), MaxMetaspaceSize));
+      }
+      if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
+        FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease));
+      }
+    } // !UseJVMCINativeLibrary
+  } // UseJVMCICompiler
 }
 #endif // INCLUDE_JVMCI
 
@@ -392,6 +412,8 @@
   // Check that JVMCI compiler supports selested GC.
   // Should be done after GCConfig::initialize() was called.
   JVMCIGlobals::check_jvmci_supported_gc();
+
+  // Do JVMCI specific settings
   set_jvmci_specific_flags();
 #endif
 
--- a/src/hotspot/share/compiler/compilerDirectives.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/compilerDirectives.cpp	Fri May 03 14:59:32 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
@@ -456,7 +456,7 @@
 }
 
 DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 
   assert(_bottom != NULL, "Must never be empty");
   _bottom->inc_refcount();
@@ -464,7 +464,7 @@
 }
 
 void DirectivesStack::push(CompilerDirectives* directive) {
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 
   directive->inc_refcount();
   if (_top == NULL) {
@@ -478,7 +478,7 @@
 }
 
 void DirectivesStack::pop(int count) {
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
   assert(count > -1, "No negative values");
   for (int i = 0; i < count; i++) {
     pop_inner();
@@ -508,14 +508,14 @@
 
 void DirectivesStack::clear() {
   // holding the lock during the whole operation ensuring consistent result
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
   while (_top->next() != NULL) {
     pop_inner();
   }
 }
 
 void DirectivesStack::print(outputStream* st) {
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
   CompilerDirectives* tmp = _top;
   while (tmp != NULL) {
     tmp->print(st);
@@ -526,7 +526,7 @@
 
 void DirectivesStack::release(DirectiveSet* set) {
   assert(set != NULL, "Never NULL");
-  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
   if (set->is_exclusive_copy()) {
     // Old CompilecCmmands forced us to create an exclusive copy
     delete set;
@@ -550,7 +550,7 @@
 
   DirectiveSet* match = NULL;
   {
-    MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 
     CompilerDirectives* dir = _top;
     assert(dir != NULL, "Must be initialized");
--- a/src/hotspot/share/compiler/disassembler.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/disassembler.cpp	Fri May 03 14:59:32 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
@@ -672,8 +672,7 @@
   nm->method()->signature()->print_symbol_on(env.output());
 #if INCLUDE_JVMCI
   {
-    char buffer[O_BUFLEN];
-    char* jvmciName = nm->jvmci_installed_code_name(buffer, O_BUFLEN);
+    const char* jvmciName = nm->jvmci_name();
     if (jvmciName != NULL) {
       env.output()->print(" (%s)", jvmciName);
     }
--- a/src/hotspot/share/compiler/oopMap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/compiler/oopMap.cpp	Fri May 03 14:59:32 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
@@ -338,7 +338,7 @@
       // Protect the operation on the derived pointers.  This
       // protects the addition of derived pointers to the shared
       // derived pointer table in DerivedPointerTable::add().
-      MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
       do {
         omv = oms.current();
         oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
--- a/src/hotspot/share/gc/cms/cmsArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/cmsArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,10 +25,10 @@
 
 #include "precompiled.hpp"
 #include "gc/cms/cmsArguments.hpp"
-#include "gc/cms/cmsCollectorPolicy.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/cms/compactibleFreeListSpace.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/workerPolicy.hpp"
 #include "runtime/arguments.hpp"
@@ -36,10 +36,6 @@
 #include "runtime/globals_extension.hpp"
 #include "utilities/defaultStream.hpp"
 
-size_t CMSArguments::conservative_max_heap_alignment() {
-  return GenCollectedHeap::conservative_max_heap_alignment();
-}
-
 void CMSArguments::set_parnew_gc_flags() {
   assert(!UseSerialGC && !UseParallelOldGC && !UseParallelGC && !UseG1GC,
          "control point invariant");
@@ -154,12 +150,12 @@
 
     // Code along this path potentially sets NewSize and OldSize
     log_trace(gc, heap)("CMS set min_heap_size: " SIZE_FORMAT " initial_heap_size:  " SIZE_FORMAT " max_heap: " SIZE_FORMAT,
-                        Arguments::min_heap_size(), InitialHeapSize, max_heap);
+                        MinHeapSize, InitialHeapSize, max_heap);
     size_t min_new = preferred_max_new_size;
     if (FLAG_IS_CMDLINE(NewSize)) {
       min_new = NewSize;
     }
-    if (max_heap > min_new && Arguments::min_heap_size() > min_new) {
+    if (max_heap > min_new && MinHeapSize > min_new) {
       // Unless explicitly requested otherwise, make young gen
       // at least min_new, and at most preferred_max_new_size.
       if (FLAG_IS_DEFAULT(NewSize)) {
@@ -225,5 +221,5 @@
 }
 
 CollectedHeap* CMSArguments::create_heap() {
-  return create_heap_with_policy<CMSHeap, ConcurrentMarkSweepPolicy>();
+  return new CMSHeap();
 }
--- a/src/hotspot/share/gc/cms/cmsArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/cmsArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -26,16 +26,16 @@
 #define SHARE_GC_CMS_CMSARGUMENTS_HPP
 
 #include "gc/shared/gcArguments.hpp"
+#include "gc/shared/genArguments.hpp"
 
 class CollectedHeap;
 
-class CMSArguments : public GCArguments {
+class CMSArguments : public GenArguments {
 private:
   void disable_adaptive_size_policy(const char* collector_name);
   void set_parnew_gc_flags();
-public:
+
   virtual void initialize();
-  virtual size_t conservative_max_heap_alignment();
   virtual CollectedHeap* create_heap();
 };
 
--- a/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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/cms/cmsCollectorPolicy.hpp"
-#include "gc/cms/parNewGeneration.hpp"
-#include "gc/shared/adaptiveSizePolicy.hpp"
-#include "gc/shared/cardTableRS.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "gc/shared/gcLocker.hpp"
-#include "gc/shared/gcPolicyCounters.hpp"
-#include "gc/shared/gcVMOperations.hpp"
-#include "gc/shared/generationSpec.hpp"
-#include "gc/shared/space.hpp"
-#include "memory/universe.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/globals_extension.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/java.hpp"
-#include "runtime/thread.inline.hpp"
-#include "runtime/vmThread.hpp"
-
-//
-// ConcurrentMarkSweepPolicy methods
-//
-
-void ConcurrentMarkSweepPolicy::initialize_alignments() {
-  _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
-  _heap_alignment = compute_heap_alignment();
-}
--- a/src/hotspot/share/gc/cms/cmsCollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * 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.
- *
- */
-
-#ifndef SHARE_GC_CMS_CMSCOLLECTORPOLICY_HPP
-#define SHARE_GC_CMS_CMSCOLLECTORPOLICY_HPP
-
-#include "gc/shared/collectorPolicy.hpp"
-
-class ConcurrentMarkSweepPolicy : public GenCollectorPolicy {
- protected:
-  void initialize_alignments();
-
- public:
-  ConcurrentMarkSweepPolicy() {}
-};
-
-#endif // SHARE_GC_CMS_CMSCOLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/cms/cmsHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -65,9 +65,8 @@
   }
 };
 
-CMSHeap::CMSHeap(GenCollectorPolicy *policy) :
-    GenCollectedHeap(policy,
-                     Generation::ParNew,
+CMSHeap::CMSHeap() :
+    GenCollectedHeap(Generation::ParNew,
                      Generation::ConcurrentMarkSweep,
                      "ParNew:CMS"),
     _workers(NULL),
@@ -162,9 +161,7 @@
   assert(old_gen()->kind() == Generation::ConcurrentMarkSweep,
          "Unexpected generation kinds");
   CMSCollector* collector =
-    new CMSCollector((ConcurrentMarkSweepGeneration*) old_gen(),
-                     rem_set(),
-                     (ConcurrentMarkSweepPolicy*) gen_policy());
+    new CMSCollector((ConcurrentMarkSweepGeneration*) old_gen(), rem_set());
 
   if (collector == NULL || !collector->completed_initialization()) {
     if (collector) {
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -34,7 +34,6 @@
 #include "utilities/growableArray.hpp"
 
 class CLDClosure;
-class GenCollectorPolicy;
 class GCMemoryManager;
 class MemoryPool;
 class OopsInGenClosure;
@@ -45,7 +44,7 @@
 
 class CMSHeap : public GenCollectedHeap {
 public:
-  CMSHeap(GenCollectorPolicy *policy);
+  CMSHeap();
 
   // Returns JNI_OK on success
   virtual jint initialize();
--- a/src/hotspot/share/gc/cms/cmsVMOperations.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/cmsVMOperations.cpp	Fri May 03 14:59:32 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
@@ -45,7 +45,7 @@
     GCTraceTime(Info, gc, phases, verify) tm("Verify Before", _collector->_gc_timer_cm);
     HandleMark hm;
     FreelistLocker x(_collector);
-    MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
     CMSHeap::heap()->prepare_for_verify();
     Universe::verify();
   }
@@ -57,7 +57,7 @@
     GCTraceTime(Info, gc, phases, verify) tm("Verify After", _collector->_gc_timer_cm);
     HandleMark hm;
     FreelistLocker x(_collector);
-    MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
     Universe::verify();
   }
 }
@@ -183,7 +183,7 @@
           && (_gc_count_before == heap->total_collections())),
          "total_collections() should be monotonically increasing");
 
-  MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
   assert(_full_gc_count_before <= heap->total_full_collections(), "Error");
   if (heap->total_full_collections() == _full_gc_count_before) {
     // Nudge the CMS thread to start a concurrent collection.
@@ -244,11 +244,11 @@
     // or by the CMS thread, so we do not want to be suspended
     // while holding that lock.
     ThreadToNativeFromVM native(jt);
-    MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
     // Either a concurrent or a stop-world full gc is sufficient
     // witness to our request.
     while (heap->total_full_collections_completed() <= _full_gc_count_before) {
-      FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
+      FullGCCount_lock->wait_without_safepoint_check();
     }
   }
 }
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp	Fri May 03 14:59:32 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
@@ -331,11 +331,11 @@
   // Note: this requires that CFLspace c'tors
   // are called serially in the order in which the locks are
   // are acquired in the program text. This is true today.
-  _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true,
-                Monitor::_safepoint_check_sometimes),
+  _freelistLock(_lockRank--, "CompactibleFreeListSpace_lock", true,
+                Monitor::_safepoint_check_never),
   _preconsumptionDirtyCardClosure(NULL),
   _parDictionaryAllocLock(Mutex::leaf - 1,  // == rank(ExpandHeap_lock) - 1
-                          "CompactibleFreeListSpace._dict_par_lock", true,
+                          "CompactibleFreeListSpace_dict_par_lock", true,
                           Monitor::_safepoint_check_never)
 {
   assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize,
@@ -366,7 +366,7 @@
   // Initialize locks for parallel case.
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
     _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1
-                                            "a freelist par lock", true, Mutex::_safepoint_check_sometimes);
+                                            "a freelist par lock", true, Mutex::_safepoint_check_never);
     DEBUG_ONLY(
       _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]);
     )
@@ -1340,7 +1340,7 @@
 }
 
 HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) {
-  MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
   return allocate(size);
 }
 
@@ -1524,8 +1524,8 @@
     // If GC is parallel, this might be called by several threads.
     // This should be rare enough that the locking overhead won't affect
     // the sequential code.
-    MutexLockerEx x(parDictionaryAllocLock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(parDictionaryAllocLock(),
+                  Mutex::_no_safepoint_check_flag);
     fc = getChunkFromDictionary(size);
   }
   if (fc != NULL) {
@@ -1868,7 +1868,7 @@
   Mutex* lock = &_parDictionaryAllocLock;
   FreeChunk* ec;
   {
-    MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(lock, Mutex::_no_safepoint_check_flag);
     ec = dictionary()->find_largest_dict();  // get largest block
     if (ec != NULL && ec->end() == (uintptr_t*) chunk) {
       // It's a coterminal block - we can coalesce.
@@ -1885,7 +1885,7 @@
   if (size < SmallForDictionary) {
     lock = _indexedFreeListParLocks[size];
   }
-  MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(lock, Mutex::_no_safepoint_check_flag);
   addChunkAndRepairOffsetTable((HeapWord*)ec, size, true);
   // record the birth under the lock since the recording involves
   // manipulation of the list on which the chunk lives and
@@ -2042,7 +2042,7 @@
   if (rem_sz < SmallForDictionary) {
     // The freeList lock is held, but multiple GC task threads might be executing in parallel.
     bool is_par = Thread::current()->is_GC_task_thread();
-    if (is_par) _indexedFreeListParLocks[rem_sz]->lock();
+    if (is_par) _indexedFreeListParLocks[rem_sz]->lock_without_safepoint_check();
     returnChunkToFreeList(ffc);
     split(size, rem_sz);
     if (is_par) _indexedFreeListParLocks[rem_sz]->unlock();
@@ -2682,8 +2682,8 @@
   assert(word_sz == _cfls->adjustObjectSize(word_sz), "Error");
   if (word_sz >=  CompactibleFreeListSpace::IndexSetSize) {
     // This locking manages sync with other large object allocations.
-    MutexLockerEx x(_cfls->parDictionaryAllocLock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_cfls->parDictionaryAllocLock(),
+                  Mutex::_no_safepoint_check_flag);
     res = _cfls->getChunkFromDictionaryExact(word_sz);
     if (res == NULL) return NULL;
   } else {
@@ -2781,8 +2781,8 @@
       size_t num_retire =  _indexedFreeList[i].count();
       assert(_num_blocks[i] > num_retire, "Should have used at least one");
       {
-        // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
-        //                Mutex::_no_safepoint_check_flag);
+        // MutexLocker x(_cfls->_indexedFreeListParLocks[i],
+        //               Mutex::_no_safepoint_check_flag);
 
         // Update globals stats for num_blocks used
         _global_num_blocks[i] += (_num_blocks[i] - num_retire);
@@ -2824,8 +2824,8 @@
       AdaptiveFreeList<FreeChunk> fl_for_cur_sz;  // Empty.
       fl_for_cur_sz.set_size(cur_sz);
       {
-        MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
-                        Mutex::_no_safepoint_check_flag);
+        MutexLocker x(_indexedFreeListParLocks[cur_sz],
+                      Mutex::_no_safepoint_check_flag);
         AdaptiveFreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz];
         if (gfl->count() != 0) {
           // nn is the number of chunks of size cur_sz that
@@ -2885,8 +2885,8 @@
         }
         // Update birth stats for this block size.
         size_t num = fl->count();
-        MutexLockerEx x(_indexedFreeListParLocks[word_sz],
-                        Mutex::_no_safepoint_check_flag);
+        MutexLocker x(_indexedFreeListParLocks[word_sz],
+                      Mutex::_no_safepoint_check_flag);
         ssize_t births = _indexedFreeList[word_sz].split_births() + num;
         _indexedFreeList[word_sz].set_split_births(births);
         return true;
@@ -2902,8 +2902,8 @@
   FreeChunk* rem_fc = NULL;
   size_t rem;
   {
-    MutexLockerEx x(parDictionaryAllocLock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(parDictionaryAllocLock(),
+                  Mutex::_no_safepoint_check_flag);
     while (n > 0) {
       fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size()));
       if (fc != NULL) {
@@ -2968,8 +2968,8 @@
     }
   }
   if (rem_fc != NULL) {
-    MutexLockerEx x(_indexedFreeListParLocks[rem],
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_indexedFreeListParLocks[rem],
+                  Mutex::_no_safepoint_check_flag);
     _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size());
     _indexedFreeList[rem].return_chunk_at_head(rem_fc);
     smallSplitBirth(rem);
@@ -3027,8 +3027,8 @@
   assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
   {
     // Update the stats for this block size.
-    MutexLockerEx x(_indexedFreeListParLocks[word_sz],
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_indexedFreeListParLocks[word_sz],
+                  Mutex::_no_safepoint_check_flag);
     const ssize_t births = _indexedFreeList[word_sz].split_births() + n;
     _indexedFreeList[word_sz].set_split_births(births);
     // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,6 @@
 #include "classfile/classLoaderDataGraph.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
-#include "gc/cms/cmsCollectorPolicy.hpp"
 #include "gc/cms/cmsGCStats.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/cms/cmsOopClosures.inline.hpp"
@@ -43,7 +42,6 @@
 #include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "gc/shared/collectorCounters.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
 #include "gc/shared/gcTimer.hpp"
@@ -82,6 +80,9 @@
 #include "services/runtimeService.hpp"
 #include "utilities/align.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 // statics
 CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
@@ -172,7 +173,7 @@
  private:
   // Note: locks are acquired in textual declaration order
   // and released in the opposite order
-  MutexLockerEx _locker1, _locker2, _locker3;
+  MutexLocker _locker1, _locker2, _locker3;
  public:
   CMSTokenSyncWithLocks(bool is_cms_thread, Mutex* mutex1,
                         Mutex* mutex2 = NULL, Mutex* mutex3 = NULL):
@@ -204,7 +205,11 @@
 };
 
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
-     ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct) :
+     ReservedSpace rs,
+     size_t initial_byte_size,
+     size_t min_byte_size,
+     size_t max_byte_size,
+     CardTableRS* ct) :
   CardGeneration(rs, initial_byte_size, ct),
   _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _did_compact(false)
@@ -255,6 +260,8 @@
   // note that all arithmetic is in units of HeapWords.
   assert(MinChunkSize >= CollectedHeap::min_fill_size(), "just checking");
   assert(_dilatation_factor >= 1.0, "from previous assert");
+
+  initialize_performance_counters(min_byte_size, max_byte_size);
 }
 
 
@@ -311,13 +318,13 @@
   return CMSHeap::heap()->size_policy();
 }
 
-void ConcurrentMarkSweepGeneration::initialize_performance_counters() {
+void ConcurrentMarkSweepGeneration::initialize_performance_counters(size_t min_old_size,
+                                                                    size_t max_old_size) {
 
   const char* gen_name = "old";
-  GenCollectorPolicy* gcp = CMSHeap::heap()->gen_policy();
   // Generation Counters - generation 1, 1 subspace
   _gen_counters = new GenerationCounters(gen_name, 1, 1,
-      gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);
+      min_old_size, max_old_size, &_virtual_space);
 
   _space_counters = new GSpaceCounters(gen_name, 0,
                                        _virtual_space.reserved_size(),
@@ -446,8 +453,7 @@
 bool CMSCollector::_foregroundGCShouldWait = false;
 
 CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
-                           CardTableRS*                   ct,
-                           ConcurrentMarkSweepPolicy*     cp):
+                           CardTableRS*                   ct):
   _overflow_list(NULL),
   _conc_workers(NULL),     // may be set later
   _completed_initialization(false),
@@ -457,7 +463,6 @@
   _roots_scanning_options(GenCollectedHeap::SO_None),
   _verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"),
   _verifying(false),
-  _collector_policy(cp),
   _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
   _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()),
@@ -491,7 +496,7 @@
   _stats(cmsGen),
   _eden_chunk_lock(new Mutex(Mutex::leaf + 1, "CMS_eden_chunk_lock", true,
                              //verify that this lock should be acquired with safepoint check.
-                             Monitor::_safepoint_check_sometimes)),
+                             Monitor::_safepoint_check_never)),
   _eden_chunk_array(NULL),     // may be set in ctor body
   _eden_chunk_index(0),        // -- ditto --
   _eden_chunk_capacity(0),     // -- ditto --
@@ -509,7 +514,7 @@
 
   // Allocate MUT and marking bit map
   {
-    MutexLockerEx x(_markBitMap.lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_markBitMap.lock(), Mutex::_no_safepoint_check_flag);
     if (!_markBitMap.allocate(_span)) {
       log_warning(gc)("Failed to allocate CMS Bit Map");
       return;
@@ -797,7 +802,7 @@
 
 HeapWord* ConcurrentMarkSweepGeneration::allocate(size_t size, bool tlab) {
   CMSSynchronousYieldRequest yr;
-  MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
   return have_lock_and_allocate(size, tlab);
 }
 
@@ -844,8 +849,8 @@
 void CMSCollector::direct_allocated(HeapWord* start, size_t size) {
   assert(_markBitMap.covers(start, size), "Out of bounds");
   if (_collectorState >= Marking) {
-    MutexLockerEx y(_markBitMap.lock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker y(_markBitMap.lock(),
+                  Mutex::_no_safepoint_check_flag);
     // [see comments preceding SweepClosure::do_blk() below for details]
     //
     // Can the P-bits be deleted now?  JJJ
@@ -1302,7 +1307,7 @@
   CMSHeap* heap = CMSHeap::heap();
   unsigned int gc_count = heap->total_full_collections();
   if (gc_count == full_gc_count) {
-    MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker y(CGC_lock, Mutex::_no_safepoint_check_flag);
     _full_gc_requested = true;
     _full_gc_cause = cause;
     CGC_lock->notify();   // nudge CMS thread
@@ -1423,7 +1428,7 @@
   bitMapLock()->unlock();
   releaseFreelistLocks();
   {
-    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
     if (_foregroundGCShouldWait) {
       // We are going to be waiting for action for the CMS thread;
       // it had better not be gone (for instance at shutdown)!
@@ -1440,7 +1445,7 @@
              "Possible deadlock");
       while (_foregroundGCShouldWait) {
         // wait for notification
-        CGC_lock->wait(Mutex::_no_safepoint_check_flag);
+        CGC_lock->wait_without_safepoint_check();
         // Possibility of delay/starvation here, since CMS token does
         // not know to give priority to VM thread? Actually, i think
         // there wouldn't be any delay/starvation, but the proof of
@@ -1685,7 +1690,7 @@
  public:
   ReleaseForegroundGC(CMSCollector* c) : _c(c) {
     assert(_c->_foregroundGCShouldWait, "Else should not need to call");
-    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
     // allow a potentially blocked foreground collector to proceed
     _c->_foregroundGCShouldWait = false;
     if (_c->_foregroundGCIsActive) {
@@ -1697,7 +1702,7 @@
 
   ~ReleaseForegroundGC() {
     assert(!_c->_foregroundGCShouldWait, "Usage protocol violation?");
-    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
     _c->_foregroundGCShouldWait = true;
   }
 };
@@ -1708,10 +1713,9 @@
 
   CMSHeap* heap = CMSHeap::heap();
   {
-    bool safepoint_check = Mutex::_no_safepoint_check_flag;
-    MutexLockerEx hl(Heap_lock, safepoint_check);
+    MutexLocker hl(Heap_lock, Mutex::_no_safepoint_check_flag);
     FreelistLocker fll(this);
-    MutexLockerEx x(CGC_lock, safepoint_check);
+    MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
     if (_foregroundGCIsActive) {
       // The foreground collector is. Skip this
       // background collection.
@@ -1855,7 +1859,7 @@
         // collection was preempted.
         {
           ReleaseForegroundGC x(this);   // unblock FG collection
-          MutexLockerEx       y(Heap_lock, Mutex::_no_safepoint_check_flag);
+          MutexLocker         y(Heap_lock, Mutex::_no_safepoint_check_flag);
           CMSTokenSync        z(true);   // not strictly needed.
           if (_collectorState == Resizing) {
             compute_new_size();
@@ -1898,7 +1902,7 @@
     // Clear _foregroundGCShouldWait and, in the event that the
     // foreground collector is waiting, notify it, before
     // returning.
-    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
     _foregroundGCShouldWait = false;
     if (_foregroundGCIsActive) {
       CGC_lock->notify();
@@ -1946,7 +1950,7 @@
   // Block the foreground collector until the
   // background collectors decides whether to
   // yield.
-  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   _foregroundGCShouldWait = true;
   if (_foregroundGCIsActive) {
     // The background collector yields to the
@@ -1964,7 +1968,7 @@
     log_debug(gc, state)("CMS Thread " INTPTR_FORMAT " waiting at CMS state %d",
                          p2i(Thread::current()), _collectorState);
     while (_foregroundGCIsActive) {
-      CGC_lock->wait(Mutex::_no_safepoint_check_flag);
+      CGC_lock->wait_without_safepoint_check();
     }
     ConcurrentMarkSweepThread::set_CMS_flag(
       ConcurrentMarkSweepThread::CMS_cms_has_token);
@@ -2206,7 +2210,7 @@
                 _markBitMap.isMarked(addr) ? "" : " not");
 
   if (verify_after_remark()) {
-    MutexLockerEx x(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker x(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
     bool result = verification_mark_bm()->isMarked(addr);
     tty->print_cr("TransitiveMark: Address " PTR_FORMAT " %s marked", p2i(addr),
                   result ? "IS" : "is NOT");
@@ -2266,7 +2270,7 @@
 
 bool CMSCollector::verify_after_remark() {
   GCTraceTime(Info, gc, phases, verify) tm("Verifying CMS Marking.");
-  MutexLockerEx ml(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
   static bool init = false;
 
   assert(SafepointSynchronize::is_at_safepoint(),
@@ -2467,7 +2471,7 @@
   if (freelistLock()->owned_by_self()) {
     Generation::oop_iterate(cl);
   } else {
-    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
     Generation::oop_iterate(cl);
   }
 }
@@ -2477,7 +2481,7 @@
   if (freelistLock()->owned_by_self()) {
     Generation::object_iterate(cl);
   } else {
-    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
     Generation::object_iterate(cl);
   }
 }
@@ -2487,7 +2491,7 @@
   if (freelistLock()->owned_by_self()) {
     Generation::safe_object_iterate(cl);
   } else {
-    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
     Generation::safe_object_iterate(cl);
   }
 }
@@ -2506,7 +2510,7 @@
   if (freelistLock()->owned_by_self()) {
     cmsSpace()->prepare_for_verify();
   } else {
-    MutexLockerEx fll(freelistLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker fll(freelistLock(), Mutex::_no_safepoint_check_flag);
     cmsSpace()->prepare_for_verify();
   }
 }
@@ -2519,7 +2523,7 @@
   if (freelistLock()->owned_by_self()) {
     cmsSpace()->verify();
   } else {
-    MutexLockerEx fll(freelistLock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker fll(freelistLock(), Mutex::_no_safepoint_check_flag);
     cmsSpace()->verify();
   }
 }
@@ -2629,7 +2633,7 @@
                                                    bool   parallel) {
   CMSSynchronousYieldRequest yr;
   assert(!tlab, "Can't deal with TLAB allocation");
-  MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker x(freelistLock(), Mutex::_no_safepoint_check_flag);
   expand_for_gc_cause(word_size*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_allocation);
   if (GCExpandToAllocateDelayMillis > 0) {
     os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
@@ -2804,8 +2808,8 @@
   assert(_restart_addr == NULL, "Control point invariant");
   {
     // acquire locks for subsequent manipulations
-    MutexLockerEx x(bitMapLock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker x(bitMapLock(),
+                  Mutex::_no_safepoint_check_flag);
     checkpointRootsInitialWork();
     // enable ("weak") refs discovery
     rp->enable_discovery();
@@ -3246,8 +3250,8 @@
     return false;
   }
   assert(work_q->size() == 0, "Shouldn't steal");
-  MutexLockerEx ml(ovflw_stk->par_lock(),
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(ovflw_stk->par_lock(),
+                 Mutex::_no_safepoint_check_flag);
   // Grab up to 1/4 the size of the work queue
   size_t num = MIN2((size_t)(work_q->max_elems() - work_q->size())/4,
                     (size_t)ParGCDesiredObjsFromOverflowList);
@@ -3451,8 +3455,8 @@
 void ParConcMarkingClosure::handle_stack_overflow(HeapWord* lost) {
   // We need to do this under a mutex to prevent other
   // workers from interfering with the work done below.
-  MutexLockerEx ml(_overflow_stack->par_lock(),
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(_overflow_stack->par_lock(),
+                 Mutex::_no_safepoint_check_flag);
   // Remember the least grey address discarded
   HeapWord* ra = (HeapWord*)_overflow_stack->least_value(lost);
   _collector->lower_restart_addr(ra);
@@ -4169,8 +4173,8 @@
         );
     }
     FreelistLocker x(this);
-    MutexLockerEx y(bitMapLock(),
-                    Mutex::_no_safepoint_check_flag);
+    MutexLocker y(bitMapLock(),
+                  Mutex::_no_safepoint_check_flag);
     checkpointRootsFinalWork();
   }
   verify_work_stacks_empty();
@@ -5259,6 +5263,9 @@
 
       // Prune dead klasses from subklass/sibling/implementor lists.
       Klass::clean_weak_klass_links(purged_class);
+
+      // Clean JVMCI metadata handles.
+      JVMCI_ONLY(JVMCI::do_unloading(purged_class));
     }
   }
 
@@ -5644,7 +5651,7 @@
   _shifter(shifter),
   _bm(),
   _lock(mutex_rank >= 0 ? new Mutex(mutex_rank, mutex_name, true,
-                                    Monitor::_safepoint_check_sometimes) : NULL)
+                                    Monitor::_safepoint_check_never) : NULL)
 {
   _bmStartWord = 0;
   _bmWordSize  = 0;
@@ -6725,8 +6732,8 @@
 void ParPushOrMarkClosure::handle_stack_overflow(HeapWord* lost) {
   // We need to do this under a mutex to prevent other
   // workers from interfering with the work done below.
-  MutexLockerEx ml(_overflow_stack->par_lock(),
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(_overflow_stack->par_lock(),
+                 Mutex::_no_safepoint_check_flag);
   // Remember the least grey address discarded
   HeapWord* ra = (HeapWord*)_overflow_stack->least_value(lost);
   _collector->lower_restart_addr(ra);
@@ -7527,7 +7534,7 @@
   }
 
   ConcurrentMarkSweepThread::synchronize(true);
-  _freelistLock->lock();
+  _freelistLock->lock_without_safepoint_check();
   _bitMap->lock()->lock_without_safepoint_check();
   _collector->startTimer();
 }
@@ -7992,7 +7999,7 @@
 void CMSCollector::par_preserve_mark_if_necessary(oop p) {
   markOop m = p->mark_raw();
   if (m->must_be_preserved(p)) {
-    MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
     // Even though we read the mark word without holding
     // the lock, we are assured that it will not change
     // because we "own" this oop, so no other thread can
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp	Fri May 03 14:59:32 2019 -0400
@@ -225,13 +225,13 @@
   // "Parallel versions" of some of the above
   oop par_pop() {
     // lock and pop
-    MutexLockerEx x(&_par_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(&_par_lock, Mutex::_no_safepoint_check_flag);
     return pop();
   }
 
   bool par_push(oop ptr) {
     // lock and push
-    MutexLockerEx x(&_par_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(&_par_lock, Mutex::_no_safepoint_check_flag);
     return push(ptr);
   }
 
@@ -585,10 +585,6 @@
   bool verifying() const { return _verifying; }
   void set_verifying(bool v) { _verifying = v; }
 
-  // Collector policy
-  ConcurrentMarkSweepPolicy* _collector_policy;
-  ConcurrentMarkSweepPolicy* collector_policy() { return _collector_policy; }
-
   void set_did_compact(bool v);
 
   // XXX Move these to CMSStats ??? FIX ME !!!
@@ -833,8 +829,7 @@
   void setup_cms_unloading_and_verification_state();
  public:
   CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
-               CardTableRS*                   ct,
-               ConcurrentMarkSweepPolicy*     cp);
+               CardTableRS*                   ct);
   ConcurrentMarkSweepThread* cmsThread() { return _cmsThread; }
 
   MemRegion ref_processor_span() const { return _span_based_discoverer.span(); }
@@ -1075,7 +1070,11 @@
   void assert_correct_size_change_locking();
 
  public:
-  ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct);
+  ConcurrentMarkSweepGeneration(ReservedSpace rs,
+                                size_t initial_byte_size,
+                                size_t min_byte_size,
+                                size_t max_byte_size,
+                                CardTableRS* ct);
 
   // Accessors
   CMSCollector* collector() const { return _collector; }
@@ -1212,7 +1211,7 @@
   // Performance Counters support
   virtual void update_counters();
   virtual void update_counters(size_t used);
-  void initialize_performance_counters();
+  void initialize_performance_counters(size_t min_old_size, size_t max_old_size);
   CollectorCounters* counters()  { return collector()->counters(); }
 
   // Support for parallel remark of survivor space
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, 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
@@ -112,7 +112,7 @@
   // Now post a notify on CGC_lock so as to nudge
   // CMS thread(s) that might be slumbering in
   // sleepBeforeNextCycle.
-  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   CGC_lock->notify_all();
 }
 
@@ -147,15 +147,14 @@
 void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) {
   assert(UseConcMarkSweepGC, "just checking");
 
-  MutexLockerEx x(CGC_lock,
-                  Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   if (!is_cms_thread) {
     assert(Thread::current()->is_VM_thread(), "Not a VM thread");
     CMSSynchronousYieldRequest yr;
     while (CMS_flag_is_set(CMS_cms_has_token)) {
       // indicate that we want to get the token
       set_CMS_flag(CMS_vm_wants_token);
-      CGC_lock->wait(true);
+      CGC_lock->wait_without_safepoint_check();
     }
     // claim the token and proceed
     clear_CMS_flag(CMS_vm_wants_token);
@@ -167,7 +166,7 @@
     // This will need to be modified is there are more CMS threads than one.
     while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) {
       set_CMS_flag(CMS_cms_wants_token);
-      CGC_lock->wait(true);
+      CGC_lock->wait_without_safepoint_check();
     }
     // claim the token
     clear_CMS_flag(CMS_cms_wants_token);
@@ -178,8 +177,7 @@
 void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
   assert(UseConcMarkSweepGC, "just checking");
 
-  MutexLockerEx x(CGC_lock,
-                  Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   if (!is_cms_thread) {
     assert(Thread::current()->is_VM_thread(), "Not a VM thread");
     assert(CMS_flag_is_set(CMS_vm_has_token), "just checking");
@@ -206,13 +204,12 @@
 
 // Wait until any cms_lock event
 void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
-  MutexLockerEx x(CGC_lock,
-                  Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   if (should_terminate() || _collector->_full_gc_requested) {
     return;
   }
   set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
-  CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis);
+  CGC_lock->wait_without_safepoint_check(t_millis);
   clear_CMS_flag(CMS_cms_wants_token);
   assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
          "Should not be set");
@@ -231,7 +228,7 @@
   // Total collections count before waiting loop
   unsigned int before_count;
   {
-    MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker hl(Heap_lock, Mutex::_no_safepoint_check_flag);
     before_count = heap->total_collections();
   }
 
@@ -255,14 +252,14 @@
 
     // Wait until the next event or the remaining timeout
     {
-      MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
 
       if (should_terminate() || _collector->_full_gc_requested) {
         return;
       }
       set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
       assert(t_millis == 0 || wait_time_millis > 0, "Sanity");
-      CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis);
+      CGC_lock->wait_without_safepoint_check(wait_time_millis);
       clear_CMS_flag(CMS_cms_wants_token);
       assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
              "Should not be set");
@@ -277,7 +274,7 @@
     // Total collections count after the event
     unsigned int after_count;
     {
-      MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker hl(Heap_lock, Mutex::_no_safepoint_check_flag);
       after_count = heap->total_collections();
     }
 
--- a/src/hotspot/share/gc/cms/parNewGeneration.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp	Fri May 03 14:59:32 2019 -0400
@@ -622,8 +622,11 @@
   _old_gen->par_oop_since_save_marks_iterate_done((int) worker_id);
 }
 
-ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size)
-  : DefNewGeneration(rs, initial_byte_size, "CMS young collection pauses"),
+ParNewGeneration::ParNewGeneration(ReservedSpace rs,
+                                   size_t initial_byte_size,
+                                   size_t min_byte_size,
+                                   size_t max_byte_size)
+  : DefNewGeneration(rs, initial_byte_size, min_byte_size, max_byte_size, "CMS young collection pauses"),
   _plab_stats("Young", YoungPLABSize, PLABWeight),
   _overflow_list(NULL),
   _is_alive_closure(this)
--- a/src/hotspot/share/gc/cms/parNewGeneration.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp	Fri May 03 14:59:32 2019 -0400
@@ -348,7 +348,10 @@
   void restore_preserved_marks();
 
  public:
-  ParNewGeneration(ReservedSpace rs, size_t initial_byte_size);
+  ParNewGeneration(ReservedSpace rs,
+                   size_t initial_byte_size,
+                   size_t min_byte_size,
+                   size_t max_byte_size);
 
   ~ParNewGeneration() {
     for (uint i = 0; i < ParallelGCThreads; i++)
--- a/src/hotspot/share/gc/cms/yieldingWorkgroup.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/cms/yieldingWorkgroup.cpp	Fri May 03 14:59:32 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
@@ -43,7 +43,7 @@
   _monitor = new Monitor(/* priority */       Mutex::leaf,
                          /* name */           "WorkGroup monitor",
                          /* allow_vm_block */ are_GC_task_threads,
-                                              Monitor::_safepoint_check_sometimes);
+                                              Monitor::_safepoint_check_never);
 
   assert(monitor() != NULL, "Failed to allocate monitor");
 }
@@ -137,7 +137,7 @@
  */
 /////////////////////
 void YieldingFlexibleWorkGang::start_task(YieldingFlexibleGangTask* new_task) {
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   assert(task() == NULL, "Gang currently tied to a task");
   assert(new_task != NULL, "Null task");
   // Bind task to gang
@@ -175,7 +175,7 @@
     assert(started_workers() <= active_workers(), "invariant");
     assert(finished_workers() <= active_workers(), "invariant");
     assert(yielded_workers() <= active_workers(), "invariant");
-    monitor()->wait(Mutex::_no_safepoint_check_flag);
+    monitor()->wait_without_safepoint_check();
   }
   switch (yielding_task()->status()) {
     case COMPLETED:
@@ -204,7 +204,7 @@
 void YieldingFlexibleWorkGang::continue_task(
   YieldingFlexibleGangTask* gang_task) {
 
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   assert(task() != NULL && task() == gang_task, "Incorrect usage");
   assert(_started_workers == _active_workers, "Precondition");
   assert(_yielded_workers > 0 && yielding_task()->status() == YIELDED,
@@ -224,7 +224,7 @@
 
 void YieldingFlexibleWorkGang::yield() {
   assert(task() != NULL, "Inconsistency; should have task binding");
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   assert(yielded_workers() < active_workers(), "Consistency check");
   if (yielding_task()->status() == ABORTING) {
     // Do not yield; we need to abort as soon as possible
@@ -247,7 +247,7 @@
     switch (yielding_task()->status()) {
       case YIELDING:
       case YIELDED: {
-        monitor()->wait(Mutex::_no_safepoint_check_flag);
+        monitor()->wait_without_safepoint_check();
         break;  // from switch
       }
       case ACTIVE:
@@ -271,7 +271,7 @@
 
 void YieldingFlexibleWorkGang::abort() {
   assert(task() != NULL, "Inconsistency; should have task binding");
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   assert(yielded_workers() < active_workers(), "Consistency check");
   #ifndef PRODUCT
     switch (yielding_task()->status()) {
@@ -319,7 +319,7 @@
 void YieldingFlexibleGangWorker::loop() {
   int previous_sequence_number = 0;
   Monitor* gang_monitor = yf_gang()->monitor();
-  MutexLockerEx ml(gang_monitor, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(gang_monitor, Mutex::_no_safepoint_check_flag);
   YieldingWorkData data;
   int id;
   while (true) {
@@ -340,7 +340,7 @@
         yf_gang()->internal_note_start();
         // Now, release the gang mutex and do the work.
         {
-          MutexUnlockerEx mul(gang_monitor, Mutex::_no_safepoint_check_flag);
+          MutexUnlocker mul(gang_monitor, Mutex::_no_safepoint_check_flag);
           GCIdMark gc_id_mark(data.task()->gc_id());
           data.task()->work(id);   // This might include yielding
         }
@@ -394,6 +394,6 @@
     // Remember the sequence number
     previous_sequence_number = data.sequence_number();
     // Wait for more work
-    gang_monitor->wait(Mutex::_no_safepoint_check_flag);
+    gang_monitor->wait_without_safepoint_check();
   }
 }
--- a/src/hotspot/share/gc/epsilon/epsilonArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,8 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/epsilon/epsilonArguments.hpp"
 #include "gc/epsilon/epsilonHeap.hpp"
-#include "gc/epsilon/epsilonCollectorPolicy.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "runtime/vm_version.hpp"
@@ -67,6 +66,13 @@
 #endif
 }
 
+void EpsilonArguments::initialize_alignments() {
+  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+  size_t align = MAX2((size_t)os::vm_allocation_granularity(), page_size);
+  SpaceAlignment = align;
+  HeapAlignment  = align;
+}
+
 CollectedHeap* EpsilonArguments::create_heap() {
-  return create_heap_with_policy<EpsilonHeap, EpsilonCollectorPolicy>();
+  return new EpsilonHeap();
 }
--- a/src/hotspot/share/gc/epsilon/epsilonArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -30,7 +30,9 @@
 class CollectedHeap;
 
 class EpsilonArguments : public GCArguments {
-public:
+private:
+  virtual void initialize_alignments();
+
   virtual void initialize();
   virtual size_t conservative_max_heap_alignment();
   virtual CollectedHeap* create_heap();
--- a/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 #include "runtime/thread.hpp"
 #include "gc/epsilon/epsilonBarrierSet.hpp"
 #include "gc/epsilon/epsilonThreadLocalData.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 #include "utilities/macros.hpp"
--- a/src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_GC_EPSILON_EPSILONCOLLECTORPOLICY_HPP
-#define SHARE_GC_EPSILON_EPSILONCOLLECTORPOLICY_HPP
-
-#include "gc/shared/collectorPolicy.hpp"
-
-class EpsilonCollectorPolicy: public CollectorPolicy {
-protected:
-  virtual void initialize_alignments() {
-    size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
-    size_t align = MAX2((size_t)os::vm_allocation_granularity(), page_size);
-    _space_alignment = align;
-    _heap_alignment  = align;
-  }
-
-public:
-  EpsilonCollectorPolicy() : CollectorPolicy() {};
-};
-
-#endif // SHARE_GC_EPSILON_EPSILONCOLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,14 +25,16 @@
 #include "gc/epsilon/epsilonHeap.hpp"
 #include "gc/epsilon/epsilonMemoryPool.hpp"
 #include "gc/epsilon/epsilonThreadLocalData.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
+#include "runtime/globals.hpp"
 
 jint EpsilonHeap::initialize() {
-  size_t align = _policy->heap_alignment();
-  size_t init_byte_size = align_up(_policy->initial_heap_byte_size(), align);
-  size_t max_byte_size  = align_up(_policy->max_heap_byte_size(), align);
+  size_t align = HeapAlignment;
+  size_t init_byte_size = align_up(InitialHeapSize, align);
+  size_t max_byte_size  = align_up(MaxHeapSize, align);
 
   // Initialize backing storage
   ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, align);
@@ -124,7 +126,7 @@
 
   while (res == NULL) {
     // Allocation failed, attempt expansion, and retry:
-    MutexLockerEx ml(Heap_lock);
+    MutexLocker ml(Heap_lock);
 
     size_t space_left = max_capacity() - capacity();
     size_t want_space = MAX2(size, EpsilonMinHeapExpand);
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,6 @@
 #include "gc/shared/softRefPolicy.hpp"
 #include "gc/shared/space.hpp"
 #include "services/memoryManager.hpp"
-#include "gc/epsilon/epsilonCollectorPolicy.hpp"
 #include "gc/epsilon/epsilonMonitoringSupport.hpp"
 #include "gc/epsilon/epsilonBarrierSet.hpp"
 #include "gc/epsilon/epsilon_globals.hpp"
@@ -36,7 +35,6 @@
 class EpsilonHeap : public CollectedHeap {
   friend class VMStructs;
 private:
-  EpsilonCollectorPolicy* _policy;
   SoftRefPolicy _soft_ref_policy;
   EpsilonMonitoringSupport* _monitoring_support;
   MemoryPool* _pool;
@@ -53,8 +51,7 @@
 public:
   static EpsilonHeap* heap();
 
-  EpsilonHeap(EpsilonCollectorPolicy* p) :
-          _policy(p),
+  EpsilonHeap() :
           _memory_manager("Epsilon Heap", "") {};
 
   virtual Name kind() const {
@@ -65,10 +62,6 @@
     return "Epsilon";
   }
 
-  virtual CollectorPolicy* collector_policy() const {
-    return _policy;
-  }
-
   virtual SoftRefPolicy* soft_ref_policy() {
     return &_soft_ref_policy;
   }
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp	Fri May 03 14:59:32 2019 -0400
@@ -196,7 +196,7 @@
                                                                     desired_word_size,
                                                                     actual_word_size);
   if (result == NULL && !survivor_is_full()) {
-    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag);
     result = survivor_gc_alloc_region()->attempt_allocation_locked(min_word_size,
                                                                    desired_word_size,
                                                                    actual_word_size);
@@ -220,7 +220,7 @@
                                                                desired_word_size,
                                                                actual_word_size);
   if (result == NULL && !old_is_full()) {
-    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag);
     result = old_gc_alloc_region()->attempt_allocation_locked(min_word_size,
                                                               desired_word_size,
                                                               actual_word_size);
--- a/src/hotspot/share/gc/g1/g1Arguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Arguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -26,15 +26,37 @@
 #include "precompiled.hpp"
 #include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1HeapVerifier.hpp"
-#include "gc/g1/g1HeterogeneousCollectorPolicy.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/g1/heapRegionRemSet.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/workerPolicy.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 
+static const double MaxRamFractionForYoung = 0.8;
+size_t G1Arguments::MaxMemoryForYoung;
+
+static size_t calculate_heap_alignment(size_t space_alignment) {
+  size_t card_table_alignment = CardTableRS::ct_max_alignment_constraint();
+  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+  return MAX3(card_table_alignment, space_alignment, page_size);
+}
+
+void G1Arguments::initialize_alignments() {
+  // Set up the region size and associated fields.
+  //
+  // There is a circular dependency here. We base the region size on the heap
+  // size, but the heap size should be aligned with the region size. To get
+  // around this we use the unaligned values for the heap.
+  HeapRegion::setup_heap_region_size(InitialHeapSize, MaxHeapSize);
+  HeapRegionRemSet::setup_remset_size();
+
+  SpaceAlignment = HeapRegion::GrainBytes;
+  HeapAlignment = calculate_heap_alignment(SpaceAlignment);
+}
+
 size_t G1Arguments::conservative_max_heap_alignment() {
   return HeapRegion::max_region_size();
 }
@@ -156,10 +178,81 @@
   initialize_verification_types();
 }
 
-CollectedHeap* G1Arguments::create_heap() {
-  if (AllocateOldGenAt != NULL) {
-    return create_heap_with_policy<G1CollectedHeap, G1HeterogeneousCollectorPolicy>();
+static size_t calculate_reasonable_max_memory_for_young(FormatBuffer<100> &calc_str, double max_ram_fraction_for_young) {
+  julong phys_mem;
+  // If MaxRam is specified, we use that as maximum physical memory available.
+  if (FLAG_IS_DEFAULT(MaxRAM)) {
+    phys_mem = os::physical_memory();
+    calc_str.append("Physical_Memory");
   } else {
-    return create_heap_with_policy<G1CollectedHeap, G1CollectorPolicy>();
+    phys_mem = (julong)MaxRAM;
+    calc_str.append("MaxRAM");
+  }
+
+  julong reasonable_max = phys_mem;
+
+  // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
+  // reasonable max size of young generation.
+  if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
+    reasonable_max = (julong)(phys_mem / MaxRAMFraction);
+    calc_str.append(" / MaxRAMFraction");
+  }  else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
+    reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
+    calc_str.append(" * MaxRAMPercentage / 100");
+  }  else {
+    // We use our own fraction to calculate max size of young generation.
+    reasonable_max = phys_mem * max_ram_fraction_for_young;
+    calc_str.append(" * %0.2f", max_ram_fraction_for_young);
+  }
+
+  return (size_t)reasonable_max;
+}
+
+void G1Arguments::initialize_heap_flags_and_sizes() {
+  if (AllocateOldGenAt != NULL) {
+    initialize_heterogeneous();
   }
+
+  GCArguments::initialize_heap_flags_and_sizes();
 }
+
+void G1Arguments::initialize_heterogeneous() {
+  FormatBuffer<100> calc_str("");
+
+  MaxMemoryForYoung = calculate_reasonable_max_memory_for_young(calc_str, MaxRamFractionForYoung);
+
+  if (MaxNewSize > MaxMemoryForYoung) {
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
+                            MaxMemoryForYoung, calc_str.buffer());
+    } else {
+      log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
+                         "Dram usage can be lowered by setting MaxNewSize to a lower value", MaxMemoryForYoung, calc_str.buffer());
+    }
+    MaxNewSize = MaxMemoryForYoung;
+  }
+  if (NewSize > MaxMemoryForYoung) {
+    if (FLAG_IS_CMDLINE(NewSize)) {
+      log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
+                            MaxMemoryForYoung, calc_str.buffer());
+    }
+    NewSize = MaxMemoryForYoung;
+  }
+
+}
+
+CollectedHeap* G1Arguments::create_heap() {
+  return new G1CollectedHeap();
+}
+
+bool G1Arguments::is_heterogeneous_heap() {
+  return AllocateOldGenAt != NULL;
+}
+
+size_t G1Arguments::reasonable_max_memory_for_young() {
+  return MaxMemoryForYoung;
+}
+
+size_t G1Arguments::heap_reserved_size_bytes() {
+  return (is_heterogeneous_heap() ? 2 : 1) * MaxHeapSize;
+}
--- a/src/hotspot/share/gc/g1/g1Arguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Arguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -34,13 +34,25 @@
   friend class G1HeapVerifierTest;
 
 private:
+  static size_t MaxMemoryForYoung;
+
   static void initialize_verification_types();
   static void parse_verification_type(const char* type);
 
-public:
+  virtual void initialize_alignments();
+  virtual void initialize_heap_flags_and_sizes();
+
+  void initialize_heterogeneous();
+
   virtual void initialize();
   virtual size_t conservative_max_heap_alignment();
   virtual CollectedHeap* create_heap();
+
+public:
+  // Heterogeneous heap support
+  static bool is_heterogeneous_heap();
+  static size_t reasonable_max_memory_for_young();
+  static size_t heap_reserved_size_bytes();
 };
 
 #endif // SHARE_GC_G1_G1ARGUMENTS_HPP
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -29,10 +29,10 @@
 #include "code/codeCache.hpp"
 #include "code/icBuffer.hpp"
 #include "gc/g1/g1Allocator.inline.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectionSet.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
@@ -436,7 +436,7 @@
     uint gc_count_before;
 
     {
-      MutexLockerEx x(Heap_lock);
+      MutexLocker x(Heap_lock);
       result = _allocator->attempt_allocation_locked(word_size);
       if (result != NULL) {
         return result;
@@ -575,7 +575,7 @@
   assert(!is_init_completed(), "Expect to be called at JVM init time");
   assert(ranges != NULL, "MemRegion array NULL");
   assert(count != 0, "No MemRegions provided");
-  MutexLockerEx x(Heap_lock);
+  MutexLocker x(Heap_lock);
 
   MemRegion reserved = _hrm->reserved();
   HeapWord* prev_last_addr = NULL;
@@ -685,7 +685,7 @@
   // that contain the address range. The address range actually within the
   // MemRegion will not be modified. That is assumed to have been initialized
   // elsewhere, probably via an mmap of archived heap data.
-  MutexLockerEx x(Heap_lock);
+  MutexLocker x(Heap_lock);
   for (size_t i = 0; i < count; i++) {
     HeapWord* start_address = ranges[i].start();
     HeapWord* last_address = ranges[i].last();
@@ -771,7 +771,7 @@
 
   // For each Memregion, free the G1 regions that constitute it, and
   // notify mark-sweep that the range is no longer to be considered 'archive.'
-  MutexLockerEx x(Heap_lock);
+  MutexLocker x(Heap_lock);
   for (size_t i = 0; i < count; i++) {
     HeapWord* start_address = ranges[i].start();
     HeapWord* last_address = ranges[i].last();
@@ -882,7 +882,7 @@
 
 
     {
-      MutexLockerEx x(Heap_lock);
+      MutexLocker x(Heap_lock);
 
       // Given that humongous objects are not allocated in young
       // regions, we'll first try to do the allocation without doing a
@@ -1177,9 +1177,6 @@
   const double maximum_free_percentage = (double) MaxHeapFreeRatio / 100.0;
   const double minimum_used_percentage = 1.0 - maximum_free_percentage;
 
-  const size_t min_heap_size = collector_policy()->min_heap_byte_size();
-  const size_t max_heap_size = collector_policy()->max_heap_byte_size();
-
   // We have to be careful here as these two calculations can overflow
   // 32-bit size_t's.
   double used_after_gc_d = (double) used_after_gc;
@@ -1188,7 +1185,7 @@
 
   // Let's make sure that they are both under the max heap size, which
   // by default will make them fit into a size_t.
-  double desired_capacity_upper_bound = (double) max_heap_size;
+  double desired_capacity_upper_bound = (double) MaxHeapSize;
   minimum_desired_capacity_d = MIN2(minimum_desired_capacity_d,
                                     desired_capacity_upper_bound);
   maximum_desired_capacity_d = MIN2(maximum_desired_capacity_d,
@@ -1208,11 +1205,11 @@
   // Should not be greater than the heap max size. No need to adjust
   // it with respect to the heap min size as it's a lower bound (i.e.,
   // we'll try to make the capacity larger than it, not smaller).
-  minimum_desired_capacity = MIN2(minimum_desired_capacity, max_heap_size);
+  minimum_desired_capacity = MIN2(minimum_desired_capacity, MaxHeapSize);
   // Should not be less than the heap min size. No need to adjust it
   // with respect to the heap max size as it's an upper bound (i.e.,
   // we'll try to make the capacity smaller than it, not greater).
-  maximum_desired_capacity =  MAX2(maximum_desired_capacity, min_heap_size);
+  maximum_desired_capacity =  MAX2(maximum_desired_capacity, MinHeapSize);
 
   if (capacity_after_gc < minimum_desired_capacity) {
     // Don't expand unless it's significant
@@ -1484,11 +1481,10 @@
   const char* get_description() { return "Humongous Regions"; }
 };
 
-G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
+G1CollectedHeap::G1CollectedHeap() :
   CollectedHeap(),
   _young_gen_sampling_thread(NULL),
   _workers(NULL),
-  _collector_policy(collector_policy),
   _card_table(NULL),
   _soft_ref_policy(),
   _old_set("Old Region Set", new OldRegionSetChecker()),
@@ -1515,7 +1511,7 @@
   _survivor(),
   _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
   _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()),
-  _policy(G1Policy::create_policy(collector_policy, _gc_timer_stw)),
+  _policy(G1Policy::create_policy(_gc_timer_stw)),
   _heap_sizing_policy(NULL),
   _collection_set(this, _policy),
   _hot_card_cache(NULL),
@@ -1644,14 +1640,13 @@
   // HeapWordSize).
   guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");
 
-  size_t init_byte_size = collector_policy()->initial_heap_byte_size();
-  size_t max_byte_size = _collector_policy->heap_reserved_size_bytes();
-  size_t heap_alignment = collector_policy()->heap_alignment();
+  size_t init_byte_size = InitialHeapSize;
+  size_t reserved_byte_size = G1Arguments::heap_reserved_size_bytes();
 
   // Ensure that the sizes are properly aligned.
   Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
-  Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
-  Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
+  Universe::check_alignment(reserved_byte_size, HeapRegion::GrainBytes, "g1 heap");
+  Universe::check_alignment(reserved_byte_size, HeapAlignment, "g1 heap");
 
   // Reserve the maximum.
 
@@ -1666,8 +1661,8 @@
   // If this happens then we could end up using a non-optimal
   // compressed oops mode.
 
-  ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size,
-                                                 heap_alignment);
+  ReservedSpace heap_rs = Universe::reserve_heap(reserved_byte_size,
+                                                 HeapAlignment);
 
   initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*)(heap_rs.base() + heap_rs.size()));
 
@@ -1699,7 +1694,7 @@
   _hot_card_cache = new G1HotCardCache(this);
 
   // Carve out the G1 part of the heap.
-  ReservedSpace g1_rs = heap_rs.first_part(max_byte_size);
+  ReservedSpace g1_rs = heap_rs.first_part(reserved_byte_size);
   size_t page_size = actual_reserved_page_size(heap_rs);
   G1RegionToSpaceMapper* heap_storage =
     G1RegionToSpaceMapper::create_heap_mapper(g1_rs,
@@ -1714,8 +1709,8 @@
   }
 
   os::trace_page_sizes("Heap",
-                       collector_policy()->min_heap_byte_size(),
-                       max_byte_size,
+                       MinHeapSize,
+                       reserved_byte_size,
                        page_size,
                        heap_rs.base(),
                        heap_rs.size());
@@ -1743,7 +1738,7 @@
   G1RegionToSpaceMapper* next_bitmap_storage =
     create_aux_memory_mapper("Next Bitmap", bitmap_size, G1CMBitMap::heap_map_factor());
 
-  _hrm = HeapRegionManager::create_manager(this, _collector_policy);
+  _hrm = HeapRegionManager::create_manager(this);
 
   _hrm->initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
   _card_table->initialize(cardtable_storage);
@@ -1870,10 +1865,6 @@
   SuspendibleThreadSet::desynchronize();
 }
 
-size_t G1CollectedHeap::conservative_max_heap_alignment() {
-  return HeapRegion::max_region_size();
-}
-
 void G1CollectedHeap::post_initialize() {
   CollectedHeap::post_initialize();
   ref_processing_init();
@@ -1940,10 +1931,6 @@
                            true);                                // allow changes to number of processing threads
 }
 
-CollectorPolicy* G1CollectedHeap::collector_policy() const {
-  return _collector_policy;
-}
-
 SoftRefPolicy* G1CollectedHeap::soft_ref_policy() {
   return &_soft_ref_policy;
 }
@@ -2066,7 +2053,7 @@
 }
 
 void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
-  MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
 
   // We assume that if concurrent == true, then the caller is a
   // concurrent thread that was joined the Suspendible Thread
@@ -2333,7 +2320,7 @@
 }
 
 bool G1CollectedHeap::is_heterogeneous_heap() const {
-  return _collector_policy->is_heterogeneous_heap();
+  return G1Arguments::is_heterogeneous_heap();
 }
 
 class PrintRegionClosure: public HeapRegionClosure {
@@ -2604,7 +2591,7 @@
 }
 
 void G1CollectedHeap::do_concurrent_mark() {
-  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
   if (!_cm_thread->in_progress()) {
     _cm_thread->set_started();
     CGC_lock->notify();
@@ -3925,7 +3912,7 @@
 void G1CollectedHeap::remove_from_old_sets(const uint old_regions_removed,
                                            const uint humongous_regions_removed) {
   if (old_regions_removed > 0 || humongous_regions_removed > 0) {
-    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag);
     _old_set.bulk_remove(old_regions_removed);
     _humongous_set.bulk_remove(humongous_regions_removed);
   }
@@ -3935,7 +3922,7 @@
 void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) {
   assert(list != NULL, "list can't be null");
   if (!list->is_empty()) {
-    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag);
     _hrm->insert_list_into_free_list(list);
   }
 }
@@ -4073,7 +4060,7 @@
 
   void do_serial_work() {
     // Need to grab the lock to be allowed to modify the old region list.
-    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag);
     _collection_set->iterate(&_cl);
   }
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -74,7 +74,6 @@
 class CompactibleSpaceClosure;
 class Space;
 class G1CollectionSet;
-class G1CollectorPolicy;
 class G1Policy;
 class G1HotCardCache;
 class G1RemSet;
@@ -156,7 +155,6 @@
   G1YoungRemSetSamplingThread* _young_gen_sampling_thread;
 
   WorkGang* _workers;
-  G1CollectorPolicy* _collector_policy;
   G1CardTable* _card_table;
 
   SoftRefPolicy      _soft_ref_policy;
@@ -926,10 +924,10 @@
   // A set of cards where updates happened during the GC
   G1DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
 
-  // Create a G1CollectedHeap with the specified policy.
+  // Create a G1CollectedHeap.
   // Must call the initialize method afterwards.
   // May not return if something goes wrong.
-  G1CollectedHeap(G1CollectorPolicy* policy);
+  G1CollectedHeap();
 
 private:
   jint initialize_concurrent_refinement();
@@ -944,9 +942,6 @@
   virtual void safepoint_synchronize_begin();
   virtual void safepoint_synchronize_end();
 
-  // Return the (conservative) maximum heap alignment for any G1 heap
-  static size_t conservative_max_heap_alignment();
-
   // Does operations required after initialization has been done.
   void post_initialize();
 
@@ -976,8 +971,6 @@
   const G1CollectionSet* collection_set() const { return &_collection_set; }
   G1CollectionSet* collection_set() { return &_collection_set; }
 
-  virtual CollectorPolicy* collector_policy() const;
-
   virtual SoftRefPolicy* soft_ref_policy();
 
   virtual void initialize_serviceability();
@@ -1008,6 +1001,7 @@
   ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; }
 
   size_t unused_committed_regions_in_bytes() const;
+
   virtual size_t capacity() const;
   virtual size_t used() const;
   // This should be called when we're not holding the heap lock. The
--- a/src/hotspot/share/gc/g1/g1CollectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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/g1Analytics.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
-#include "gc/g1/g1YoungGenSizer.hpp"
-#include "gc/g1/heapRegion.hpp"
-#include "gc/g1/heapRegionRemSet.hpp"
-#include "gc/shared/gcPolicyCounters.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/debug.hpp"
-
-G1CollectorPolicy::G1CollectorPolicy() {
-
-  // Set up the region size and associated fields. Given that the
-  // policy is created before the heap, we have to set this up here,
-  // so it's done as soon as possible.
-
-  // It would have been natural to pass initial_heap_byte_size() and
-  // max_heap_byte_size() to setup_heap_region_size() but those have
-  // not been set up at this point since they should be aligned with
-  // the region size. So, there is a circular dependency here. We base
-  // the region size on the heap size, but the heap size should be
-  // aligned with the region size. To get around this we use the
-  // unaligned values for the heap.
-  HeapRegion::setup_heap_region_size(InitialHeapSize, MaxHeapSize);
-  HeapRegionRemSet::setup_remset_size();
-}
-
-void G1CollectorPolicy::initialize_alignments() {
-  _space_alignment = HeapRegion::GrainBytes;
-  size_t card_table_alignment = CardTableRS::ct_max_alignment_constraint();
-  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
-  _heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size);
-}
-
-size_t G1CollectorPolicy::heap_reserved_size_bytes() const {
-  return _max_heap_byte_size;
-}
-
-bool G1CollectorPolicy::is_heterogeneous_heap() const {
-  return false;
-}
--- a/src/hotspot/share/gc/g1/g1CollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_G1COLLECTORPOLICY_HPP
-#define SHARE_GC_G1_G1COLLECTORPOLICY_HPP
-
-#include "gc/shared/collectorPolicy.hpp"
-
-// G1CollectorPolicy is primarily used during initialization and to expose the
-// functionality of the CollectorPolicy interface to the rest of the VM.
-
-class G1YoungGenSizer;
-
-class G1CollectorPolicy: public CollectorPolicy {
-protected:
-  void initialize_alignments();
-
-public:
-  G1CollectorPolicy();
-  virtual size_t heap_reserved_size_bytes() const;
-  virtual bool is_heterogeneous_heap() const;
-};
-#endif // SHARE_GC_G1_G1COLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Fri May 03 14:59:32 2019 -0400
@@ -166,13 +166,13 @@
 }
 
 void G1CMMarkStack::add_chunk_to_chunk_list(TaskQueueEntryChunk* elem) {
-  MutexLockerEx x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag);
   add_chunk_to_list(&_chunk_list, elem);
   _chunks_in_chunk_list++;
 }
 
 void G1CMMarkStack::add_chunk_to_free_list(TaskQueueEntryChunk* elem) {
-  MutexLockerEx x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag);
   add_chunk_to_list(&_free_list, elem);
 }
 
@@ -185,7 +185,7 @@
 }
 
 G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::remove_chunk_from_chunk_list() {
-  MutexLockerEx x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MarkStackChunkList_lock, Mutex::_no_safepoint_check_flag);
   TaskQueueEntryChunk* result = remove_chunk_from_list(&_chunk_list);
   if (result != NULL) {
     _chunks_in_chunk_list--;
@@ -194,7 +194,7 @@
 }
 
 G1CMMarkStack::TaskQueueEntryChunk* G1CMMarkStack::remove_chunk_from_free_list() {
-  MutexLockerEx x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MarkStackFreeList_lock, Mutex::_no_safepoint_check_flag);
   return remove_chunk_from_list(&_free_list);
 }
 
@@ -311,7 +311,7 @@
 }
 
 void G1CMRootRegions::notify_scan_done() {
-  MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
   _scan_in_progress = false;
   RootRegionScan_lock->notify_all();
 }
@@ -338,9 +338,9 @@
   }
 
   {
-    MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
     while (scan_in_progress()) {
-      RootRegionScan_lock->wait(Mutex::_no_safepoint_check_flag);
+      ml.wait();
     }
   }
   return true;
@@ -1288,7 +1288,7 @@
     // Now update the old/humongous region sets
     _g1h->remove_from_old_sets(cl.old_regions_removed(), cl.humongous_regions_removed());
     {
-      MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
       _g1h->decrement_summary_bytes(cl.freed_bytes());
 
       _cleanup_list->add_ordered(&local_cleanup_list);
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -397,7 +397,7 @@
 }
 
 void G1ConcurrentMarkThread::stop_service() {
-  MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(CGC_lock, Mutex::_no_safepoint_check_flag);
   CGC_lock->notify_all();
 }
 
@@ -407,9 +407,9 @@
   // below while the world is otherwise stopped.
   assert(!in_progress(), "should have been cleared");
 
-  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGC_lock, Mutex::_no_safepoint_check_flag);
   while (!started() && !should_terminate()) {
-    CGC_lock->wait(Mutex::_no_safepoint_check_flag);
+    ml.wait();
   }
 
   if (started()) {
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -59,9 +59,9 @@
 }
 
 void G1ConcurrentRefineThread::wait_for_completed_buffers() {
-  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
   while (!should_terminate() && !is_active()) {
-    _monitor->wait(Mutex::_no_safepoint_check_flag);
+    ml.wait();
   }
 }
 
@@ -71,7 +71,7 @@
 }
 
 void G1ConcurrentRefineThread::activate() {
-  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
   if (!is_primary()) {
     set_active(true);
   } else {
@@ -82,7 +82,7 @@
 }
 
 void G1ConcurrentRefineThread::deactivate() {
-  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
   if (!is_primary()) {
     set_active(false);
   } else {
@@ -140,6 +140,6 @@
 }
 
 void G1ConcurrentRefineThread::stop_service() {
-  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
   _monitor->notify();
 }
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 #include "precompiled.hpp"
 #include "code/codeCache.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1FullCollector.hpp"
 #include "gc/g1/g1FullGCAdjustTask.hpp"
 #include "gc/g1/g1FullGCCompactTask.hpp"
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp	Fri May 03 14:59:32 2019 -0400
@@ -62,8 +62,7 @@
     oop obj = CompressedOops::decode_not_null(heap_oop);
     bool failed = false;
     if (!_g1h->is_in(obj) || _g1h->is_obj_dead_cond(obj, _verify_option)) {
-      MutexLockerEx x(ParGCRareEvent_lock,
-          Mutex::_no_safepoint_check_flag);
+      MutexLocker x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
       LogStreamHandle(Error, gc, verify) yy;
       if (!_failures) {
         yy.cr();
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Fri May 03 14:59:32 2019 -0400
@@ -60,9 +60,8 @@
   _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):");
   _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):");
   _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):");
-#if INCLUDE_AOT
-  _gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scan (ms):");
-#endif
+  AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scan (ms):");)
+  JVMCI_ONLY(_gc_par_phases[JVMCIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMCI Root Scan (ms):");)
   _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):");
   _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
   _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
@@ -527,9 +526,8 @@
       "SystemDictionaryRoots",
       "CLDGRoots",
       "JVMTIRoots",
-#if INCLUDE_AOT
-      "AOTCodeRoots",
-#endif
+      AOT_ONLY("AOTCodeRoots" COMMA)
+      JVMCI_ONLY("JVMCIRoots" COMMA)
       "CMRefRoots",
       "WaitForStrongCLD",
       "WeakCLDRoots",
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Fri May 03 14:59:32 2019 -0400
@@ -55,9 +55,8 @@
     SystemDictionaryRoots,
     CLDGRoots,
     JVMTIRoots,
-#if INCLUDE_AOT
-    AOTCodeRoots,
-#endif
+    AOT_ONLY(AOTCodeRoots COMMA)
+    JVMCI_ONLY(JVMCIRoots COMMA)
     CMRefRoots,
     WaitForStrongCLD,
     WeakCLDRoots,
--- a/src/hotspot/share/gc/g1/g1HeterogeneousCollectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * 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 "precompiled.hpp"
-#include "gc/g1/g1HeterogeneousCollectorPolicy.hpp"
-#include "logging/log.hpp"
-#include "runtime/globals_extension.hpp"
-#include "runtime/os.hpp"
-#include "utilities/formatBuffer.hpp"
-
-const double G1HeterogeneousCollectorPolicy::MaxRamFractionForYoung = 0.8;
-size_t G1HeterogeneousCollectorPolicy::MaxMemoryForYoung;
-
-static size_t calculate_reasonable_max_memory_for_young(FormatBuffer<100> &calc_str, double max_ram_fraction_for_young) {
-  julong phys_mem;
-  // If MaxRam is specified, we use that as maximum physical memory available.
-  if (FLAG_IS_DEFAULT(MaxRAM)) {
-    phys_mem = os::physical_memory();
-    calc_str.append("Physical_Memory");
-  } else {
-    phys_mem = (julong)MaxRAM;
-    calc_str.append("MaxRAM");
-  }
-
-  julong reasonable_max = phys_mem;
-
-  // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
-  // reasonable max size of young generation.
-  if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
-    reasonable_max = (julong)(phys_mem / MaxRAMFraction);
-    calc_str.append(" / MaxRAMFraction");
-  }  else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
-    reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
-    calc_str.append(" * MaxRAMPercentage / 100");
-  }  else {
-    // We use our own fraction to calculate max size of young generation.
-    reasonable_max = phys_mem * max_ram_fraction_for_young;
-    calc_str.append(" * %0.2f", max_ram_fraction_for_young);
-  }
-
-  return (size_t)reasonable_max;
-}
-
-void G1HeterogeneousCollectorPolicy::initialize_flags() {
-
-  FormatBuffer<100> calc_str("");
-
-  MaxMemoryForYoung = calculate_reasonable_max_memory_for_young(calc_str, MaxRamFractionForYoung);
-
-  if (MaxNewSize > MaxMemoryForYoung) {
-    if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
-                            MaxMemoryForYoung, calc_str.buffer());
-    } else {
-      log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
-                         "Dram usage can be lowered by setting MaxNewSize to a lower value", MaxMemoryForYoung, calc_str.buffer());
-    }
-    MaxNewSize = MaxMemoryForYoung;
-  }
-  if (NewSize > MaxMemoryForYoung) {
-    if (FLAG_IS_CMDLINE(NewSize)) {
-      log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
-                            MaxMemoryForYoung, calc_str.buffer());
-    }
-    NewSize = MaxMemoryForYoung;
-  }
-
-  // After setting new size flags, call base class initialize_flags()
-  G1CollectorPolicy::initialize_flags();
-}
-
-size_t G1HeterogeneousCollectorPolicy::reasonable_max_memory_for_young() {
-  return MaxMemoryForYoung;
-}
-
-size_t G1HeterogeneousCollectorPolicy::heap_reserved_size_bytes() const {
-    return 2 * _max_heap_byte_size;
-}
-
-bool G1HeterogeneousCollectorPolicy::is_heterogeneous_heap() const {
-  return true;
-}
--- a/src/hotspot/share/gc/g1/g1HeterogeneousCollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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.
- *
- */
-
-#ifndef SHARE_GC_G1_G1HETEROGENEOUSCOLLECTORPOLICY_HPP
-#define SHARE_GC_G1_G1HETEROGENEOUSCOLLECTORPOLICY_HPP
-
-#include "gc/g1/g1CollectorPolicy.hpp"
-#include "gc/g1/g1HeterogeneousHeapYoungGenSizer.hpp"
-
-class G1HeterogeneousCollectorPolicy : public G1CollectorPolicy {
-private:
-  // Max fraction of dram to use for young generation when MaxRAMFraction and
-  // MaxRAMPercentage are not specified on commandline.
-  static const double MaxRamFractionForYoung;
-  static size_t MaxMemoryForYoung;
-
-protected:
-  virtual void initialize_flags();
-
-public:
-  G1HeterogeneousCollectorPolicy() {}
-  virtual size_t heap_reserved_size_bytes() const;
-  virtual bool is_heterogeneous_heap() const;
-  static size_t reasonable_max_memory_for_young();
-};
-
-#endif // SHARE_GC_G1_G1HETEROGENEOUSCOLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -28,8 +28,8 @@
 #include "gc/g1/g1Policy.hpp"
 #include "gc/g1/heterogeneousHeapRegionManager.hpp"
 
-G1HeterogeneousHeapPolicy::G1HeterogeneousHeapPolicy(G1CollectorPolicy* policy, STWGCTimer* gc_timer) :
-  G1Policy(policy, gc_timer), _manager(NULL) {}
+G1HeterogeneousHeapPolicy::G1HeterogeneousHeapPolicy(STWGCTimer* gc_timer) :
+  G1Policy(gc_timer), _manager(NULL) {}
 
 // We call the super class init(), after which we provision young_list_target_length() regions in dram.
 void G1HeterogeneousHeapPolicy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) {
--- a/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 #ifndef SHARE_GC_G1_G1HETEROGENEOUSHEAPPOLICY_HPP
 #define SHARE_GC_G1_G1HETEROGENEOUSHEAPPOLICY_HPP
 
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1Policy.hpp"
 #include "gc/g1/heterogeneousHeapRegionManager.hpp"
 
@@ -34,7 +33,7 @@
   HeterogeneousHeapRegionManager* _manager;
 
 public:
-  G1HeterogeneousHeapPolicy(G1CollectorPolicy* policy, STWGCTimer* gc_timer);
+  G1HeterogeneousHeapPolicy(STWGCTimer* gc_timer);
 
   // initialize policy
   virtual void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
--- a/src/hotspot/share/gc/g1/g1HeterogeneousHeapYoungGenSizer.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapYoungGenSizer.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,13 +23,13 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/g1/g1HeterogeneousCollectorPolicy.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1HeterogeneousHeapYoungGenSizer.hpp"
 #include "gc/g1/heapRegion.hpp"
 
 G1HeterogeneousHeapYoungGenSizer::G1HeterogeneousHeapYoungGenSizer() : G1YoungGenSizer() {
   // will be used later when min and max young size is calculated.
-  _max_young_length = (uint)(G1HeterogeneousCollectorPolicy::reasonable_max_memory_for_young() / HeapRegion::GrainBytes);
+  _max_young_length = (uint)(G1Arguments::reasonable_max_memory_for_young() / HeapRegion::GrainBytes);
 }
 
 // Since heap is sized potentially to larger value accounting for dram + nvdimm, we need to limit
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Fri May 03 14:59:32 2019 -0400
@@ -203,7 +203,7 @@
 }
 
 MemoryUsage G1MonitoringSupport::memory_usage() {
-  MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
   return MemoryUsage(InitialHeapSize, _overall_used, _overall_committed, _g1h->max_capacity());
 }
 
@@ -225,7 +225,7 @@
 void G1MonitoringSupport::recalculate_sizes() {
   assert_heap_locked_or_at_safepoint(true);
 
-  MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
   // Recalculate all the sizes from scratch.
 
   // This never includes used bytes of current allocating heap region.
@@ -317,7 +317,7 @@
 }
 
 MemoryUsage G1MonitoringSupport::eden_space_memory_usage(size_t initial_size, size_t max_size) {
-  MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
 
   return MemoryUsage(initial_size,
                      _eden_space_used,
@@ -326,7 +326,7 @@
 }
 
 MemoryUsage G1MonitoringSupport::survivor_space_memory_usage(size_t initial_size, size_t max_size) {
-  MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
 
   return MemoryUsage(initial_size,
                      _survivor_space_used,
@@ -335,7 +335,7 @@
 }
 
 MemoryUsage G1MonitoringSupport::old_gen_memory_usage(size_t initial_size, size_t max_size) {
-  MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
 
   return MemoryUsage(initial_size,
                      _old_gen_used,
--- a/src/hotspot/share/gc/g1/g1Policy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/g1/g1Analytics.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectionSetCandidates.hpp"
@@ -49,7 +50,7 @@
 #include "utilities/growableArray.hpp"
 #include "utilities/pair.hpp"
 
-G1Policy::G1Policy(G1CollectorPolicy* policy, STWGCTimer* gc_timer) :
+G1Policy::G1Policy(STWGCTimer* gc_timer) :
   _predictor(G1ConfidencePercent / 100.0),
   _analytics(new G1Analytics(&_predictor)),
   _remset_tracker(),
@@ -65,7 +66,7 @@
   _survivor_surv_rate_group(new SurvRateGroup()),
   _reserve_factor((double) G1ReservePercent / 100.0),
   _reserve_regions(0),
-  _young_gen_sizer(G1YoungGenSizer::create_gen_sizer(policy)),
+  _young_gen_sizer(G1YoungGenSizer::create_gen_sizer()),
   _free_regions_at_end_of_collection(0),
   _max_rs_lengths(0),
   _rs_lengths_prediction(0),
@@ -89,11 +90,11 @@
   delete _young_gen_sizer;
 }
 
-G1Policy* G1Policy::create_policy(G1CollectorPolicy* policy, STWGCTimer* gc_timer_stw) {
-  if (policy->is_heterogeneous_heap()) {
-    return new G1HeterogeneousHeapPolicy(policy, gc_timer_stw);
+G1Policy* G1Policy::create_policy(STWGCTimer* gc_timer_stw) {
+  if (G1Arguments::is_heterogeneous_heap()) {
+    return new G1HeterogeneousHeapPolicy(gc_timer_stw);
   } else {
-    return new G1Policy(policy, gc_timer_stw);
+    return new G1Policy(gc_timer_stw);
   }
 }
 
--- a/src/hotspot/share/gc/g1/g1Policy.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 #ifndef SHARE_GC_G1_G1POLICY_HPP
 #define SHARE_GC_G1_G1POLICY_HPP
 
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1InCSetState.hpp"
@@ -284,11 +283,11 @@
   void abort_time_to_mixed_tracking();
 public:
 
-  G1Policy(G1CollectorPolicy* policy, STWGCTimer* gc_timer);
+  G1Policy(STWGCTimer* gc_timer);
 
   virtual ~G1Policy();
 
-  static G1Policy* create_policy(G1CollectorPolicy* policy, STWGCTimer* gc_timer_stw);
+  static G1Policy* create_policy(STWGCTimer* gc_timer_stw);
 
   G1CollectorState* collector_state() const;
 
--- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Fri May 03 14:59:32 2019 -0400
@@ -43,6 +43,9 @@
 #include "runtime/mutex.hpp"
 #include "services/management.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 void G1RootProcessor::worker_has_discovered_all_strong_classes() {
   assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
@@ -50,7 +53,7 @@
   uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
   if (new_value == n_workers()) {
     // This thread is last. Notify the others.
-    MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
     _lock.notify_all();
   }
 }
@@ -59,9 +62,9 @@
   assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
 
   if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
-    MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
     while ((uint)_n_workers_discovered_strong_classes != n_workers()) {
-      _lock.wait(Mutex::_no_safepoint_check_flag, 0, false);
+      ml.wait(0);
     }
   }
 }
@@ -267,6 +270,15 @@
   }
 #endif
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMCIRoots, worker_i);
+    if (_process_strong_tasks.try_claim_task(G1RP_PS_JVMCI_oops_do)) {
+      JVMCI::oops_do(strong_roots);
+    }
+  }
+#endif
+
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
     if (_process_strong_tasks.try_claim_task(G1RP_PS_SystemDictionary_oops_do)) {
--- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Fri May 03 14:59:32 2019 -0400
@@ -63,7 +63,8 @@
     G1RP_PS_ClassLoaderDataGraph_oops_do,
     G1RP_PS_jvmti_oops_do,
     G1RP_PS_CodeCache_oops_do,
-    G1RP_PS_aot_oops_do,
+    AOT_ONLY(G1RP_PS_aot_oops_do COMMA)
+    JVMCI_ONLY(G1RP_PS_JVMCI_oops_do COMMA)
     G1RP_PS_filter_satb_buffers,
     G1RP_PS_refProcessor_oops_do,
     // Leave this one last.
--- a/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.cpp	Fri May 03 14:59:32 2019 -0400
@@ -40,7 +40,7 @@
 }
 
 void G1SharedDirtyCardQueue::enqueue(void* card_ptr) {
-  MutexLockerEx ml(Shared_DirtyCardQ_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Shared_DirtyCardQ_lock, Mutex::_no_safepoint_check_flag);
   if (_index == 0) {
     flush();
     _buffer = _qset->allocate_buffer();
--- a/src/hotspot/share/gc/g1/g1StringDedupQueue.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1StringDedupQueue.cpp	Fri May 03 14:59:32 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
@@ -54,14 +54,14 @@
 }
 
 void G1StringDedupQueue::wait_impl() {
-  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
   while (_empty && !_cancel) {
-    ml.wait(Mutex::_no_safepoint_check_flag);
+    ml.wait();
   }
 }
 
 void G1StringDedupQueue::cancel_wait_impl() {
-  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
   _cancel = true;
   ml.notify();
 }
@@ -75,7 +75,7 @@
   if (!worker_queue.is_full()) {
     worker_queue.push(java_string);
     if (_empty) {
-      MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+      MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
       if (_empty) {
         // Mark non-empty and notify waiter
         _empty = false;
--- a/src/hotspot/share/gc/g1/g1VMOperations.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp	Fri May 03 14:59:32 2019 -0400
@@ -191,10 +191,10 @@
       JavaThread* jt = (JavaThread*)thr;
       ThreadToNativeFromVM native(jt);
 
-      MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+      MonitorLocker ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
       while (g1h->old_marking_cycles_completed() <=
                                           _old_marking_cycles_completed_before) {
-        FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
+        ml.wait();
       }
     }
   }
--- a/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1HeterogeneousHeapYoungGenSizer.hpp"
 #include "gc/g1/g1YoungGenSizer.hpp"
 #include "gc/g1/heapRegion.hpp"
@@ -130,8 +130,8 @@
           &_max_desired_young_length);
 }
 
-G1YoungGenSizer* G1YoungGenSizer::create_gen_sizer(G1CollectorPolicy* policy) {
-  if (policy->is_heterogeneous_heap()) {
+G1YoungGenSizer* G1YoungGenSizer::create_gen_sizer() {
+  if (G1Arguments::is_heterogeneous_heap()) {
     return new G1HeterogeneousHeapYoungGenSizer();
   } else {
     return new G1YoungGenSizer();
--- a/src/hotspot/share/gc/g1/g1YoungGenSizer.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 #ifndef SHARE_GC_G1_G1YOUNGGENSIZER_HPP
 #define SHARE_GC_G1_G1YOUNGGENSIZER_HPP
 
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 // There are three command line options related to the young gen size:
@@ -108,7 +107,7 @@
     return _use_adaptive_sizing;
   }
 
-  static G1YoungGenSizer* create_gen_sizer(G1CollectorPolicy* policy);
+  static G1YoungGenSizer* create_gen_sizer();
 };
 
 #endif // SHARE_GC_G1_G1YOUNGGENSIZER_HPP
--- a/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -47,10 +47,10 @@
 }
 
 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
-  MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
   if (!should_terminate()) {
     uintx waitms = G1ConcRefinementServiceIntervalMillis;
-    _monitor.wait(Mutex::_no_safepoint_check_flag, waitms);
+    ml.wait(waitms);
   }
 }
 
@@ -124,7 +124,7 @@
 }
 
 void G1YoungRemSetSamplingThread::stop_service() {
-  MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(&_monitor, Mutex::_no_safepoint_check_flag);
   _monitor.notify();
 }
 
--- a/src/hotspot/share/gc/g1/heapRegion.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp	Fri May 03 14:59:32 2019 -0400
@@ -516,7 +516,7 @@
       oop obj = CompressedOops::decode_not_null(heap_oop);
       bool failed = false;
       if (!_g1h->is_in(obj) || _g1h->is_obj_dead_cond(obj, _vo)) {
-        MutexLockerEx x(ParGCRareEvent_lock,
+        MutexLocker x(ParGCRareEvent_lock,
           Mutex::_no_safepoint_check_flag);
 
         if (!_failures) {
@@ -588,7 +588,7 @@
                 cv_field == dirty :
                 cv_obj == dirty || cv_field == dirty));
         if (is_bad) {
-          MutexLockerEx x(ParGCRareEvent_lock,
+          MutexLocker x(ParGCRareEvent_lock,
             Mutex::_no_safepoint_check_flag);
 
           if (!_failures) {
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,13 +23,13 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/heapRegionManager.inline.hpp"
 #include "gc/g1/heapRegionSet.inline.hpp"
 #include "gc/g1/heterogeneousHeapRegionManager.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/bitMap.inline.hpp"
 
@@ -68,9 +68,9 @@
   _free_list("Free list", new MasterFreeRegionListChecker())
 { }
 
-HeapRegionManager* HeapRegionManager::create_manager(G1CollectedHeap* heap, G1CollectorPolicy* policy) {
-  if (policy->is_heterogeneous_heap()) {
-    return new HeterogeneousHeapRegionManager((uint)(policy->max_heap_byte_size() / HeapRegion::GrainBytes) /*heap size as num of regions*/);
+HeapRegionManager* HeapRegionManager::create_manager(G1CollectedHeap* heap) {
+  if (G1Arguments::is_heterogeneous_heap()) {
+    return new HeterogeneousHeapRegionManager((uint)(G1Arguments::heap_reserved_size_bytes() / HeapRegion::GrainBytes) /*heap size as num of regions*/);
   }
   return new HeapRegionManager();
 }
--- a/src/hotspot/share/gc/g1/heapRegionManager.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp	Fri May 03 14:59:32 2019 -0400
@@ -26,10 +26,8 @@
 #define SHARE_GC_G1_HEAPREGIONMANAGER_HPP
 
 #include "gc/g1/g1BiasedArray.hpp"
-#include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1RegionToSpaceMapper.hpp"
 #include "gc/g1/heapRegionSet.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "services/memoryUsage.hpp"
 
 class HeapRegion;
@@ -129,7 +127,7 @@
   // Empty constructor, we'll initialize it with the initialize() method.
   HeapRegionManager();
 
-  static HeapRegionManager* create_manager(G1CollectedHeap* heap, G1CollectorPolicy* policy);
+  static HeapRegionManager* create_manager(G1CollectedHeap* heap);
 
   virtual void initialize(G1RegionToSpaceMapper* heap_storage,
                           G1RegionToSpaceMapper* prev_bitmap,
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp	Fri May 03 14:59:32 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
@@ -361,7 +361,7 @@
   size_t ind = from_hrm_ind & _mod_max_fine_entries_mask;
   PerRegionTable* prt = find_region_table(ind, from_hr);
   if (prt == NULL) {
-    MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_m, Mutex::_no_safepoint_check_flag);
     // Confirm that it's really not there...
     prt = find_region_table(ind, from_hr);
     if (prt == NULL) {
@@ -577,7 +577,7 @@
 
 bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
   // Cast away const in this case.
-  MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag);
+  MutexLocker x((Mutex*)_m, Mutex::_no_safepoint_check_flag);
   return contains_reference_locked(from);
 }
 
@@ -628,7 +628,7 @@
 }
 
 void HeapRegionRemSet::clear(bool only_cardset) {
-  MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(&_m, Mutex::_no_safepoint_check_flag);
   clear_locked(only_cardset);
 }
 
@@ -658,7 +658,7 @@
           BOOL_TO_STR(CodeCache_lock->owned_by_self()), BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()));
   // Optimistic unlocked contains-check
   if (!_code_roots.contains(nm)) {
-    MutexLockerEx ml(&_m, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(&_m, Mutex::_no_safepoint_check_flag);
     add_strong_code_root_locked(nm);
   }
 }
@@ -678,7 +678,7 @@
   assert(nm != NULL, "sanity");
   assert_locked_or_safepoint(CodeCache_lock);
 
-  MutexLockerEx ml(CodeCache_lock->owned_by_self() ? NULL : &_m, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(CodeCache_lock->owned_by_self() ? NULL : &_m, Mutex::_no_safepoint_check_flag);
   _code_roots.remove(nm);
 
   // Check that there were no duplicates
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp	Fri May 03 14:59:32 2019 -0400
@@ -194,7 +194,7 @@
   }
 
   size_t occupied() {
-    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(&_m, Mutex::_no_safepoint_check_flag);
     return occupied_locked();
   }
   size_t occupied_locked() {
@@ -274,7 +274,7 @@
   // The actual # of bytes this hr_remset takes up.
   // Note also includes the strong code root set.
   size_t mem_size() {
-    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(&_m, Mutex::_no_safepoint_check_flag);
     return _other_regions.mem_size()
       // This correction is necessary because the above includes the second
       // part.
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp	Fri May 03 14:59:32 2019 -0400
@@ -26,8 +26,9 @@
 #include "gc/parallel/adjoiningGenerations.hpp"
 #include "gc/parallel/adjoiningGenerationsForHeteroHeap.hpp"
 #include "gc/parallel/adjoiningVirtualSpaces.hpp"
-#include "gc/parallel/generationSizer.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/parallel/parallelArguments.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
@@ -38,17 +39,15 @@
 // gen with ASPSYoungGen and ASPSOldGen, respectively.  Revert to
 // the old behavior otherwise (with PSYoungGen and PSOldGen).
 
-AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs,
-                                           GenerationSizer* policy,
-                                           size_t alignment) :
-  _virtual_spaces(new AdjoiningVirtualSpaces(old_young_rs, policy->min_old_size(),
-                                             policy->min_young_size(), alignment)) {
-  size_t init_low_byte_size = policy->initial_old_size();
-  size_t min_low_byte_size = policy->min_old_size();
-  size_t max_low_byte_size = policy->max_old_size();
-  size_t init_high_byte_size = policy->initial_young_size();
-  size_t min_high_byte_size = policy->min_young_size();
-  size_t max_high_byte_size = policy->max_young_size();
+AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs) :
+  _virtual_spaces(new AdjoiningVirtualSpaces(old_young_rs, MinOldSize,
+                                             MinNewSize, GenAlignment)) {
+  size_t init_low_byte_size = OldSize;
+  size_t min_low_byte_size = MinOldSize;
+  size_t max_low_byte_size = MaxOldSize;
+  size_t init_high_byte_size = NewSize;
+  size_t min_high_byte_size = MinNewSize;
+  size_t max_high_byte_size = MaxNewSize;
 
   assert(min_low_byte_size <= init_low_byte_size &&
          init_low_byte_size <= max_low_byte_size, "Parameter check");
@@ -95,7 +94,7 @@
     // Layout the reserved space for the generations.
     // If OldGen is allocated on nv-dimm, we need to split the reservation (this is required for windows).
     ReservedSpace old_rs   =
-      virtual_spaces()->reserved_space().first_part(max_low_byte_size, policy->is_hetero_heap() /* split */);
+      virtual_spaces()->reserved_space().first_part(max_low_byte_size, ParallelArguments::is_heterogeneous_heap() /* split */);
     ReservedSpace heap_rs  =
       virtual_spaces()->reserved_space().last_part(max_low_byte_size);
     ReservedSpace young_rs = heap_rs.first_part(max_high_byte_size);
@@ -111,10 +110,10 @@
                             "old", 1);
 
     // The virtual spaces are created by the initialization of the gens.
-    _young_gen->initialize(young_rs, alignment);
+    _young_gen->initialize(young_rs, GenAlignment);
     assert(young_gen()->gen_size_limit() == young_rs.size(),
       "Consistency check");
-    _old_gen->initialize(old_rs, alignment, "old", 1);
+    _old_gen->initialize(old_rs, GenAlignment, "old", 1);
     assert(old_gen()->gen_size_limit() == old_rs.size(), "Consistency check");
   }
 }
@@ -284,12 +283,10 @@
   }
 }
 
-AdjoiningGenerations* AdjoiningGenerations::create_adjoining_generations(ReservedSpace old_young_rs,
-                                                                         GenerationSizer* policy,
-                                                                         size_t alignment) {
-  if (policy->is_hetero_heap() && UseAdaptiveGCBoundary) {
-    return new AdjoiningGenerationsForHeteroHeap(old_young_rs, policy, alignment);
+AdjoiningGenerations* AdjoiningGenerations::create_adjoining_generations(ReservedSpace old_young_rs) {
+  if (ParallelArguments::is_heterogeneous_heap() && UseAdaptiveGCBoundary) {
+    return new AdjoiningGenerationsForHeteroHeap(old_young_rs);
   } else {
-    return new AdjoiningGenerations(old_young_rs, policy, alignment);
+    return new AdjoiningGenerations(old_young_rs);
   }
 }
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,6 @@
 #include "gc/parallel/adjoiningVirtualSpaces.hpp"
 #include "gc/parallel/asPSOldGen.hpp"
 #include "gc/parallel/asPSYoungGen.hpp"
-#include "gc/parallel/generationSizer.hpp"
 
 
 // Contains two generations that both use an AdjoiningVirtualSpaces.
@@ -59,7 +58,7 @@
    AdjoiningVirtualSpaces* _virtual_spaces;
 
  public:
-  AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
+  AdjoiningGenerations(ReservedSpace rs);
 
   // Accessors
   PSYoungGen* young_gen() { return _young_gen; }
@@ -78,7 +77,7 @@
   // for the adjoining generations.
   virtual size_t reserved_byte_size();
 
-  // Return new AdjoiningGenerations instance based on collector policy (specifically - whether heap is heterogeneous).
-  static AdjoiningGenerations* create_adjoining_generations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
+  // Return new AdjoiningGenerations instance based on arguments (specifically - whether heap is heterogeneous).
+  static AdjoiningGenerations* create_adjoining_generations(ReservedSpace rs);
 };
 #endif // SHARE_GC_PARALLEL_ADJOININGGENERATIONS_HPP
--- a/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/parallel/adjoiningGenerationsForHeteroHeap.hpp"
 #include "gc/parallel/adjoiningVirtualSpaces.hpp"
-#include "gc/parallel/generationSizer.hpp"
+#include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "gc/parallel/psFileBackedVirtualspace.hpp"
 #include "logging/log.hpp"
@@ -37,17 +37,17 @@
 // Create two virtual spaces (HeteroVirtualSpaces), low() on nv-dimm memory, high() on dram.
 // create ASPSOldGen and ASPSYoungGen the same way as in base class
 
-AdjoiningGenerationsForHeteroHeap::AdjoiningGenerationsForHeteroHeap(ReservedSpace old_young_rs, GenerationSizer* policy, size_t alignment) :
-  _total_size_limit(policy->max_heap_byte_size()) {
-  size_t init_old_byte_size = policy->initial_old_size();
-  size_t min_old_byte_size = policy->min_old_size();
-  size_t max_old_byte_size = policy->max_old_size();
-  size_t init_young_byte_size = policy->initial_young_size();
-  size_t min_young_byte_size = policy->min_young_size();
-  size_t max_young_byte_size = policy->max_young_size();
+AdjoiningGenerationsForHeteroHeap::AdjoiningGenerationsForHeteroHeap(ReservedSpace old_young_rs) :
+  _total_size_limit(ParallelArguments::heap_reserved_size_bytes()) {
+  size_t init_old_byte_size = OldSize;
+  size_t min_old_byte_size = MinOldSize;
+  size_t max_old_byte_size = MaxOldSize;
+  size_t init_young_byte_size = NewSize;
+  size_t min_young_byte_size = MinNewSize;
+  size_t max_young_byte_size = MaxNewSize;
   // create HeteroVirtualSpaces which is composed of non-overlapping virtual spaces.
   HeteroVirtualSpaces* hetero_virtual_spaces = new HeteroVirtualSpaces(old_young_rs, min_old_byte_size,
-                                                                       min_young_byte_size, _total_size_limit, alignment);
+                                                                       min_young_byte_size, _total_size_limit);
 
   assert(min_old_byte_size <= init_old_byte_size &&
          init_old_byte_size <= max_old_byte_size, "Parameter check");
@@ -83,11 +83,11 @@
   _virtual_spaces = hetero_virtual_spaces;
 }
 
-size_t AdjoiningGenerationsForHeteroHeap::required_reserved_memory(GenerationSizer* policy) {
+size_t AdjoiningGenerationsForHeteroHeap::required_reserved_memory() {
   // This is the size that young gen can grow to, when AdaptiveGCBoundary is true.
-  size_t max_yg_size = policy->max_heap_byte_size() - policy->min_old_size();
+  size_t max_yg_size = ParallelArguments::heap_reserved_size_bytes() - MinOldSize;
   // This is the size that old gen can grow to, when AdaptiveGCBoundary is true.
-  size_t max_old_size = policy->max_heap_byte_size() - policy->min_young_size();
+  size_t max_old_size = ParallelArguments::heap_reserved_size_bytes() - MinNewSize;
 
   return max_yg_size + max_old_size;
 }
@@ -98,10 +98,11 @@
   return total_size_limit();
 }
 
-AdjoiningGenerationsForHeteroHeap::HeteroVirtualSpaces::HeteroVirtualSpaces(ReservedSpace rs, size_t min_old_byte_size, size_t min_yg_byte_size, size_t max_total_size, size_t alignment) :
-                                                                            AdjoiningVirtualSpaces(rs, min_old_byte_size, min_yg_byte_size, alignment),
+AdjoiningGenerationsForHeteroHeap::HeteroVirtualSpaces::HeteroVirtualSpaces(ReservedSpace rs, size_t min_old_byte_size, size_t min_yg_byte_size, size_t max_total_size) :
+                                                                            AdjoiningVirtualSpaces(rs, min_old_byte_size, min_yg_byte_size, GenAlignment),
                                                                             _max_total_size(max_total_size),
-                                                                            _min_old_byte_size(min_old_byte_size), _min_young_byte_size(min_yg_byte_size),
+                                                                            _min_old_byte_size(min_old_byte_size),
+                                                                            _min_young_byte_size(min_yg_byte_size),
                                                                             _max_old_byte_size(_max_total_size - _min_young_byte_size),
                                                                             _max_young_byte_size(_max_total_size - _min_old_byte_size) {
 }
--- a/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -56,8 +56,8 @@
   public:
     HeteroVirtualSpaces(ReservedSpace rs,
                         size_t min_old_byte_size,
-                        size_t min_young_byte_size, size_t max_total_size,
-                        size_t alignment);
+                        size_t min_young_byte_size,
+                        size_t max_total_size);
 
     // Increase old generation size and decrease young generation size by same amount
     bool adjust_boundary_up(size_t size_in_bytes);
@@ -72,11 +72,11 @@
   };
 
 public:
-  AdjoiningGenerationsForHeteroHeap(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
+  AdjoiningGenerationsForHeteroHeap(ReservedSpace rs);
 
   // Given the size policy, calculate the total amount of memory that needs to be reserved.
   // We need to reserve more memory than Xmx, since we use non-overlapping virtual spaces for the young and old generations.
-  static size_t required_reserved_memory(GenerationSizer* policy);
+  static size_t required_reserved_memory();
 
   // Return the total byte size of the reserved space
   size_t reserved_byte_size();
--- a/src/hotspot/share/gc/parallel/asPSOldGen.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/asPSOldGen.cpp	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,7 @@
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
 #include "gc/parallel/psMarkSweepDecorator.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "utilities/align.hpp"
@@ -90,9 +91,8 @@
   assert(virtual_space()->is_aligned(gen_size_limit()), "not aligned");
   assert(gen_size_limit() >= virtual_space()->committed_size(), "bad gen size");
 
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
   size_t result =  gen_size_limit() - virtual_space()->committed_size();
-  size_t result_aligned = align_down(result, heap->generation_alignment());
+  size_t result_aligned = align_down(result, GenAlignment);
   return result_aligned;
 }
 
@@ -103,11 +103,10 @@
   }
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t gen_alignment = heap->generation_alignment();
   PSAdaptiveSizePolicy* policy = heap->size_policy();
   const size_t working_size =
     used_in_bytes() + (size_t) policy->avg_promoted()->padded_average();
-  const size_t working_aligned = align_up(working_size, gen_alignment);
+  const size_t working_aligned = align_up(working_size, GenAlignment);
   const size_t working_or_min = MAX2(working_aligned, min_gen_size());
   if (working_or_min > reserved().byte_size()) {
     // If the used or minimum gen size (aligned up) is greater
@@ -125,7 +124,7 @@
 
   size_t result = policy->promo_increment_aligned_down(max_contraction);
   // Also adjust for inter-generational alignment
-  size_t result_aligned = align_down(result, gen_alignment);
+  size_t result_aligned = align_down(result, GenAlignment);
 
   Log(gc, ergo) log;
   if (log.is_trace()) {
@@ -138,7 +137,7 @@
     log.trace(" min_gen_size() " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, min_gen_size()/K, min_gen_size());
     log.trace(" max_contraction " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, max_contraction/K, max_contraction);
     log.trace("    without alignment " SIZE_FORMAT " K / " SIZE_FORMAT_HEX, promo_increment/K, promo_increment);
-    log.trace(" alignment " SIZE_FORMAT_HEX, gen_alignment);
+    log.trace(" alignment " SIZE_FORMAT_HEX, GenAlignment);
   }
 
   assert(result_aligned <= max_contraction, "arithmetic is wrong");
--- a/src/hotspot/share/gc/parallel/asPSYoungGen.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/asPSYoungGen.cpp	Fri May 03 14:59:32 2019 -0400
@@ -29,6 +29,7 @@
 #include "gc/parallel/psScavenge.inline.hpp"
 #include "gc/parallel/psYoungGen.hpp"
 #include "gc/shared/gcUtil.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/spaceDecorator.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
@@ -74,9 +75,9 @@
   size_t current_committed_size = virtual_space()->committed_size();
   assert((gen_size_limit() >= current_committed_size),
     "generation size limit is wrong");
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
+
   size_t result =  gen_size_limit() - current_committed_size;
-  size_t result_aligned = align_down(result, heap->generation_alignment());
+  size_t result_aligned = align_down(result, GenAlignment);
   return result_aligned;
 }
 
@@ -93,13 +94,12 @@
   if (eden_space()->is_empty()) {
     // Respect the minimum size for eden and for the young gen as a whole.
     ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-    const size_t eden_alignment = heap->space_alignment();
-    const size_t gen_alignment = heap->generation_alignment();
+    const size_t eden_alignment = SpaceAlignment;
 
     assert(eden_space()->capacity_in_bytes() >= eden_alignment,
       "Alignment is wrong");
     size_t eden_avail = eden_space()->capacity_in_bytes() - eden_alignment;
-    eden_avail = align_down(eden_avail, gen_alignment);
+    eden_avail = align_down(eden_avail, GenAlignment);
 
     assert(virtual_space()->committed_size() >= min_gen_size(),
       "minimum gen size is wrong");
@@ -111,7 +111,7 @@
     // for reasons the "increment" fraction is used.
     PSAdaptiveSizePolicy* policy = heap->size_policy();
     size_t result = policy->eden_increment_aligned_down(max_contraction);
-    size_t result_aligned = align_down(result, gen_alignment);
+    size_t result_aligned = align_down(result, GenAlignment);
 
     log_trace(gc, ergo)("ASPSYoungGen::available_for_contraction: " SIZE_FORMAT " K", result_aligned/K);
     log_trace(gc, ergo)("  max_contraction " SIZE_FORMAT " K", max_contraction/K);
@@ -128,8 +128,7 @@
 // If to_space is below from_space, to_space is not considered.
 // to_space can be.
 size_t ASPSYoungGen::available_to_live() {
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t alignment = heap->space_alignment();
+  const size_t alignment = SpaceAlignment;
 
   // Include any space that is committed but is not in eden.
   size_t available = pointer_delta(eden_space()->bottom(),
@@ -275,7 +274,6 @@
   assert(eden_start < from_start, "Cannot push into from_space");
 
   ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t alignment = heap->space_alignment();
   const bool maintain_minimum =
     (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
 
@@ -331,9 +329,9 @@
 
       // Should we be in this method if from_space is empty? Why not the set_space method? FIX ME!
       if (from_size == 0) {
-        from_size = alignment;
+        from_size = SpaceAlignment;
       } else {
-        from_size = align_up(from_size, alignment);
+        from_size = align_up(from_size, SpaceAlignment);
       }
 
       from_end = from_start + from_size;
@@ -380,7 +378,7 @@
     // if the space sizes are to be increased by several times then
     // 'to_start' will point beyond the young generation. In this case
     // 'to_start' should be adjusted.
-    to_start = MAX2(to_start, eden_start + alignment);
+    to_start = MAX2(to_start, eden_start + SpaceAlignment);
 
     // Compute how big eden can be, then adjust end.
     // See  comments above on calculating eden_end.
@@ -395,7 +393,7 @@
     assert(eden_end >= eden_start, "addition overflowed");
 
     // Don't let eden shrink down to 0 or less.
-    eden_end = MAX2(eden_end, eden_start + alignment);
+    eden_end = MAX2(eden_end, eden_start + SpaceAlignment);
     to_start = MAX2(to_start, eden_end);
 
     log_trace(gc, ergo)("    [eden_start .. eden_end): "
--- a/src/hotspot/share/gc/parallel/gcTaskManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/gcTaskManager.cpp	Fri May 03 14:59:32 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
@@ -524,7 +524,7 @@
       // and get the count for additional IdleGCTask's under
       // the GCTaskManager's monitor so that the "more_inactive_workers"
       // count is correct.
-      MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
       _wait_helper.set_should_wait(true);
       // active_workers are a number being requested.  idle_workers
       // are the number currently idle.  If all the workers are being
@@ -563,7 +563,7 @@
 
 void  GCTaskManager::release_idle_workers() {
   {
-    MutexLockerEx ml(monitor(),
+    MutexLocker ml(monitor(),
       Mutex::_no_safepoint_check_flag);
     _wait_helper.set_should_wait(false);
     monitor()->notify_all();
@@ -613,7 +613,7 @@
 
 void GCTaskManager::add_task(GCTask* task) {
   assert(task != NULL, "shouldn't have null task");
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   if (TraceGCTaskManager) {
     tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
                   p2i(task), GCTask::Kind::to_string(task->kind()));
@@ -630,7 +630,7 @@
 
 void GCTaskManager::add_list(GCTaskQueue* list) {
   assert(list != NULL, "shouldn't have null task");
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   if (TraceGCTaskManager) {
     tty->print_cr("GCTaskManager::add_list(%u)", list->length());
   }
@@ -654,7 +654,7 @@
 GCTask* GCTaskManager::get_task(uint which) {
   GCTask* result = NULL;
   // Grab the queue lock.
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   // Wait while the queue is block or
   // there is nothing to do, except maybe release resources.
   while (is_blocked() ||
@@ -671,7 +671,7 @@
       tty->print_cr("    => (%s)->wait()",
                     monitor()->name());
     }
-    monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
+    ml.wait(0);
   }
   // We've reacquired the queue lock here.
   // Figure out which condition caused us to exit the loop above.
@@ -707,7 +707,7 @@
 }
 
 void GCTaskManager::note_completion(uint which) {
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   if (TraceGCTaskManager) {
     tty->print_cr("GCTaskManager::note_completion(%u)", which);
   }
@@ -872,15 +872,15 @@
   log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask:::do_it() should_wait: %s",
       p2i(this), wait_helper->should_wait() ? "true" : "false");
 
-  MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
   log_trace(gc, task)("--- idle %d", which);
   // Increment has to be done when the idle tasks are created.
   // manager->increment_idle_workers();
-  manager->monitor()->notify_all();
+  ml.notify_all();
   while (wait_helper->should_wait()) {
     log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask::do_it()  [" INTPTR_FORMAT "] (%s)->wait()",
       p2i(this), p2i(manager->monitor()), manager->monitor()->name());
-    manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
+    ml.wait(0);
   }
   manager->decrement_idle_workers();
 
@@ -943,7 +943,7 @@
       tty->print_cr("WaitForBarrierGCTask::do_it(%u) waiting on %u workers",
                     which, manager->busy_workers());
     }
-    manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
+    manager->monitor()->wait_without_safepoint_check(0);
   }
 }
 
@@ -955,7 +955,7 @@
   }
   {
     // First, wait for the barrier to arrive.
-    MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(manager->lock(), Mutex::_no_safepoint_check_flag);
     do_it_internal(manager, which);
     // Release manager->lock().
   }
@@ -991,7 +991,7 @@
   }
   {
     // Grab the lock and check again.
-    MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
     while (should_wait()) {
       if (TraceGCTaskManager) {
         tty->print_cr("[" INTPTR_FORMAT "]"
@@ -999,7 +999,7 @@
           "  [" INTPTR_FORMAT "] (%s)->wait()",
           p2i(this), p2i(monitor()), monitor()->name());
       }
-      monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
+      ml.wait(0);
     }
     // Reset the flag in case someone reuses this task.
     if (reset) {
@@ -1016,7 +1016,7 @@
 }
 
 void WaitHelper::notify() {
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   set_should_wait(false);
   // Waiter doesn't miss the notify in the wait_for method
   // since it checks the flag after grabbing the monitor.
@@ -1041,7 +1041,7 @@
                       Mutex::_allow_vm_block_flag);    // allow_vm_block
   }
   {
-    MutexLockerEx ml(lock());
+    MutexLocker ml(lock());
     // Lazy initialization.
     if (freelist() == NULL) {
       _freelist =
@@ -1067,7 +1067,7 @@
   assert(instance != NULL, "shouldn't release NULL");
   assert(!instance->is_locked(), "shouldn't be locked");
   {
-    MutexLockerEx ml(lock());
+    MutexLocker ml(lock());
     freelist()->push(instance);
     // release lock().
   }
--- a/src/hotspot/share/gc/parallel/generationSizer.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/parallel/generationSizer.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "runtime/globals_extension.hpp"
-#include "utilities/align.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-void GenerationSizer::initialize_alignments() {
-  _space_alignment = _gen_alignment = default_gen_alignment();
-  _heap_alignment = compute_heap_alignment();
-}
-
-void GenerationSizer::initialize_flags() {
-  // Do basic sizing work
-  GenCollectorPolicy::initialize_flags();
-
-  // The survivor ratio's are calculated "raw", unlike the
-  // default gc, which adds 2 to the ratio value. We need to
-  // make sure the values are valid before using them.
-  if (MinSurvivorRatio < 3) {
-    FLAG_SET_ERGO(uintx, MinSurvivorRatio, 3);
-  }
-
-  if (InitialSurvivorRatio < 3) {
-    FLAG_SET_ERGO(uintx, InitialSurvivorRatio, 3);
-  }
-}
-
-void GenerationSizer::initialize_size_info() {
-  const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8);
-  const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
-  const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages);
-  const size_t page_sz = MIN2(max_page_sz, min_page_sz);
-
-  // Can a page size be something else than a power of two?
-  assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
-  size_t new_alignment = align_up(page_sz, _gen_alignment);
-  if (new_alignment != _gen_alignment) {
-    _gen_alignment = new_alignment;
-    _space_alignment = new_alignment;
-    // Redo everything from the start
-    initialize_flags();
-  }
-  GenCollectorPolicy::initialize_size_info();
-}
-
-bool GenerationSizer::is_hetero_heap() const {
-  return false;
-}
-
-size_t GenerationSizer::heap_reserved_size_bytes() const {
-  return _max_heap_byte_size;
-}
--- a/src/hotspot/share/gc/parallel/generationSizer.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_PARALLEL_GENERATIONSIZER_HPP
-#define SHARE_GC_PARALLEL_GENERATIONSIZER_HPP
-
-#include "gc/shared/collectorPolicy.hpp"
-
-// There is a nice batch of tested generation sizing code in
-// GenCollectorPolicy. Lets reuse it!
-
-class GenerationSizer : public GenCollectorPolicy {
- private:
-  // The alignment used for boundary between young gen and old gen
-  static size_t default_gen_alignment() { return 64 * K * HeapWordSize; }
-
- protected:
-
-  void initialize_alignments();
-  void initialize_flags();
-  void initialize_size_info();
-
- public:
-  virtual size_t heap_reserved_size_bytes() const;
-  virtual bool is_hetero_heap() const;
-};
-#endif // SHARE_GC_PARALLEL_GENERATIONSIZER_HPP
--- a/src/hotspot/share/gc/parallel/heterogeneousGenerationSizer.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +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 "precompiled.hpp"
-#include "gc/parallel/heterogeneousGenerationSizer.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "logging/log.hpp"
-#include "runtime/globals_extension.hpp"
-#include "runtime/os.hpp"
-#include "utilities/align.hpp"
-#include "utilities/formatBuffer.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-const double HeterogeneousGenerationSizer::MaxRamFractionForYoung = 0.8;
-
-// Check the available dram memory to limit NewSize and MaxNewSize before
-// calling base class initialize_flags().
-void HeterogeneousGenerationSizer::initialize_flags() {
-  FormatBuffer<100> calc_str("");
-
-  julong phys_mem;
-  // If MaxRam is specified, we use that as maximum physical memory available.
-  if (FLAG_IS_DEFAULT(MaxRAM)) {
-    phys_mem = os::physical_memory();
-    calc_str.append("Physical_Memory");
-  } else {
-    phys_mem = (julong)MaxRAM;
-    calc_str.append("MaxRAM");
-  }
-
-  julong reasonable_max = phys_mem;
-
-  // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
-  // reasonable max size of young generation.
-  if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
-    reasonable_max = (julong)(phys_mem / MaxRAMFraction);
-    calc_str.append(" / MaxRAMFraction");
-  } else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
-    reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
-    calc_str.append(" * MaxRAMPercentage / 100");
-  } else {
-    // We use our own fraction to calculate max size of young generation.
-    reasonable_max = phys_mem * MaxRamFractionForYoung;
-    calc_str.append(" * %0.2f", MaxRamFractionForYoung);
-  }
-  reasonable_max = align_up(reasonable_max, _gen_alignment);
-
-  if (MaxNewSize > reasonable_max) {
-    if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
-                            (size_t)reasonable_max, calc_str.buffer());
-    } else {
-      log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
-                         "Dram usage can be lowered by setting MaxNewSize to a lower value", (size_t)reasonable_max, calc_str.buffer());
-    }
-    MaxNewSize = reasonable_max;
-  }
-  if (NewSize > reasonable_max) {
-    if (FLAG_IS_CMDLINE(NewSize)) {
-      log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
-                            (size_t)reasonable_max, calc_str.buffer());
-    }
-    NewSize = reasonable_max;
-  }
-
-  // After setting new size flags, call base class initialize_flags()
-  GenerationSizer::initialize_flags();
-}
-
-bool HeterogeneousGenerationSizer::is_hetero_heap() const {
-  return true;
-}
-
-size_t HeterogeneousGenerationSizer::heap_reserved_size_bytes() const {
-  if (UseAdaptiveGCBoundary) {
-    // This is the size that young gen can grow to, when UseAdaptiveGCBoundary is true.
-    size_t max_yg_size = _max_heap_byte_size - _min_old_size;
-    // This is the size that old gen can grow to, when UseAdaptiveGCBoundary is true.
-    size_t max_old_size = _max_heap_byte_size - _min_young_size;
-
-    return max_yg_size + max_old_size;
-  } else {
-    return _max_heap_byte_size;
-  }
-}
--- a/src/hotspot/share/gc/parallel/heterogeneousGenerationSizer.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * 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.
- *
- */
-
-#ifndef SHARE_GC_PARALLEL_HETEROGENEOUSGENERATIONSIZER_HPP
-#define SHARE_GC_PARALLEL_HETEROGENEOUSGENERATIONSIZER_HPP
-
-#include "gc/parallel/generationSizer.hpp"
-
-// There is a nice batch of tested generation sizing code in
-// GenCollectorPolicy. Lets reuse it!
-
-class HeterogeneousGenerationSizer : public GenerationSizer {
-private:
-  // Max fraction of dram to use for young generation when MaxRAMFraction and
-  // MaxRAMPercentage are not specified on commandline.
-  static const double MaxRamFractionForYoung;
-
-protected:
-  virtual void initialize_flags();
-
-public:
-  virtual size_t heap_reserved_size_bytes() const;
-  virtual bool is_hetero_heap() const;
-};
-#endif // SHARE_GC_PARALLEL_HETEROGENEOUSGENERATIONSIZER_HPP
--- a/src/hotspot/share/gc/parallel/parallelArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,20 +24,22 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/parallel/heterogeneousGenerationSizer.hpp"
 #include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "gc/shared/adaptiveSizePolicy.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/shared/gcArguments.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/workerPolicy.hpp"
+#include "logging/log.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "runtime/java.hpp"
 #include "utilities/defaultStream.hpp"
 
+static const double MaxRamFractionForYoung = 0.8;
+
 size_t ParallelArguments::conservative_max_heap_alignment() {
-  return CollectorPolicy::compute_heap_alignment();
+  return compute_heap_alignment();
 }
 
 void ParallelArguments::initialize() {
@@ -93,10 +95,125 @@
   }
 }
 
-CollectedHeap* ParallelArguments::create_heap() {
-  if (AllocateOldGenAt != NULL) {
-    return create_heap_with_policy<ParallelScavengeHeap, HeterogeneousGenerationSizer>();
-  } else {
-    return create_heap_with_policy<ParallelScavengeHeap, GenerationSizer>();
+// The alignment used for boundary between young gen and old gen
+static size_t default_gen_alignment() {
+  return 64 * K * HeapWordSize;
+}
+
+void ParallelArguments::initialize_alignments() {
+  SpaceAlignment = GenAlignment = default_gen_alignment();
+  HeapAlignment = compute_heap_alignment();
+}
+
+void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() {
+  // Do basic sizing work
+  GenArguments::initialize_heap_flags_and_sizes();
+
+  // The survivor ratio's are calculated "raw", unlike the
+  // default gc, which adds 2 to the ratio value. We need to
+  // make sure the values are valid before using them.
+  if (MinSurvivorRatio < 3) {
+    FLAG_SET_ERGO(uintx, MinSurvivorRatio, 3);
+  }
+
+  if (InitialSurvivorRatio < 3) {
+    FLAG_SET_ERGO(uintx, InitialSurvivorRatio, 3);
+  }
+}
+
+void ParallelArguments::initialize_heap_flags_and_sizes() {
+  if (is_heterogeneous_heap()) {
+    initialize_heterogeneous();
+  }
+
+  initialize_heap_flags_and_sizes_one_pass();
+
+  const size_t max_page_sz = os::page_size_for_region_aligned(MaxHeapSize, 8);
+  const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
+  const size_t min_page_sz = os::page_size_for_region_aligned(MinHeapSize, min_pages);
+  const size_t page_sz = MIN2(max_page_sz, min_page_sz);
+
+  // Can a page size be something else than a power of two?
+  assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
+  size_t new_alignment = align_up(page_sz, GenAlignment);
+  if (new_alignment != GenAlignment) {
+    GenAlignment = new_alignment;
+    SpaceAlignment = new_alignment;
+    // Redo everything from the start
+    initialize_heap_flags_and_sizes_one_pass();
   }
 }
+
+// Check the available dram memory to limit NewSize and MaxNewSize before
+// calling base class initialize_flags().
+void ParallelArguments::initialize_heterogeneous() {
+  FormatBuffer<100> calc_str("");
+
+  julong phys_mem;
+  // If MaxRam is specified, we use that as maximum physical memory available.
+  if (FLAG_IS_DEFAULT(MaxRAM)) {
+    phys_mem = os::physical_memory();
+    calc_str.append("Physical_Memory");
+  } else {
+    phys_mem = (julong)MaxRAM;
+    calc_str.append("MaxRAM");
+  }
+
+  julong reasonable_max = phys_mem;
+
+  // If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
+  // reasonable max size of young generation.
+  if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
+    reasonable_max = (julong)(phys_mem / MaxRAMFraction);
+    calc_str.append(" / MaxRAMFraction");
+  } else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
+    reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
+    calc_str.append(" * MaxRAMPercentage / 100");
+  } else {
+    // We use our own fraction to calculate max size of young generation.
+    reasonable_max = phys_mem * MaxRamFractionForYoung;
+    calc_str.append(" * %0.2f", MaxRamFractionForYoung);
+  }
+  reasonable_max = align_up(reasonable_max, GenAlignment);
+
+  if (MaxNewSize > reasonable_max) {
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
+                            (size_t)reasonable_max, calc_str.buffer());
+    } else {
+      log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
+                         "Dram usage can be lowered by setting MaxNewSize to a lower value", (size_t)reasonable_max, calc_str.buffer());
+    }
+    MaxNewSize = reasonable_max;
+  }
+  if (NewSize > reasonable_max) {
+    if (FLAG_IS_CMDLINE(NewSize)) {
+      log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
+                            (size_t)reasonable_max, calc_str.buffer());
+    }
+    NewSize = reasonable_max;
+  }
+}
+
+bool ParallelArguments::is_heterogeneous_heap() {
+  return AllocateOldGenAt != NULL;
+}
+
+size_t ParallelArguments::heap_reserved_size_bytes() {
+  if (!is_heterogeneous_heap() || !UseAdaptiveGCBoundary) {
+    return MaxHeapSize;
+  }
+
+  // Heterogeneous heap and adaptive size gc boundary
+
+  // This is the size that young gen can grow to, when UseAdaptiveGCBoundary is true.
+  size_t max_yg_size = MaxHeapSize - MinOldSize;
+  // This is the size that old gen can grow to, when UseAdaptiveGCBoundary is true.
+  size_t max_old_size = MaxHeapSize - MinNewSize;
+
+  return max_yg_size + max_old_size;
+}
+
+CollectedHeap* ParallelArguments::create_heap() {
+  return new ParallelScavengeHeap();
+}
--- a/src/hotspot/share/gc/parallel/parallelArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -26,14 +26,26 @@
 #define SHARE_GC_PARALLEL_PARALLELARGUMENTS_HPP
 
 #include "gc/shared/gcArguments.hpp"
+#include "gc/shared/genArguments.hpp"
 
 class CollectedHeap;
 
-class ParallelArguments : public GCArguments {
-public:
+class ParallelArguments : public GenArguments {
+private:
+  virtual void initialize_alignments();
+  virtual void initialize_heap_flags_and_sizes();
+
+  void initialize_heap_flags_and_sizes_one_pass();
+  void initialize_heterogeneous();
+
   virtual void initialize();
   virtual size_t conservative_max_heap_alignment();
   virtual CollectedHeap* create_heap();
+
+public:
+  // Heterogeneous heap support
+  static bool is_heterogeneous_heap();
+  static size_t heap_reserved_size_bytes();
 };
 
 #endif // SHARE_GC_PARALLEL_PARALLELARGUMENTS_HPP
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -27,8 +27,8 @@
 #include "gc/parallel/adjoiningGenerations.hpp"
 #include "gc/parallel/adjoiningGenerationsForHeteroHeap.hpp"
 #include "gc/parallel/adjoiningVirtualSpaces.hpp"
+#include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/gcTaskManager.hpp"
-#include "gc/parallel/generationSizer.hpp"
 #include "gc/parallel/objectStartArray.inline.hpp"
 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
@@ -41,6 +41,7 @@
 #include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcWhen.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/scavengableNMethods.hpp"
 #include "logging/log.hpp"
 #include "memory/metaspaceCounters.hpp"
@@ -60,14 +61,14 @@
 GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
 
 jint ParallelScavengeHeap::initialize() {
-  size_t heap_size = _collector_policy->heap_reserved_size_bytes();
+  const size_t reserved_heap_size = ParallelArguments::heap_reserved_size_bytes();
 
-  ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment());
+  ReservedSpace heap_rs = Universe::reserve_heap(reserved_heap_size, HeapAlignment);
 
   os::trace_page_sizes("Heap",
-                       _collector_policy->min_heap_byte_size(),
-                       heap_size,
-                       generation_alignment(),
+                       MinHeapSize,
+                       reserved_heap_size,
+                       GenAlignment,
                        heap_rs.base(),
                        heap_rs.size());
 
@@ -88,7 +89,7 @@
   double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
   double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
 
-  _gens = AdjoiningGenerations::create_adjoining_generations(heap_rs, _collector_policy, generation_alignment());
+  _gens = AdjoiningGenerations::create_adjoining_generations(heap_rs);
 
   _old_gen = _gens->old_gen();
   _young_gen = _gens->young_gen();
@@ -100,13 +101,13 @@
     new PSAdaptiveSizePolicy(eden_capacity,
                              initial_promo_size,
                              young_gen()->to_space()->capacity_in_bytes(),
-                             _collector_policy->gen_alignment(),
+                             GenAlignment,
                              max_gc_pause_sec,
                              max_gc_minor_pause_sec,
                              GCTimeRatio
                              );
 
-  assert(_collector_policy->is_hetero_heap() || !UseAdaptiveGCBoundary ||
+  assert(ParallelArguments::is_heterogeneous_heap() || !UseAdaptiveGCBoundary ||
     (old_gen()->virtual_space()->high_boundary() ==
      young_gen()->virtual_space()->low_boundary()),
     "Boundaries must meet");
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,18 +25,18 @@
 #ifndef SHARE_GC_PARALLEL_PARALLELSCAVENGEHEAP_HPP
 #define SHARE_GC_PARALLEL_PARALLELSCAVENGEHEAP_HPP
 
-#include "gc/parallel/generationSizer.hpp"
 #include "gc/parallel/objectStartArray.hpp"
 #include "gc/parallel/psGCAdaptivePolicyCounters.hpp"
 #include "gc/parallel/psOldGen.hpp"
 #include "gc/parallel/psYoungGen.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
 #include "gc/shared/gcWhen.hpp"
+#include "gc/shared/referenceProcessor.hpp"
 #include "gc/shared/softRefPolicy.hpp"
 #include "gc/shared/strongRootsScope.hpp"
+#include "logging/log.hpp"
 #include "memory/metaspace.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/ostream.hpp"
@@ -60,8 +60,6 @@
   static PSAdaptiveSizePolicy*       _size_policy;
   static PSGCAdaptivePolicyCounters* _gc_policy_counters;
 
-  GenerationSizer* _collector_policy;
-
   SoftRefPolicy _soft_ref_policy;
 
   // Collection of generations that are adjacent in the
@@ -92,9 +90,8 @@
   HeapWord* mem_allocate_old_gen(size_t size);
 
  public:
-  ParallelScavengeHeap(GenerationSizer* policy) :
+  ParallelScavengeHeap() :
     CollectedHeap(),
-    _collector_policy(policy),
     _gens(NULL),
     _death_march_count(0),
     _young_manager(NULL),
@@ -117,10 +114,6 @@
     return "Parallel";
   }
 
-  virtual CollectorPolicy* collector_policy() const { return _collector_policy; }
-
-  virtual GenerationSizer* ps_collector_policy() const { return _collector_policy; }
-
   virtual SoftRefPolicy* soft_ref_policy() { return &_soft_ref_policy; }
 
   virtual GrowableArray<GCMemoryManager*> memory_managers();
@@ -148,15 +141,6 @@
   void post_initialize();
   void update_counters();
 
-  // The alignment used for the various areas
-  size_t space_alignment()      { return _collector_policy->space_alignment(); }
-  size_t generation_alignment() { return _collector_policy->gen_alignment(); }
-
-  // Return the (conservative) maximum heap alignment
-  static size_t conservative_max_heap_alignment() {
-    return CollectorPolicy::compute_heap_alignment();
-  }
-
   size_t capacity() const;
   size_t used() const;
 
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp	Fri May 03 14:59:32 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
@@ -46,6 +46,9 @@
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 //
 // ThreadRootsMarkingTask
@@ -121,6 +124,12 @@
       AOTLoader::oops_do(&mark_and_push_closure);
       break;
 
+#if INCLUDE_JVMCI
+    case jvmci:
+      JVMCI::oops_do(&mark_and_push_closure);
+      break;
+#endif
+
     default:
       fatal("Unknown root type");
   }
--- a/src/hotspot/share/gc/parallel/pcTasks.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/pcTasks.hpp	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,7 @@
 #include "gc/parallel/gcTaskManager.hpp"
 #include "gc/parallel/psParallelCompact.hpp"
 #include "gc/parallel/psTasks.hpp"
+#include "gc/shared/referenceProcessor.hpp"
 
 
 // Tasks for parallel compaction of the old generation
@@ -98,6 +99,7 @@
     system_dictionary     = 7,
     class_loader_data     = 8,
     code_cache            = 9
+    JVMCI_ONLY(COMMA jvmci = 10)
   };
  private:
   RootType _root_type;
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
 #include "gc/parallel/psGCAdaptivePolicyCounters.hpp"
 #include "gc/parallel/psScavenge.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcCause.hpp"
 #include "gc/shared/gcUtil.inline.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Fri May 03 14:59:32 2019 -0400
@@ -62,6 +62,9 @@
 #include "utilities/align.hpp"
 #include "utilities/events.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 elapsedTimer        PSMarkSweep::_accumulated_time;
 jlong               PSMarkSweep::_time_of_last_gc   = 0;
@@ -85,7 +88,7 @@
 // Note that this method should only be called from the vm_thread while
 // at a safepoint!
 //
-// Note that the all_soft_refs_clear flag in the collector policy
+// Note that the all_soft_refs_clear flag in the soft ref policy
 // may be true because this method can be called without intervening
 // activity.  For example when the heap space is tight and full measure
 // are being taken to free space.
@@ -132,7 +135,7 @@
   PSAdaptiveSizePolicy* size_policy = heap->size_policy();
 
   // The scope of casr should end after code that can change
-  // CollectorPolicy::_should_clear_all_soft_refs.
+  // SoftRefolicy::_should_clear_all_soft_refs.
   ClearedAllSoftRefs casr(clear_all_softrefs, heap->soft_ref_policy());
 
   PSYoungGen* young_gen = heap->young_gen();
@@ -524,7 +527,8 @@
     ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
     //ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
-    AOTLoader::oops_do(mark_and_push_closure());
+    AOT_ONLY(AOTLoader::oops_do(mark_and_push_closure());)
+    JVMCI_ONLY(JVMCI::oops_do(mark_and_push_closure());)
   }
 
   // Flush marking stack.
@@ -562,6 +566,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   _gc_tracer->report_object_count_after_gc(is_alive_closure());
@@ -615,7 +622,10 @@
 
   CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
-  AOTLoader::oops_do(adjust_pointer_closure());
+  AOT_ONLY(AOTLoader::oops_do(adjust_pointer_closure());)
+
+  JVMCI_ONLY(JVMCI::oops_do(adjust_pointer_closure());)
+
   ref_processor()->weak_oops_do(adjust_pointer_closure());
   PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure());
 
--- a/src/hotspot/share/gc/parallel/psOldGen.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psOldGen.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/parallel/objectStartArray.inline.hpp"
+#include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #include "gc/parallel/psAdaptiveSizePolicy.hpp"
 #include "gc/parallel/psCardTable.hpp"
@@ -72,7 +73,7 @@
 
 void PSOldGen::initialize_virtual_space(ReservedSpace rs, size_t alignment) {
 
-  if(ParallelScavengeHeap::heap()->ps_collector_policy()->is_hetero_heap()) {
+  if(ParallelArguments::is_heterogeneous_heap()) {
     _virtual_space = new PSFileBackedVirtualSpace(rs, alignment, AllocateOldGenAt);
     if (!(static_cast <PSFileBackedVirtualSpace*>(_virtual_space))->initialize()) {
       vm_exit_during_initialization("Could not map space for PSOldGen at given AllocateOldGenAt path");
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri May 03 14:59:32 2019 -0400
@@ -31,6 +31,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/parallel/gcTaskManager.hpp"
+#include "gc/parallel/parallelArguments.hpp"
 #include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/parMarkBitMap.inline.hpp"
 #include "gc/parallel/pcTasks.hpp"
@@ -77,6 +78,9 @@
 #include "utilities/formatBuffer.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 #include <math.h>
 
@@ -1709,7 +1713,7 @@
 // Note that this method should only be called from the vm_thread while at a
 // safepoint.
 //
-// Note that the all_soft_refs_clear flag in the collector policy
+// Note that the all_soft_refs_clear flag in the soft ref policy
 // may be true because this method can be called without intervening
 // activity.  For example when the heap space is tight and full measure
 // are being taken to free space.
@@ -1762,7 +1766,7 @@
   PSAdaptiveSizePolicy* size_policy = heap->size_policy();
 
   // The scope of casr should end after code that can change
-  // CollectorPolicy::_should_clear_all_soft_refs.
+  // SoftRefPolicy::_should_clear_all_soft_refs.
   ClearedAllSoftRefs casr(maximum_heap_compaction,
                           heap->soft_ref_policy());
 
@@ -1992,7 +1996,7 @@
   // We also return false when it's a heterogenous heap because old generation cannot absorb data from eden
   // when it is allocated on different memory (example, nv-dimm) than young.
   if (!(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary) ||
-      ParallelScavengeHeap::heap()->ps_collector_policy()->is_hetero_heap()) {
+      ParallelArguments::is_heterogeneous_heap()) {
     return false;
   }
 
@@ -2123,6 +2127,7 @@
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::class_loader_data));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
+    JVMCI_ONLY(q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmci));)
 
     if (active_gc_threads > 1) {
       for (uint j = 0; j < active_gc_threads; j++) {
@@ -2176,6 +2181,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
@@ -2207,7 +2215,10 @@
 
   CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
-  AOTLoader::oops_do(&oop_closure);
+  AOT_ONLY(AOTLoader::oops_do(&oop_closure);)
+
+  JVMCI_ONLY(JVMCI::oops_do(&oop_closure);)
+
   ref_processor()->weak_oops_do(&oop_closure);
   // Roots were visited so references into the young gen in roots
   // may have been scanned.  Process them also.
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri May 03 14:59:32 2019 -0400
@@ -34,7 +34,6 @@
 #include "gc/parallel/psPromotionManager.inline.hpp"
 #include "gc/parallel/psScavenge.inline.hpp"
 #include "gc/parallel/psTasks.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcCause.hpp"
 #include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/gcId.hpp"
@@ -379,6 +378,7 @@
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::class_loader_data));
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
+      JVMCI_ONLY(q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmci));)
 
       TaskTerminator terminator(active_workers,
                                 (TaskQueueSetSuper*) promotion_manager->stack_array_depth());
--- a/src/hotspot/share/gc/parallel/psTasks.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psTasks.cpp	Fri May 03 14:59:32 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
@@ -44,6 +44,9 @@
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 //
 // ScavengeRootsTask
@@ -95,7 +98,6 @@
       JvmtiExport::oops_do(&roots_closure);
       break;
 
-
     case code_cache:
       {
         MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
@@ -104,6 +106,12 @@
       }
       break;
 
+#if INCLUDE_JVMCI
+    case jvmci:
+      JVMCI::oops_do(&roots_closure);
+      break;
+#endif
+
     default:
       fatal("Unknown root type");
   }
--- a/src/hotspot/share/gc/parallel/psTasks.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psTasks.hpp	Fri May 03 14:59:32 2019 -0400
@@ -61,6 +61,7 @@
     management            = 7,
     jvmti                 = 8,
     code_cache            = 9
+    JVMCI_ONLY(COMMA jvmci = 10)
   };
  private:
   RootType _root_type;
--- a/src/hotspot/share/gc/parallel/psYoungGen.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp	Fri May 03 14:59:32 2019 -0400
@@ -29,6 +29,7 @@
 #include "gc/parallel/psScavenge.hpp"
 #include "gc/parallel/psYoungGen.hpp"
 #include "gc/shared/gcUtil.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/spaceDecorator.hpp"
 #include "logging/log.hpp"
 #include "oops/oop.inline.hpp"
@@ -115,8 +116,7 @@
                                            _max_gen_size, _virtual_space);
 
   // Compute maximum space sizes for performance counters
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  size_t alignment = heap->space_alignment();
+  size_t alignment = SpaceAlignment;
   size_t size = virtual_space()->reserved_size();
 
   size_t max_survivor_size;
@@ -165,17 +165,14 @@
 }
 
 void PSYoungGen::compute_initial_space_boundaries() {
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-
   // Compute sizes
-  size_t alignment = heap->space_alignment();
   size_t size = virtual_space()->committed_size();
-  assert(size >= 3 * alignment, "Young space is not large enough for eden + 2 survivors");
+  assert(size >= 3 * SpaceAlignment, "Young space is not large enough for eden + 2 survivors");
 
   size_t survivor_size = size / InitialSurvivorRatio;
-  survivor_size = align_down(survivor_size, alignment);
+  survivor_size = align_down(survivor_size, SpaceAlignment);
   // ... but never less than an alignment
-  survivor_size = MAX2(survivor_size, alignment);
+  survivor_size = MAX2(survivor_size, SpaceAlignment);
 
   // Young generation is eden + 2 survivor spaces
   size_t eden_size = size - (2 * survivor_size);
@@ -219,13 +216,10 @@
 
 #ifndef PRODUCT
 void PSYoungGen::space_invariants() {
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t alignment = heap->space_alignment();
-
   // Currently, our eden size cannot shrink to zero
-  guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small");
-  guarantee(from_space()->capacity_in_bytes() >= alignment, "from too small");
-  guarantee(to_space()->capacity_in_bytes() >= alignment, "to too small");
+  guarantee(eden_space()->capacity_in_bytes() >= SpaceAlignment, "eden too small");
+  guarantee(from_space()->capacity_in_bytes() >= SpaceAlignment, "from too small");
+  guarantee(to_space()->capacity_in_bytes() >= SpaceAlignment, "to too small");
 
   // Relationship of spaces to each other
   char* eden_start = (char*)eden_space()->bottom();
@@ -482,8 +476,6 @@
   char* to_start   = (char*)to_space()->bottom();
   char* to_end     = (char*)to_space()->end();
 
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t alignment = heap->space_alignment();
   const bool maintain_minimum =
     (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
 
@@ -537,9 +529,9 @@
 
       // Should we be in this method if from_space is empty? Why not the set_space method? FIX ME!
       if (from_size == 0) {
-        from_size = alignment;
+        from_size = SpaceAlignment;
       } else {
-        from_size = align_up(from_size, alignment);
+        from_size = align_up(from_size, SpaceAlignment);
       }
 
       from_end = from_start + from_size;
@@ -582,7 +574,7 @@
     // if the space sizes are to be increased by several times then
     // 'to_start' will point beyond the young generation. In this case
     // 'to_start' should be adjusted.
-    to_start = MAX2(to_start, eden_start + alignment);
+    to_start = MAX2(to_start, eden_start + SpaceAlignment);
 
     // Compute how big eden can be, then adjust end.
     // See  comments above on calculating eden_end.
@@ -600,7 +592,7 @@
     // to_start = MAX2(to_start, eden_end);
 
     // Don't let eden shrink down to 0 or less.
-    eden_end = MAX2(eden_end, eden_start + alignment);
+    eden_end = MAX2(eden_end, eden_start + SpaceAlignment);
     to_start = MAX2(to_start, eden_end);
 
     log_trace(gc, ergo)("    [eden_start .. eden_end): [" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,
@@ -800,10 +792,6 @@
 // from-space.
 size_t PSYoungGen::available_to_live() {
   size_t delta_in_survivor = 0;
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  const size_t space_alignment = heap->space_alignment();
-  const size_t gen_alignment = heap->generation_alignment();
-
   MutableSpace* space_shrinking = NULL;
   if (from_space()->end() > to_space()->end()) {
     space_shrinking = from_space();
@@ -820,9 +808,9 @@
 
   if (space_shrinking->is_empty()) {
     // Don't let the space shrink to 0
-    assert(space_shrinking->capacity_in_bytes() >= space_alignment,
+    assert(space_shrinking->capacity_in_bytes() >= SpaceAlignment,
       "Space is too small");
-    delta_in_survivor = space_shrinking->capacity_in_bytes() - space_alignment;
+    delta_in_survivor = space_shrinking->capacity_in_bytes() - SpaceAlignment;
   } else {
     delta_in_survivor = pointer_delta(space_shrinking->end(),
                                       space_shrinking->top(),
@@ -830,7 +818,7 @@
   }
 
   size_t delta_in_bytes = unused_committed + delta_in_survivor;
-  delta_in_bytes = align_down(delta_in_bytes, gen_alignment);
+  delta_in_bytes = align_down(delta_in_bytes, GenAlignment);
   return delta_in_bytes;
 }
 
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp	Fri May 03 14:59:32 2019 -0400
@@ -30,6 +30,7 @@
 #include "gc/shared/ageTable.inline.hpp"
 #include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectorCounters.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
@@ -151,6 +152,8 @@
 
 DefNewGeneration::DefNewGeneration(ReservedSpace rs,
                                    size_t initial_size,
+                                   size_t min_size,
+                                   size_t max_size,
                                    const char* policy)
   : Generation(rs, initial_size),
     _preserved_marks_set(false /* in_c_heap */),
@@ -174,17 +177,15 @@
   // Compute the maximum eden and survivor space sizes. These sizes
   // are computed assuming the entire reserved space is committed.
   // These values are exported as performance counters.
-  uintx alignment = gch->collector_policy()->space_alignment();
   uintx size = _virtual_space.reserved_size();
-  _max_survivor_size = compute_survivor_size(size, alignment);
+  _max_survivor_size = compute_survivor_size(size, SpaceAlignment);
   _max_eden_size = size - (2*_max_survivor_size);
 
   // allocate the performance counters
-  GenCollectorPolicy* gcp = gch->gen_policy();
 
   // Generation counters -- generation 0, 3 subspaces
   _gen_counters = new GenerationCounters("new", 0, 3,
-      gcp->min_young_size(), gcp->max_young_size(), &_virtual_space);
+      min_size, max_size, &_virtual_space);
   _gc_counters = new CollectorCounters(policy, 0);
 
   _eden_counters = new CSpaceCounters("eden", 0, _max_eden_size, _eden_space,
@@ -206,9 +207,6 @@
 void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size,
                                                 bool clear_space,
                                                 bool mangle_space) {
-  uintx alignment =
-    GenCollectedHeap::heap()->collector_policy()->space_alignment();
-
   // If the spaces are being cleared (only done at heap initialization
   // currently), the survivor spaces need not be empty.
   // Otherwise, no care is taken for used areas in the survivor spaces
@@ -218,17 +216,17 @@
 
   // Compute sizes
   uintx size = _virtual_space.committed_size();
-  uintx survivor_size = compute_survivor_size(size, alignment);
+  uintx survivor_size = compute_survivor_size(size, SpaceAlignment);
   uintx eden_size = size - (2*survivor_size);
   assert(eden_size > 0 && survivor_size <= eden_size, "just checking");
 
   if (eden_size < minimum_eden_size) {
     // May happen due to 64Kb rounding, if so adjust eden size back up
-    minimum_eden_size = align_up(minimum_eden_size, alignment);
+    minimum_eden_size = align_up(minimum_eden_size, SpaceAlignment);
     uintx maximum_survivor_size = (size - minimum_eden_size) / 2;
     uintx unaligned_survivor_size =
-      align_down(maximum_survivor_size, alignment);
-    survivor_size = MAX2(unaligned_survivor_size, alignment);
+      align_down(maximum_survivor_size, SpaceAlignment);
+    survivor_size = MAX2(unaligned_survivor_size, SpaceAlignment);
     eden_size = size - (2*survivor_size);
     assert(eden_size > 0 && survivor_size <= eden_size, "just checking");
     assert(eden_size >= minimum_eden_size, "just checking");
@@ -461,9 +459,8 @@
 }
 
 size_t DefNewGeneration::max_capacity() const {
-  const size_t alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
   const size_t reserved_bytes = reserved().byte_size();
-  return reserved_bytes - compute_survivor_size(reserved_bytes, alignment);
+  return reserved_bytes - compute_survivor_size(reserved_bytes, SpaceAlignment);
 }
 
 size_t DefNewGeneration::unsafe_max_alloc_nogc() const {
--- a/src/hotspot/share/gc/serial/defNewGeneration.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp	Fri May 03 14:59:32 2019 -0400
@@ -191,7 +191,10 @@
   };
 
  public:
-  DefNewGeneration(ReservedSpace rs, size_t initial_byte_size,
+  DefNewGeneration(ReservedSpace rs,
+                   size_t initial_byte_size,
+                   size_t min_byte_size,
+                   size_t max_byte_size,
                    const char* policy="Serial young collection pauses");
 
   virtual void ref_processor_init();
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp	Fri May 03 14:59:32 2019 -0400
@@ -56,6 +56,9 @@
 #include "utilities/copy.hpp"
 #include "utilities/events.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
@@ -233,6 +236,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   gc_tracer()->report_object_count_after_gc(&is_alive);
--- a/src/hotspot/share/gc/serial/serialArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/serialArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,16 +23,10 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/serial/serialArguments.hpp"
 #include "gc/serial/serialHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-
-size_t SerialArguments::conservative_max_heap_alignment() {
-  return GenCollectedHeap::conservative_max_heap_alignment();
-}
 
 CollectedHeap* SerialArguments::create_heap() {
-  return create_heap_with_policy<SerialHeap, MarkSweepPolicy>();
+  return new SerialHeap();
 }
--- a/src/hotspot/share/gc/serial/serialArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/serialArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,13 +25,12 @@
 #ifndef SHARE_GC_SERIAL_SERIALARGUMENTS_HPP
 #define SHARE_GC_SERIAL_SERIALARGUMENTS_HPP
 
-#include "gc/shared/gcArguments.hpp"
+#include "gc/shared/genArguments.hpp"
 
 class CollectedHeap;
 
-class SerialArguments : public GCArguments {
-public:
-  virtual size_t conservative_max_heap_alignment();
+class SerialArguments : public GenArguments {
+private:
   virtual CollectedHeap* create_heap();
 };
 
--- a/src/hotspot/share/gc/serial/serialHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/serialHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -36,9 +36,8 @@
   return static_cast<SerialHeap*>(heap);
 }
 
-SerialHeap::SerialHeap(GenCollectorPolicy* policy) :
-    GenCollectedHeap(policy,
-                     Generation::DefNew,
+SerialHeap::SerialHeap() :
+    GenCollectedHeap(Generation::DefNew,
                      Generation::MarkSweepCompact,
                      "Copy:MSC"),
     _eden_pool(NULL),
--- a/src/hotspot/share/gc/serial/serialHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -30,7 +30,6 @@
 #include "gc/shared/genCollectedHeap.hpp"
 #include "utilities/growableArray.hpp"
 
-class GenCollectorPolicy;
 class GCMemoryManager;
 class MemoryPool;
 class TenuredGeneration;
@@ -46,7 +45,7 @@
 public:
   static SerialHeap* heap();
 
-  SerialHeap(GenCollectorPolicy* policy);
+  SerialHeap();
 
   virtual Name kind() const {
     return CollectedHeap::Serial;
--- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp	Fri May 03 14:59:32 2019 -0400
@@ -45,6 +45,8 @@
 
 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
                                      size_t initial_byte_size,
+                                     size_t min_byte_size,
+                                     size_t max_byte_size,
                                      CardTableRS* remset) :
   CardGeneration(rs, initial_byte_size, remset)
 {
@@ -60,10 +62,9 @@
   // initialize performance counters
 
   const char* gen_name = "old";
-  GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
   // Generation Counters -- generation 1, 1 subspace
   _gen_counters = new GenerationCounters(gen_name, 1, 1,
-      gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);
+      min_byte_size, max_byte_size, &_virtual_space);
 
   _gc_counters = new CollectorCounters("Serial full collection pauses", 1);
 
--- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp	Fri May 03 14:59:32 2019 -0400
@@ -58,6 +58,8 @@
  public:
   TenuredGeneration(ReservedSpace rs,
                     size_t initial_byte_size,
+                    size_t min_byte_size,
+                    size_t max_byte_size,
                     CardTableRS* remset);
 
   Generation::Name kind() { return Generation::MarkSweepCompact; }
--- a/src/hotspot/share/gc/shared/ageTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/ageTable.cpp	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
 #include "gc/shared/ageTable.inline.hpp"
 #include "gc/shared/ageTableTracer.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
 #include "oops/oop.inline.hpp"
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -65,7 +65,7 @@
   }
 
   double timestamp = fetch_timestamp();
-  MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(&_mutex, Mutex::_no_safepoint_check_flag);
   int index = compute_log_index();
   _records[index].thread = NULL; // Its the GC thread so it's not that interesting.
   _records[index].timestamp = timestamp;
@@ -81,6 +81,11 @@
   st.print_cr("}");
 }
 
+size_t CollectedHeap::unused() const {
+  MutexLocker ml(Heap_lock);
+  return capacity() - used();
+}
+
 VirtualSpaceSummary CollectedHeap::create_heap_space_summary() {
   size_t capacity_in_words = capacity() / HeapWordSize;
 
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -44,7 +44,6 @@
 
 class AdaptiveSizePolicy;
 class BarrierSet;
-class CollectorPolicy;
 class GCHeapSummary;
 class GCTimer;
 class GCTracer;
@@ -210,6 +209,9 @@
   virtual size_t capacity() const = 0;
   virtual size_t used() const = 0;
 
+  // Returns unused capacity.
+  virtual size_t unused() const;
+
   // Return "true" if the part of the heap that allocates Java
   // objects has reached the maximal committed limit that it can
   // reach, without a garbage collection.
@@ -385,9 +387,6 @@
 
   void increment_total_full_collections() { _total_full_collections++; }
 
-  // Return the CollectorPolicy for the heap
-  virtual CollectorPolicy* collector_policy() const = 0;
-
   // Return the SoftRefPolicy for the heap;
   virtual SoftRefPolicy* soft_ref_policy() = 0;
 
--- a/src/hotspot/share/gc/shared/collectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,547 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/shared/adaptiveSizePolicy.hpp"
-#include "gc/shared/cardTableRS.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "gc/shared/gcLocker.hpp"
-#include "gc/shared/gcPolicyCounters.hpp"
-#include "gc/shared/gcVMOperations.hpp"
-#include "gc/shared/generationSpec.hpp"
-#include "gc/shared/space.hpp"
-#include "logging/log.hpp"
-#include "memory/universe.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/globals_extension.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/java.hpp"
-#include "runtime/thread.inline.hpp"
-#include "runtime/vmThread.hpp"
-#include "utilities/align.hpp"
-#include "utilities/macros.hpp"
-
-// CollectorPolicy methods
-
-CollectorPolicy::CollectorPolicy() :
-    _initial_heap_byte_size(InitialHeapSize),
-    _max_heap_byte_size(MaxHeapSize),
-    _min_heap_byte_size(Arguments::min_heap_size()),
-    _space_alignment(0),
-    _heap_alignment(0)
-{}
-
-#ifdef ASSERT
-void CollectorPolicy::assert_flags() {
-  assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
-  assert(InitialHeapSize % _heap_alignment == 0, "InitialHeapSize alignment");
-  assert(MaxHeapSize % _heap_alignment == 0, "MaxHeapSize alignment");
-}
-
-void CollectorPolicy::assert_size_info() {
-  assert(InitialHeapSize == _initial_heap_byte_size, "Discrepancy between InitialHeapSize flag and local storage");
-  assert(MaxHeapSize == _max_heap_byte_size, "Discrepancy between MaxHeapSize flag and local storage");
-  assert(_max_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible minimum and maximum heap sizes");
-  assert(_initial_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible initial and minimum heap sizes");
-  assert(_max_heap_byte_size >= _initial_heap_byte_size, "Ergonomics decided on incompatible initial and maximum heap sizes");
-  assert(_min_heap_byte_size % _heap_alignment == 0, "min_heap_byte_size alignment");
-  assert(_initial_heap_byte_size % _heap_alignment == 0, "initial_heap_byte_size alignment");
-  assert(_max_heap_byte_size % _heap_alignment == 0, "max_heap_byte_size alignment");
-}
-#endif // ASSERT
-
-void CollectorPolicy::initialize_flags() {
-  assert(_space_alignment != 0, "Space alignment not set up properly");
-  assert(_heap_alignment != 0, "Heap alignment not set up properly");
-  assert(_heap_alignment >= _space_alignment,
-         "heap_alignment: " SIZE_FORMAT " less than space_alignment: " SIZE_FORMAT,
-         _heap_alignment, _space_alignment);
-  assert(_heap_alignment % _space_alignment == 0,
-         "heap_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
-         _heap_alignment, _space_alignment);
-
-  if (FLAG_IS_CMDLINE(MaxHeapSize)) {
-    if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
-      vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
-    }
-    if (_min_heap_byte_size != 0 && MaxHeapSize < _min_heap_byte_size) {
-      vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
-    }
-  }
-
-  // Check heap parameter properties
-  if (MaxHeapSize < 2 * M) {
-    vm_exit_during_initialization("Too small maximum heap");
-  }
-  if (InitialHeapSize < M) {
-    vm_exit_during_initialization("Too small initial heap");
-  }
-  if (_min_heap_byte_size < M) {
-    vm_exit_during_initialization("Too small minimum heap");
-  }
-
-  // User inputs from -Xmx and -Xms must be aligned
-  _min_heap_byte_size = align_up(_min_heap_byte_size, _heap_alignment);
-  size_t aligned_initial_heap_size = align_up(InitialHeapSize, _heap_alignment);
-  size_t aligned_max_heap_size = align_up(MaxHeapSize, _heap_alignment);
-
-  // Write back to flags if the values changed
-  if (aligned_initial_heap_size != InitialHeapSize) {
-    FLAG_SET_ERGO(size_t, InitialHeapSize, aligned_initial_heap_size);
-  }
-  if (aligned_max_heap_size != MaxHeapSize) {
-    FLAG_SET_ERGO(size_t, MaxHeapSize, aligned_max_heap_size);
-  }
-
-  if (FLAG_IS_CMDLINE(InitialHeapSize) && _min_heap_byte_size != 0 &&
-      InitialHeapSize < _min_heap_byte_size) {
-    vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
-  }
-  if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
-    FLAG_SET_ERGO(size_t, MaxHeapSize, InitialHeapSize);
-  } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
-    FLAG_SET_ERGO(size_t, InitialHeapSize, MaxHeapSize);
-    if (InitialHeapSize < _min_heap_byte_size) {
-      _min_heap_byte_size = InitialHeapSize;
-    }
-  }
-
-  _initial_heap_byte_size = InitialHeapSize;
-  _max_heap_byte_size = MaxHeapSize;
-
-  FLAG_SET_ERGO(size_t, MinHeapDeltaBytes, align_up(MinHeapDeltaBytes, _space_alignment));
-
-  DEBUG_ONLY(CollectorPolicy::assert_flags();)
-}
-
-void CollectorPolicy::initialize_size_info() {
-  log_debug(gc, heap)("Minimum heap " SIZE_FORMAT "  Initial heap " SIZE_FORMAT "  Maximum heap " SIZE_FORMAT,
-                      _min_heap_byte_size, _initial_heap_byte_size, _max_heap_byte_size);
-
-  DEBUG_ONLY(CollectorPolicy::assert_size_info();)
-}
-
-size_t CollectorPolicy::compute_heap_alignment() {
-  // The card marking array and the offset arrays for old generations are
-  // committed in os pages as well. Make sure they are entirely full (to
-  // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
-  // byte entry and the os page size is 4096, the maximum heap size should
-  // be 512*4096 = 2MB aligned.
-
-  size_t alignment = CardTableRS::ct_max_alignment_constraint();
-
-  if (UseLargePages) {
-      // In presence of large pages we have to make sure that our
-      // alignment is large page aware.
-      alignment = lcm(os::large_page_size(), alignment);
-  }
-
-  return alignment;
-}
-
-// GenCollectorPolicy methods
-
-GenCollectorPolicy::GenCollectorPolicy() :
-    _min_young_size(0),
-    _initial_young_size(0),
-    _max_young_size(0),
-    _min_old_size(0),
-    _initial_old_size(0),
-    _max_old_size(0),
-    _gen_alignment(0)
-{}
-
-size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
-  return align_down_bounded(base_size / (NewRatio + 1), _gen_alignment);
-}
-
-size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
-                                                 size_t maximum_size) {
-  size_t max_minus = maximum_size - _gen_alignment;
-  return desired_size < max_minus ? desired_size : max_minus;
-}
-
-size_t GenCollectorPolicy::young_gen_size_lower_bound() {
-  // The young generation must be aligned and have room for eden + two survivors
-  return align_up(3 * _space_alignment, _gen_alignment);
-}
-
-size_t GenCollectorPolicy::old_gen_size_lower_bound() {
-  return align_up(_space_alignment, _gen_alignment);
-}
-
-#ifdef ASSERT
-void GenCollectorPolicy::assert_flags() {
-  CollectorPolicy::assert_flags();
-  assert(NewSize >= _min_young_size, "Ergonomics decided on a too small young gen size");
-  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
-  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
-  assert(NewSize % _gen_alignment == 0, "NewSize alignment");
-  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % _gen_alignment == 0, "MaxNewSize alignment");
-  assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
-  assert(OldSize % _gen_alignment == 0, "OldSize alignment");
-}
-
-void GenCollectorPolicy::assert_size_info() {
-  CollectorPolicy::assert_size_info();
-  // GenCollectorPolicy::initialize_size_info may update the MaxNewSize
-  assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
-  assert(NewSize == _initial_young_size, "Discrepancy between NewSize flag and local storage");
-  assert(MaxNewSize == _max_young_size, "Discrepancy between MaxNewSize flag and local storage");
-  assert(OldSize == _initial_old_size, "Discrepancy between OldSize flag and local storage");
-  assert(_min_young_size <= _initial_young_size, "Ergonomics decided on incompatible minimum and initial young gen sizes");
-  assert(_initial_young_size <= _max_young_size, "Ergonomics decided on incompatible initial and maximum young gen sizes");
-  assert(_min_young_size % _gen_alignment == 0, "_min_young_size alignment");
-  assert(_initial_young_size % _gen_alignment == 0, "_initial_young_size alignment");
-  assert(_max_young_size % _gen_alignment == 0, "_max_young_size alignment");
-  assert(_min_young_size <= bound_minus_alignment(_min_young_size, _min_heap_byte_size),
-      "Ergonomics made minimum young generation larger than minimum heap");
-  assert(_initial_young_size <=  bound_minus_alignment(_initial_young_size, _initial_heap_byte_size),
-      "Ergonomics made initial young generation larger than initial heap");
-  assert(_max_young_size <= bound_minus_alignment(_max_young_size, _max_heap_byte_size),
-      "Ergonomics made maximum young generation lager than maximum heap");
-  assert(_min_old_size <= _initial_old_size, "Ergonomics decided on incompatible minimum and initial old gen sizes");
-  assert(_initial_old_size <= _max_old_size, "Ergonomics decided on incompatible initial and maximum old gen sizes");
-  assert(_max_old_size % _gen_alignment == 0, "_max_old_size alignment");
-  assert(_initial_old_size % _gen_alignment == 0, "_initial_old_size alignment");
-  assert(_max_heap_byte_size <= (_max_young_size + _max_old_size), "Total maximum heap sizes must be sum of generation maximum sizes");
-  assert(_min_young_size + _min_old_size <= _min_heap_byte_size, "Minimum generation sizes exceed minimum heap size");
-  assert(_initial_young_size + _initial_old_size == _initial_heap_byte_size, "Initial generation sizes should match initial heap size");
-  assert(_max_young_size + _max_old_size == _max_heap_byte_size, "Maximum generation sizes should match maximum heap size");
-}
-#endif // ASSERT
-
-void GenCollectorPolicy::initialize_flags() {
-  CollectorPolicy::initialize_flags();
-
-  assert(_gen_alignment != 0, "Generation alignment not set up properly");
-  assert(_heap_alignment >= _gen_alignment,
-         "heap_alignment: " SIZE_FORMAT " less than gen_alignment: " SIZE_FORMAT,
-         _heap_alignment, _gen_alignment);
-  assert(_gen_alignment % _space_alignment == 0,
-         "gen_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
-         _gen_alignment, _space_alignment);
-  assert(_heap_alignment % _gen_alignment == 0,
-         "heap_alignment: " SIZE_FORMAT " not aligned by gen_alignment: " SIZE_FORMAT,
-         _heap_alignment, _gen_alignment);
-
-  // All generational heaps have a young gen; handle those flags here
-
-  // Make sure the heap is large enough for two generations
-  size_t smallest_new_size = young_gen_size_lower_bound();
-  size_t smallest_heap_size = align_up(smallest_new_size + old_gen_size_lower_bound(),
-                                           _heap_alignment);
-  if (MaxHeapSize < smallest_heap_size) {
-    FLAG_SET_ERGO(size_t, MaxHeapSize, smallest_heap_size);
-    _max_heap_byte_size = MaxHeapSize;
-  }
-  // If needed, synchronize _min_heap_byte size and _initial_heap_byte_size
-  if (_min_heap_byte_size < smallest_heap_size) {
-    _min_heap_byte_size = smallest_heap_size;
-    if (InitialHeapSize < _min_heap_byte_size) {
-      FLAG_SET_ERGO(size_t, InitialHeapSize, smallest_heap_size);
-      _initial_heap_byte_size = smallest_heap_size;
-    }
-  }
-
-  // Make sure NewSize allows an old generation to fit even if set on the command line
-  if (FLAG_IS_CMDLINE(NewSize) && NewSize >= _initial_heap_byte_size) {
-    log_warning(gc, ergo)("NewSize was set larger than initial heap size, will use initial heap size.");
-    FLAG_SET_ERGO(size_t, NewSize, bound_minus_alignment(NewSize, _initial_heap_byte_size));
-  }
-
-  // Now take the actual NewSize into account. We will silently increase NewSize
-  // if the user specified a smaller or unaligned value.
-  size_t bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize);
-  bounded_new_size = MAX2(smallest_new_size, align_down(bounded_new_size, _gen_alignment));
-  if (bounded_new_size != NewSize) {
-    FLAG_SET_ERGO(size_t, NewSize, bounded_new_size);
-  }
-  _min_young_size = smallest_new_size;
-  _initial_young_size = NewSize;
-
-  if (!FLAG_IS_DEFAULT(MaxNewSize)) {
-    if (MaxNewSize >= MaxHeapSize) {
-      // Make sure there is room for an old generation
-      size_t smaller_max_new_size = MaxHeapSize - _gen_alignment;
-      if (FLAG_IS_CMDLINE(MaxNewSize)) {
-        log_warning(gc, ergo)("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire "
-                              "heap (" SIZE_FORMAT "k).  A new max generation size of " SIZE_FORMAT "k will be used.",
-                              MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K);
-      }
-      FLAG_SET_ERGO(size_t, MaxNewSize, smaller_max_new_size);
-      if (NewSize > MaxNewSize) {
-        FLAG_SET_ERGO(size_t, NewSize, MaxNewSize);
-        _initial_young_size = NewSize;
-      }
-    } else if (MaxNewSize < _initial_young_size) {
-      FLAG_SET_ERGO(size_t, MaxNewSize, _initial_young_size);
-    } else if (!is_aligned(MaxNewSize, _gen_alignment)) {
-      FLAG_SET_ERGO(size_t, MaxNewSize, align_down(MaxNewSize, _gen_alignment));
-    }
-    _max_young_size = MaxNewSize;
-  }
-
-  if (NewSize > MaxNewSize) {
-    // At this point this should only happen if the user specifies a large NewSize and/or
-    // a small (but not too small) MaxNewSize.
-    if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
-                            "A new max generation size of " SIZE_FORMAT "k will be used.",
-                            NewSize/K, MaxNewSize/K, NewSize/K);
-    }
-    FLAG_SET_ERGO(size_t, MaxNewSize, NewSize);
-    _max_young_size = MaxNewSize;
-  }
-
-  if (SurvivorRatio < 1 || NewRatio < 1) {
-    vm_exit_during_initialization("Invalid young gen ratio specified");
-  }
-
-  if (OldSize < old_gen_size_lower_bound()) {
-    FLAG_SET_ERGO(size_t, OldSize, old_gen_size_lower_bound());
-  }
-  if (!is_aligned(OldSize, _gen_alignment)) {
-    FLAG_SET_ERGO(size_t, OldSize, align_down(OldSize, _gen_alignment));
-  }
-
-  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
-    // NewRatio will be used later to set the young generation size so we use
-    // it to calculate how big the heap should be based on the requested OldSize
-    // and NewRatio.
-    assert(NewRatio > 0, "NewRatio should have been set up earlier");
-    size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
-
-    calculated_heapsize = align_up(calculated_heapsize, _heap_alignment);
-    FLAG_SET_ERGO(size_t, MaxHeapSize, calculated_heapsize);
-    _max_heap_byte_size = MaxHeapSize;
-    FLAG_SET_ERGO(size_t, InitialHeapSize, calculated_heapsize);
-    _initial_heap_byte_size = InitialHeapSize;
-  }
-
-  // Adjust NewSize and OldSize or MaxHeapSize to match each other
-  if (NewSize + OldSize > MaxHeapSize) {
-    if (FLAG_IS_CMDLINE(MaxHeapSize)) {
-      // Somebody has set a maximum heap size with the intention that we should not
-      // exceed it. Adjust New/OldSize as necessary.
-      size_t calculated_size = NewSize + OldSize;
-      double shrink_factor = (double) MaxHeapSize / calculated_size;
-      size_t smaller_new_size = align_down((size_t)(NewSize * shrink_factor), _gen_alignment);
-      FLAG_SET_ERGO(size_t, NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));
-      _initial_young_size = NewSize;
-
-      // OldSize is already aligned because above we aligned MaxHeapSize to
-      // _heap_alignment, and we just made sure that NewSize is aligned to
-      // _gen_alignment. In initialize_flags() we verified that _heap_alignment
-      // is a multiple of _gen_alignment.
-      FLAG_SET_ERGO(size_t, OldSize, MaxHeapSize - NewSize);
-    } else {
-      FLAG_SET_ERGO(size_t, MaxHeapSize, align_up(NewSize + OldSize, _heap_alignment));
-      _max_heap_byte_size = MaxHeapSize;
-    }
-  }
-
-  // Update NewSize, if possible, to avoid sizing the young gen too small when only
-  // OldSize is set on the command line.
-  if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) {
-    if (OldSize < _initial_heap_byte_size) {
-      size_t new_size = _initial_heap_byte_size - OldSize;
-      // Need to compare against the flag value for max since _max_young_size
-      // might not have been set yet.
-      if (new_size >= _min_young_size && new_size <= MaxNewSize) {
-        FLAG_SET_ERGO(size_t, NewSize, new_size);
-        _initial_young_size = NewSize;
-      }
-    }
-  }
-
-  always_do_update_barrier = UseConcMarkSweepGC;
-
-  DEBUG_ONLY(GenCollectorPolicy::assert_flags();)
-}
-
-// Values set on the command line win over any ergonomically
-// set command line parameters.
-// Ergonomic choice of parameters are done before this
-// method is called.  Values for command line parameters such as NewSize
-// and MaxNewSize feed those ergonomic choices into this method.
-// This method makes the final generation sizings consistent with
-// themselves and with overall heap sizings.
-// In the absence of explicitly set command line flags, policies
-// such as the use of NewRatio are used to size the generation.
-
-// Minimum sizes of the generations may be different than
-// the initial sizes.  An inconsistency is permitted here
-// in the total size that can be specified explicitly by
-// command line specification of OldSize and NewSize and
-// also a command line specification of -Xms.  Issue a warning
-// but allow the values to pass.
-void GenCollectorPolicy::initialize_size_info() {
-  CollectorPolicy::initialize_size_info();
-
-  _initial_young_size = NewSize;
-  _max_young_size = MaxNewSize;
-  _initial_old_size = OldSize;
-
-  // Determine maximum size of the young generation.
-
-  if (FLAG_IS_DEFAULT(MaxNewSize)) {
-    _max_young_size = scale_by_NewRatio_aligned(_max_heap_byte_size);
-    // Bound the maximum size by NewSize below (since it historically
-    // would have been NewSize and because the NewRatio calculation could
-    // yield a size that is too small) and bound it by MaxNewSize above.
-    // Ergonomics plays here by previously calculating the desired
-    // NewSize and MaxNewSize.
-    _max_young_size = MIN2(MAX2(_max_young_size, _initial_young_size), MaxNewSize);
-  }
-
-  // Given the maximum young size, determine the initial and
-  // minimum young sizes.
-
-  if (_max_heap_byte_size == _initial_heap_byte_size) {
-    // The maximum and initial heap sizes are the same so the generation's
-    // initial size must be the same as it maximum size. Use NewSize as the
-    // size if set on command line.
-    _max_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : _max_young_size;
-    _initial_young_size = _max_young_size;
-
-    // Also update the minimum size if min == initial == max.
-    if (_max_heap_byte_size == _min_heap_byte_size) {
-      _min_young_size = _max_young_size;
-    }
-  } else {
-    if (FLAG_IS_CMDLINE(NewSize)) {
-      // If NewSize is set on the command line, we should use it as
-      // the initial size, but make sure it is within the heap bounds.
-      _initial_young_size =
-        MIN2(_max_young_size, bound_minus_alignment(NewSize, _initial_heap_byte_size));
-      _min_young_size = bound_minus_alignment(_initial_young_size, _min_heap_byte_size);
-    } else {
-      // For the case where NewSize is not set on the command line, use
-      // NewRatio to size the initial generation size. Use the current
-      // NewSize as the floor, because if NewRatio is overly large, the resulting
-      // size can be too small.
-      _initial_young_size =
-        MIN2(_max_young_size, MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize));
-    }
-  }
-
-  log_trace(gc, heap)("1: Minimum young " SIZE_FORMAT "  Initial young " SIZE_FORMAT "  Maximum young " SIZE_FORMAT,
-                      _min_young_size, _initial_young_size, _max_young_size);
-
-  // At this point the minimum, initial and maximum sizes
-  // of the overall heap and of the young generation have been determined.
-  // The maximum old size can be determined from the maximum young
-  // and maximum heap size since no explicit flags exist
-  // for setting the old generation maximum.
-  _max_old_size = MAX2(_max_heap_byte_size - _max_young_size, _gen_alignment);
-
-  // If no explicit command line flag has been set for the
-  // old generation size, use what is left.
-  if (!FLAG_IS_CMDLINE(OldSize)) {
-    // The user has not specified any value but the ergonomics
-    // may have chosen a value (which may or may not be consistent
-    // with the overall heap size).  In either case make
-    // the minimum, maximum and initial sizes consistent
-    // with the young sizes and the overall heap sizes.
-    _min_old_size = _gen_alignment;
-    _initial_old_size = MIN2(_max_old_size, MAX2(_initial_heap_byte_size - _initial_young_size, _min_old_size));
-    // _max_old_size has already been made consistent above.
-  } else {
-    // OldSize has been explicitly set on the command line. Use it
-    // for the initial size but make sure the minimum allow a young
-    // generation to fit as well.
-    // If the user has explicitly set an OldSize that is inconsistent
-    // with other command line flags, issue a warning.
-    // The generation minimums and the overall heap minimum should
-    // be within one generation alignment.
-    if (_initial_old_size > _max_old_size) {
-      log_warning(gc, ergo)("Inconsistency between maximum heap size and maximum "
-                            "generation sizes: using maximum heap = " SIZE_FORMAT
-                            ", -XX:OldSize flag is being ignored",
-                            _max_heap_byte_size);
-      _initial_old_size = _max_old_size;
-    }
-
-    _min_old_size = MIN2(_initial_old_size, _min_heap_byte_size - _min_young_size);
-  }
-
-  // The initial generation sizes should match the initial heap size,
-  // if not issue a warning and resize the generations. This behavior
-  // differs from JDK8 where the generation sizes have higher priority
-  // than the initial heap size.
-  if ((_initial_old_size + _initial_young_size) != _initial_heap_byte_size) {
-    log_warning(gc, ergo)("Inconsistency between generation sizes and heap size, resizing "
-                          "the generations to fit the heap.");
-
-    size_t desired_young_size = _initial_heap_byte_size - _initial_old_size;
-    if (_initial_heap_byte_size < _initial_old_size) {
-      // Old want all memory, use minimum for young and rest for old
-      _initial_young_size = _min_young_size;
-      _initial_old_size = _initial_heap_byte_size - _min_young_size;
-    } else if (desired_young_size > _max_young_size) {
-      // Need to increase both young and old generation
-      _initial_young_size = _max_young_size;
-      _initial_old_size = _initial_heap_byte_size - _max_young_size;
-    } else if (desired_young_size < _min_young_size) {
-      // Need to decrease both young and old generation
-      _initial_young_size = _min_young_size;
-      _initial_old_size = _initial_heap_byte_size - _min_young_size;
-    } else {
-      // The young generation boundaries allow us to only update the
-      // young generation.
-      _initial_young_size = desired_young_size;
-    }
-
-    log_trace(gc, heap)("2: Minimum young " SIZE_FORMAT "  Initial young " SIZE_FORMAT "  Maximum young " SIZE_FORMAT,
-                    _min_young_size, _initial_young_size, _max_young_size);
-  }
-
-  // Write back to flags if necessary.
-  if (NewSize != _initial_young_size) {
-    FLAG_SET_ERGO(size_t, NewSize, _initial_young_size);
-  }
-
-  if (MaxNewSize != _max_young_size) {
-    FLAG_SET_ERGO(size_t, MaxNewSize, _max_young_size);
-  }
-
-  if (OldSize != _initial_old_size) {
-    FLAG_SET_ERGO(size_t, OldSize, _initial_old_size);
-  }
-
-  log_trace(gc, heap)("Minimum old " SIZE_FORMAT "  Initial old " SIZE_FORMAT "  Maximum old " SIZE_FORMAT,
-                  _min_old_size, _initial_old_size, _max_old_size);
-
-  DEBUG_ONLY(GenCollectorPolicy::assert_size_info();)
-}
-
-//
-// MarkSweepPolicy methods
-//
-
-void MarkSweepPolicy::initialize_alignments() {
-  _space_alignment = _gen_alignment = (size_t)Generation::GenGrain;
-  _heap_alignment = compute_heap_alignment();
-}
--- a/src/hotspot/share/gc/shared/collectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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_COLLECTORPOLICY_HPP
-#define SHARE_GC_SHARED_COLLECTORPOLICY_HPP
-
-#include "gc/shared/barrierSet.hpp"
-#include "gc/shared/cardTableRS.hpp"
-#include "gc/shared/generationSpec.hpp"
-#include "memory/allocation.hpp"
-#include "utilities/macros.hpp"
-
-// This class (or more correctly, subtypes of this class)
-// are used to define global garbage collector attributes.
-// This includes initialization of generations and any other
-// shared resources they may need.
-//
-// In general, all flag adjustment and validation should be
-// done in initialize_flags(), which is called prior to
-// initialize_size_info().
-//
-// This class is not fully developed yet. As more collector(s)
-// are added, it is expected that we will come across further
-// behavior that requires global attention. The correct place
-// to deal with those issues is this class.
-
-// Forward declarations.
-class GenCollectorPolicy;
-class AdaptiveSizePolicy;
-class ConcurrentMarkSweepPolicy;
-class G1CollectorPolicy;
-class MarkSweepPolicy;
-
-class CollectorPolicy : public CHeapObj<mtGC> {
- protected:
-  virtual void initialize_alignments() = 0;
-  virtual void initialize_flags();
-  virtual void initialize_size_info();
-
-  DEBUG_ONLY(virtual void assert_flags();)
-  DEBUG_ONLY(virtual void assert_size_info();)
-
-  size_t _initial_heap_byte_size;
-  size_t _max_heap_byte_size;
-  size_t _min_heap_byte_size;
-
-  size_t _space_alignment;
-  size_t _heap_alignment;
-
-  CollectorPolicy();
-
- public:
-  void initialize_all() {
-    initialize_alignments();
-    initialize_flags();
-    initialize_size_info();
-  }
-
-  // Return maximum heap alignment that may be imposed by the policy.
-  static size_t compute_heap_alignment();
-
-  size_t space_alignment()        { return _space_alignment; }
-  size_t heap_alignment()         { return _heap_alignment; }
-
-  size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
-  size_t max_heap_byte_size()     { return _max_heap_byte_size; }
-  size_t min_heap_byte_size()     { return _min_heap_byte_size; }
-};
-
-class GenCollectorPolicy : public CollectorPolicy {
-  friend class TestGenCollectorPolicy;
-  friend class VMStructs;
-
-protected:
-  size_t _min_young_size;
-  size_t _initial_young_size;
-  size_t _max_young_size;
-  size_t _min_old_size;
-  size_t _initial_old_size;
-  size_t _max_old_size;
-
-  // _gen_alignment and _space_alignment will have the same value most of the
-  // time. When using large pages they can differ.
-  size_t _gen_alignment;
-
-  void initialize_flags();
-  void initialize_size_info();
-
-  DEBUG_ONLY(void assert_flags();)
-  DEBUG_ONLY(void assert_size_info();)
-
-  // Compute max heap alignment.
-  size_t compute_max_alignment();
-
-  // Scale the base_size by NewRatio according to
-  //     result = base_size / (NewRatio + 1)
-  // and align by min_alignment()
-  size_t scale_by_NewRatio_aligned(size_t base_size);
-
-  // Bound the value by the given maximum minus the min_alignment.
-  size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
-
- public:
-  GenCollectorPolicy();
-
-  // Accessors
-  size_t min_young_size()     { return _min_young_size; }
-  size_t initial_young_size() { return _initial_young_size; }
-  size_t max_young_size()     { return _max_young_size; }
-  size_t gen_alignment()      { return _gen_alignment; }
-  size_t min_old_size()       { return _min_old_size; }
-  size_t initial_old_size()   { return _initial_old_size; }
-  size_t max_old_size()       { return _max_old_size; }
-
-  size_t young_gen_size_lower_bound();
-
-  size_t old_gen_size_lower_bound();
-};
-
-class MarkSweepPolicy : public GenCollectorPolicy {
- protected:
-  void initialize_alignments();
-
- public:
-  MarkSweepPolicy() {}
-};
-
-#endif // SHARE_GC_SHARED_COLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/concurrentGCPhaseManager.cpp	Fri May 03 14:59:32 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
@@ -50,7 +50,7 @@
   assert_ConcurrentGC_thread();
   assert_not_enter_unconstrained(phase);
   assert(stack != NULL, "precondition");
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   if (stack->_top != NULL) {
     assert(stack->_top->_active, "precondition");
     _prev = stack->_top;
@@ -61,7 +61,7 @@
 
 ConcurrentGCPhaseManager::~ConcurrentGCPhaseManager() {
   assert_ConcurrentGC_thread();
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   assert_manager_is_tos(this, _stack, "This");
   wait_when_requested_impl();
   _stack->_top = _prev;
@@ -70,7 +70,7 @@
 
 bool ConcurrentGCPhaseManager::is_requested() const {
   assert_ConcurrentGC_thread();
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   assert_manager_is_tos(this, _stack, "This");
   return _active && (_stack->_requested_phase == _phase);
 }
@@ -81,14 +81,14 @@
   bool waited = false;
   while (_active && (_stack->_requested_phase == _phase)) {
     waited = true;
-    CGCPhaseManager_lock->wait(Mutex::_no_safepoint_check_flag);
+    CGCPhaseManager_lock->wait_without_safepoint_check();
   }
   return waited;
 }
 
 bool ConcurrentGCPhaseManager::wait_when_requested() const {
   assert_ConcurrentGC_thread();
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   assert_manager_is_tos(this, _stack, "This");
   return wait_when_requested_impl();
 }
@@ -96,7 +96,7 @@
 void ConcurrentGCPhaseManager::set_phase(int phase, bool force) {
   assert_ConcurrentGC_thread();
   assert_not_enter_unconstrained(phase);
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   assert_manager_is_tos(this, _stack, "This");
   if (!force) wait_when_requested_impl();
   _phase = phase;
@@ -105,7 +105,7 @@
 
 void ConcurrentGCPhaseManager::deactivate() {
   assert_ConcurrentGC_thread();
-  MonitorLockerEx ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGCPhaseManager_lock, Mutex::_no_safepoint_check_flag);
   assert_manager_is_tos(this, _stack, "This");
   _active = false;
   ml.notify_all();
@@ -114,7 +114,7 @@
 bool ConcurrentGCPhaseManager::wait_for_phase(int phase, Stack* stack) {
   assert(Thread::current()->is_Java_thread(), "precondition");
   assert(stack != NULL, "precondition");
-  MonitorLockerEx ml(CGCPhaseManager_lock);
+  MonitorLocker ml(CGCPhaseManager_lock);
   // Update request and notify service of change.
   if (stack->_requested_phase != phase) {
     stack->_requested_phase = phase;
--- a/src/hotspot/share/gc/shared/concurrentGCPhaseManager.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/concurrentGCPhaseManager.hpp	Fri May 03 14:59:32 2019 -0400
@@ -109,7 +109,7 @@
   // - this must be the current top of manager stack
   void deactivate();
 
-  // Used to implement CollectorPolicy::request_concurrent_phase().
+  // Used to implement CollectedHeap::request_concurrent_phase().
   // Updates request to the new phase, and notifies threads blocked on
   // the old request of the change.  Returns true if the phase is
   // UNCONSTRAINED_PHASE.  Otherwise, waits until an active phase is
--- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -50,7 +50,7 @@
   run_service();
 
   // Signal thread has terminated
-  MonitorLockerEx ml(Terminator_lock);
+  MonitorLocker ml(Terminator_lock);
   OrderAccess::release_store(&_has_terminated, true);
   ml.notify_all();
 }
@@ -65,7 +65,7 @@
   stop_service();
 
   // Wait for thread to terminate
-  MonitorLockerEx ml(Terminator_lock);
+  MonitorLocker ml(Terminator_lock);
   while (!_has_terminated) {
     ml.wait();
   }
--- a/src/hotspot/share/gc/shared/gcArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,13 +24,20 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/gcArguments.hpp"
+#include "logging/log.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/macros.hpp"
 
+size_t MinHeapSize = 0;
+
+size_t HeapAlignment = 0;
+size_t SpaceAlignment = 0;
+
 void GCArguments::initialize() {
   if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
     MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
@@ -65,6 +72,30 @@
   }
 }
 
+void GCArguments::initialize_heap_sizes() {
+  initialize_alignments();
+  initialize_heap_flags_and_sizes();
+  initialize_size_info();
+}
+
+size_t GCArguments::compute_heap_alignment() {
+  // The card marking array and the offset arrays for old generations are
+  // committed in os pages as well. Make sure they are entirely full (to
+  // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
+  // byte entry and the os page size is 4096, the maximum heap size should
+  // be 512*4096 = 2MB aligned.
+
+  size_t alignment = CardTableRS::ct_max_alignment_constraint();
+
+  if (UseLargePages) {
+      // In presence of large pages we have to make sure that our
+      // alignment is large page aware.
+      alignment = lcm(os::large_page_size(), alignment);
+  }
+
+  return alignment;
+}
+
 bool GCArguments::check_args_consistency() {
   bool status = true;
   if (!FLAG_IS_DEFAULT(AllocateHeapAt) && !FLAG_IS_DEFAULT(AllocateOldGenAt)) {
@@ -79,3 +110,88 @@
   }
   return status;
 }
+
+#ifdef ASSERT
+void GCArguments::assert_flags() {
+  assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
+  assert(InitialHeapSize % HeapAlignment == 0, "InitialHeapSize alignment");
+  assert(MaxHeapSize % HeapAlignment == 0, "MaxHeapSize alignment");
+}
+
+void GCArguments::assert_size_info() {
+  assert(MaxHeapSize >= MinHeapSize, "Ergonomics decided on incompatible minimum and maximum heap sizes");
+  assert(InitialHeapSize >= MinHeapSize, "Ergonomics decided on incompatible initial and minimum heap sizes");
+  assert(MaxHeapSize >= InitialHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
+  assert(MaxHeapSize % HeapAlignment == 0, "MinHeapSize alignment");
+  assert(InitialHeapSize % HeapAlignment == 0, "InitialHeapSize alignment");
+  assert(MaxHeapSize % HeapAlignment == 0, "MaxHeapSize alignment");
+}
+#endif // ASSERT
+
+void GCArguments::initialize_size_info() {
+  log_debug(gc, heap)("Minimum heap " SIZE_FORMAT "  Initial heap " SIZE_FORMAT "  Maximum heap " SIZE_FORMAT,
+                      MinHeapSize, InitialHeapSize, MaxHeapSize);
+
+  DEBUG_ONLY(assert_size_info();)
+}
+
+void GCArguments::initialize_heap_flags_and_sizes() {
+  assert(SpaceAlignment != 0, "Space alignment not set up properly");
+  assert(HeapAlignment != 0, "Heap alignment not set up properly");
+  assert(HeapAlignment >= SpaceAlignment,
+         "HeapAlignment: " SIZE_FORMAT " less than SpaceAlignment: " SIZE_FORMAT,
+         HeapAlignment, SpaceAlignment);
+  assert(HeapAlignment % SpaceAlignment == 0,
+         "HeapAlignment: " SIZE_FORMAT " not aligned by SpaceAlignment: " SIZE_FORMAT,
+         HeapAlignment, SpaceAlignment);
+
+  if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+    if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+      vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
+    }
+    if (MinHeapSize != 0 && MaxHeapSize < MinHeapSize) {
+      vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
+    }
+  }
+
+  // Check heap parameter properties
+  if (MaxHeapSize < 2 * M) {
+    vm_exit_during_initialization("Too small maximum heap");
+  }
+  if (InitialHeapSize < M) {
+    vm_exit_during_initialization("Too small initial heap");
+  }
+  if (MinHeapSize < M) {
+    vm_exit_during_initialization("Too small minimum heap");
+  }
+
+  // User inputs from -Xmx and -Xms must be aligned
+  MinHeapSize = align_up(MinHeapSize, HeapAlignment);
+  size_t aligned_initial_heap_size = align_up(InitialHeapSize, HeapAlignment);
+  size_t aligned_max_heap_size = align_up(MaxHeapSize, HeapAlignment);
+
+  // Write back to flags if the values changed
+  if (aligned_initial_heap_size != InitialHeapSize) {
+    FLAG_SET_ERGO(size_t, InitialHeapSize, aligned_initial_heap_size);
+  }
+  if (aligned_max_heap_size != MaxHeapSize) {
+    FLAG_SET_ERGO(size_t, MaxHeapSize, aligned_max_heap_size);
+  }
+
+  if (FLAG_IS_CMDLINE(InitialHeapSize) && MinHeapSize != 0 &&
+      InitialHeapSize < MinHeapSize) {
+    vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
+  }
+  if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+    FLAG_SET_ERGO(size_t, MaxHeapSize, InitialHeapSize);
+  } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
+    FLAG_SET_ERGO(size_t, InitialHeapSize, MaxHeapSize);
+    if (InitialHeapSize < MinHeapSize) {
+      MinHeapSize = InitialHeapSize;
+    }
+  }
+
+  FLAG_SET_ERGO(size_t, MinHeapDeltaBytes, align_up(MinHeapDeltaBytes, SpaceAlignment));
+
+  DEBUG_ONLY(assert_flags();)
+}
--- a/src/hotspot/share/gc/shared/gcArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -30,15 +30,30 @@
 
 class CollectedHeap;
 
+extern size_t MinHeapSize;
+
+extern size_t HeapAlignment;
+extern size_t SpaceAlignment;
+
 class GCArguments {
 protected:
-  template <class Heap, class Policy>
-  CollectedHeap* create_heap_with_policy();
+  // Initialize HeapAlignment, SpaceAlignment, and extra alignments (E.g. GenAlignment)
+  virtual void initialize_alignments() = 0;
+  virtual void initialize_heap_flags_and_sizes();
+  virtual void initialize_size_info();
+
+  DEBUG_ONLY(void assert_flags();)
+  DEBUG_ONLY(void assert_size_info();)
 
 public:
   virtual void initialize();
   virtual size_t conservative_max_heap_alignment() = 0;
   virtual CollectedHeap* create_heap() = 0;
+
+  void initialize_heap_sizes();
+
+  static size_t compute_heap_alignment();
+
   static bool check_args_consistency();
 };
 
--- a/src/hotspot/share/gc/shared/gcArguments.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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/shared/gcArguments.hpp"
-
-class CollectedHeap;
-
-template <class Heap, class Policy>
-CollectedHeap* GCArguments::create_heap_with_policy() {
-  Policy* policy = new Policy();
-  policy->initialize_all();
-  return new Heap(policy);
-}
--- a/src/hotspot/share/gc/shared/gcConfiguration.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcConfiguration.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 
 #include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcConfiguration.hpp"
 #include "memory/universe.hpp"
 #include "runtime/arguments.hpp"
@@ -131,7 +132,7 @@
 }
 
 size_t GCHeapConfiguration::min_size() const {
-  return Arguments::min_heap_size();
+  return MinHeapSize;
 }
 
 size_t GCHeapConfiguration::initial_size() const {
--- a/src/hotspot/share/gc/shared/gcLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcLocker.cpp	Fri May 03 14:59:32 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
@@ -102,7 +102,7 @@
 
 void GCLocker::stall_until_clear() {
   assert(!JavaThread::current()->in_critical(), "Would deadlock");
-  MutexLocker   ml(JNICritical_lock);
+  MonitorLocker ml(JNICritical_lock);
 
   if (needs_gc()) {
     log_debug_jni("Allocation failed. Thread stalled by JNI critical section.");
@@ -110,20 +110,20 @@
 
   // Wait for _needs_gc  to be cleared
   while (needs_gc()) {
-    JNICritical_lock->wait();
+    ml.wait();
   }
 }
 
 void GCLocker::jni_lock(JavaThread* thread) {
   assert(!thread->in_critical(), "shouldn't currently be in a critical region");
-  MutexLocker mu(JNICritical_lock);
+  MonitorLocker ml(JNICritical_lock);
   // Block entering threads if we know at least one thread is in a
   // JNI critical region and we need a GC.
   // We check that at least one thread is in a critical region before
   // blocking because blocked threads are woken up by a thread exiting
   // a JNI critical region.
   while (is_active_and_needs_gc() || _doing_gc) {
-    JNICritical_lock->wait();
+    ml.wait();
   }
   thread->enter_critical();
   _jni_lock_count++;
--- a/src/hotspot/share/gc/shared/gcOverheadChecker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.cpp	Fri May 03 14:59:32 2019 -0400
@@ -68,7 +68,7 @@
           // GC time limit may or may not have been reached. We
           // are approaching that condition and so as not to
           // throw an out-of-memory before all SoftRef's have been
-          // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
+          // cleared, set _should_clear_all_soft_refs in SoftRefPolicy.
           // The clearing will be done on the next GC.
           bool near_limit = gc_overhead_limit_near();
           if (near_limit) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/genArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/genArguments.hpp"
+#include "gc/shared/generation.hpp"
+#include "logging/log.hpp"
+#include "runtime/globals_extension.hpp"
+#include "runtime/java.hpp"
+#include "utilities/align.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+size_t MinNewSize = 0;
+
+size_t MinOldSize = 0;
+size_t MaxOldSize = 0;
+
+size_t GenAlignment = 0;
+
+size_t GenArguments::conservative_max_heap_alignment() { return (size_t)Generation::GenGrain; }
+
+static size_t young_gen_size_lower_bound() {
+  // The young generation must be aligned and have room for eden + two survivors
+  return align_up(3 * SpaceAlignment, GenAlignment);
+}
+
+static size_t old_gen_size_lower_bound() {
+  return align_up(SpaceAlignment, GenAlignment);
+}
+
+size_t GenArguments::scale_by_NewRatio_aligned(size_t base_size, size_t alignment) {
+  return align_down_bounded(base_size / (NewRatio + 1), alignment);
+}
+
+static size_t bound_minus_alignment(size_t desired_size,
+                                    size_t maximum_size,
+                                    size_t alignment) {
+  size_t max_minus = maximum_size - alignment;
+  return desired_size < max_minus ? desired_size : max_minus;
+}
+
+void GenArguments::initialize_alignments() {
+  SpaceAlignment = GenAlignment = (size_t)Generation::GenGrain;
+  HeapAlignment = compute_heap_alignment();
+}
+
+void GenArguments::initialize_heap_flags_and_sizes() {
+  GCArguments::initialize_heap_flags_and_sizes();
+
+  assert(GenAlignment != 0, "Generation alignment not set up properly");
+  assert(HeapAlignment >= GenAlignment,
+         "HeapAlignment: " SIZE_FORMAT " less than GenAlignment: " SIZE_FORMAT,
+         HeapAlignment, GenAlignment);
+  assert(GenAlignment % SpaceAlignment == 0,
+         "GenAlignment: " SIZE_FORMAT " not aligned by SpaceAlignment: " SIZE_FORMAT,
+         GenAlignment, SpaceAlignment);
+  assert(HeapAlignment % GenAlignment == 0,
+         "HeapAlignment: " SIZE_FORMAT " not aligned by GenAlignment: " SIZE_FORMAT,
+         HeapAlignment, GenAlignment);
+
+  // All generational heaps have a young gen; handle those flags here
+
+  // Make sure the heap is large enough for two generations
+  size_t smallest_new_size = young_gen_size_lower_bound();
+  size_t smallest_heap_size = align_up(smallest_new_size + old_gen_size_lower_bound(),
+                                       HeapAlignment);
+  if (MaxHeapSize < smallest_heap_size) {
+    FLAG_SET_ERGO(size_t, MaxHeapSize, smallest_heap_size);
+  }
+  // If needed, synchronize MinHeapSize size and InitialHeapSize
+  if (MinHeapSize < smallest_heap_size) {
+    MinHeapSize = smallest_heap_size;
+    if (InitialHeapSize < MinHeapSize) {
+      FLAG_SET_ERGO(size_t, InitialHeapSize, smallest_heap_size);
+    }
+  }
+
+  // Make sure NewSize allows an old generation to fit even if set on the command line
+  if (FLAG_IS_CMDLINE(NewSize) && NewSize >= InitialHeapSize) {
+    log_warning(gc, ergo)("NewSize was set larger than initial heap size, will use initial heap size.");
+    FLAG_SET_ERGO(size_t, NewSize, bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment));
+  }
+
+  // Now take the actual NewSize into account. We will silently increase NewSize
+  // if the user specified a smaller or unaligned value.
+  size_t bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize, GenAlignment);
+  bounded_new_size = MAX2(smallest_new_size, align_down(bounded_new_size, GenAlignment));
+  if (bounded_new_size != NewSize) {
+    FLAG_SET_ERGO(size_t, NewSize, bounded_new_size);
+  }
+  MinNewSize = smallest_new_size;
+
+  if (!FLAG_IS_DEFAULT(MaxNewSize)) {
+    if (MaxNewSize >= MaxHeapSize) {
+      // Make sure there is room for an old generation
+      size_t smaller_max_new_size = MaxHeapSize - GenAlignment;
+      if (FLAG_IS_CMDLINE(MaxNewSize)) {
+        log_warning(gc, ergo)("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire "
+                              "heap (" SIZE_FORMAT "k).  A new max generation size of " SIZE_FORMAT "k will be used.",
+                              MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K);
+      }
+      FLAG_SET_ERGO(size_t, MaxNewSize, smaller_max_new_size);
+      if (NewSize > MaxNewSize) {
+        FLAG_SET_ERGO(size_t, NewSize, MaxNewSize);
+      }
+    } else if (MaxNewSize < NewSize) {
+      FLAG_SET_ERGO(size_t, MaxNewSize, NewSize);
+    } else if (!is_aligned(MaxNewSize, GenAlignment)) {
+      FLAG_SET_ERGO(size_t, MaxNewSize, align_down(MaxNewSize, GenAlignment));
+    }
+  }
+
+  if (NewSize > MaxNewSize) {
+    // At this point this should only happen if the user specifies a large NewSize and/or
+    // a small (but not too small) MaxNewSize.
+    if (FLAG_IS_CMDLINE(MaxNewSize)) {
+      log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+                            "A new max generation size of " SIZE_FORMAT "k will be used.",
+                            NewSize/K, MaxNewSize/K, NewSize/K);
+    }
+    FLAG_SET_ERGO(size_t, MaxNewSize, NewSize);
+  }
+
+  if (SurvivorRatio < 1 || NewRatio < 1) {
+    vm_exit_during_initialization("Invalid young gen ratio specified");
+  }
+
+  if (OldSize < old_gen_size_lower_bound()) {
+    FLAG_SET_ERGO(size_t, OldSize, old_gen_size_lower_bound());
+  }
+  if (!is_aligned(OldSize, GenAlignment)) {
+    FLAG_SET_ERGO(size_t, OldSize, align_down(OldSize, GenAlignment));
+  }
+
+  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
+    // NewRatio will be used later to set the young generation size so we use
+    // it to calculate how big the heap should be based on the requested OldSize
+    // and NewRatio.
+    assert(NewRatio > 0, "NewRatio should have been set up earlier");
+    size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
+
+    calculated_heapsize = align_up(calculated_heapsize, HeapAlignment);
+    FLAG_SET_ERGO(size_t, MaxHeapSize, calculated_heapsize);
+    FLAG_SET_ERGO(size_t, InitialHeapSize, calculated_heapsize);
+  }
+
+  // Adjust NewSize and OldSize or MaxHeapSize to match each other
+  if (NewSize + OldSize > MaxHeapSize) {
+    if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+      // Somebody has set a maximum heap size with the intention that we should not
+      // exceed it. Adjust New/OldSize as necessary.
+      size_t calculated_size = NewSize + OldSize;
+      double shrink_factor = (double) MaxHeapSize / calculated_size;
+      size_t smaller_new_size = align_down((size_t)(NewSize * shrink_factor), GenAlignment);
+      FLAG_SET_ERGO(size_t, NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));
+
+      // OldSize is already aligned because above we aligned MaxHeapSize to
+      // HeapAlignment, and we just made sure that NewSize is aligned to
+      // GenAlignment. In initialize_flags() we verified that HeapAlignment
+      // is a multiple of GenAlignment.
+      FLAG_SET_ERGO(size_t, OldSize, MaxHeapSize - NewSize);
+    } else {
+      FLAG_SET_ERGO(size_t, MaxHeapSize, align_up(NewSize + OldSize, HeapAlignment));
+    }
+  }
+
+  // Update NewSize, if possible, to avoid sizing the young gen too small when only
+  // OldSize is set on the command line.
+  if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) {
+    if (OldSize < InitialHeapSize) {
+      size_t new_size = InitialHeapSize - OldSize;
+      if (new_size >= MinNewSize && new_size <= MaxNewSize) {
+        FLAG_SET_ERGO(size_t, NewSize, new_size);
+      }
+    }
+  }
+
+  always_do_update_barrier = UseConcMarkSweepGC;
+
+  DEBUG_ONLY(assert_flags();)
+}
+
+// Values set on the command line win over any ergonomically
+// set command line parameters.
+// Ergonomic choice of parameters are done before this
+// method is called.  Values for command line parameters such as NewSize
+// and MaxNewSize feed those ergonomic choices into this method.
+// This method makes the final generation sizings consistent with
+// themselves and with overall heap sizings.
+// In the absence of explicitly set command line flags, policies
+// such as the use of NewRatio are used to size the generation.
+
+// Minimum sizes of the generations may be different than
+// the initial sizes.  An inconsistency is permitted here
+// in the total size that can be specified explicitly by
+// command line specification of OldSize and NewSize and
+// also a command line specification of -Xms.  Issue a warning
+// but allow the values to pass.
+void GenArguments::initialize_size_info() {
+  GCArguments::initialize_size_info();
+
+  size_t max_young_size = MaxNewSize;
+
+  // Determine maximum size of the young generation.
+
+  if (FLAG_IS_DEFAULT(MaxNewSize)) {
+    max_young_size = scale_by_NewRatio_aligned(MaxHeapSize, GenAlignment);
+    // Bound the maximum size by NewSize below (since it historically
+    // would have been NewSize and because the NewRatio calculation could
+    // yield a size that is too small) and bound it by MaxNewSize above.
+    // Ergonomics plays here by previously calculating the desired
+    // NewSize and MaxNewSize.
+    max_young_size = MIN2(MAX2(max_young_size, NewSize), MaxNewSize);
+  }
+
+  // Given the maximum young size, determine the initial and
+  // minimum young sizes.
+  size_t initial_young_size = NewSize;
+
+  if (MaxHeapSize == InitialHeapSize) {
+    // The maximum and initial heap sizes are the same so the generation's
+    // initial size must be the same as it maximum size. Use NewSize as the
+    // size if set on command line.
+    max_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : max_young_size;
+    initial_young_size = max_young_size;
+
+    // Also update the minimum size if min == initial == max.
+    if (MaxHeapSize == MinHeapSize) {
+      MinNewSize = max_young_size;
+    }
+  } else {
+    if (FLAG_IS_CMDLINE(NewSize)) {
+      // If NewSize is set on the command line, we should use it as
+      // the initial size, but make sure it is within the heap bounds.
+      initial_young_size =
+        MIN2(max_young_size, bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment));
+      MinNewSize = bound_minus_alignment(initial_young_size, MinHeapSize, GenAlignment);
+    } else {
+      // For the case where NewSize is not set on the command line, use
+      // NewRatio to size the initial generation size. Use the current
+      // NewSize as the floor, because if NewRatio is overly large, the resulting
+      // size can be too small.
+      initial_young_size =
+        MIN2(max_young_size, MAX2(scale_by_NewRatio_aligned(InitialHeapSize, GenAlignment), NewSize));
+    }
+  }
+
+  log_trace(gc, heap)("1: Minimum young " SIZE_FORMAT "  Initial young " SIZE_FORMAT "  Maximum young " SIZE_FORMAT,
+                      MinNewSize, initial_young_size, max_young_size);
+
+  // At this point the minimum, initial and maximum sizes
+  // of the overall heap and of the young generation have been determined.
+  // The maximum old size can be determined from the maximum young
+  // and maximum heap size since no explicit flags exist
+  // for setting the old generation maximum.
+  MaxOldSize = MAX2(MaxHeapSize - max_young_size, GenAlignment);
+
+  size_t initial_old_size = OldSize;
+
+  // If no explicit command line flag has been set for the
+  // old generation size, use what is left.
+  if (!FLAG_IS_CMDLINE(OldSize)) {
+    // The user has not specified any value but the ergonomics
+    // may have chosen a value (which may or may not be consistent
+    // with the overall heap size).  In either case make
+    // the minimum, maximum and initial sizes consistent
+    // with the young sizes and the overall heap sizes.
+    MinOldSize = GenAlignment;
+    initial_old_size = MIN2(MaxOldSize, MAX2(InitialHeapSize - initial_young_size, MinOldSize));
+    // MaxOldSize has already been made consistent above.
+  } else {
+    // OldSize has been explicitly set on the command line. Use it
+    // for the initial size but make sure the minimum allow a young
+    // generation to fit as well.
+    // If the user has explicitly set an OldSize that is inconsistent
+    // with other command line flags, issue a warning.
+    // The generation minimums and the overall heap minimum should
+    // be within one generation alignment.
+    if (initial_old_size > MaxOldSize) {
+      log_warning(gc, ergo)("Inconsistency between maximum heap size and maximum "
+                            "generation sizes: using maximum heap = " SIZE_FORMAT
+                            ", -XX:OldSize flag is being ignored",
+                            MaxHeapSize);
+      initial_old_size = MaxOldSize;
+    }
+
+    MinOldSize = MIN2(initial_old_size, MinHeapSize - MinNewSize);
+  }
+
+  // The initial generation sizes should match the initial heap size,
+  // if not issue a warning and resize the generations. This behavior
+  // differs from JDK8 where the generation sizes have higher priority
+  // than the initial heap size.
+  if ((initial_old_size + initial_young_size) != InitialHeapSize) {
+    log_warning(gc, ergo)("Inconsistency between generation sizes and heap size, resizing "
+                          "the generations to fit the heap.");
+
+    size_t desired_young_size = InitialHeapSize - initial_old_size;
+    if (InitialHeapSize < initial_old_size) {
+      // Old want all memory, use minimum for young and rest for old
+      initial_young_size = MinNewSize;
+      initial_old_size = InitialHeapSize - MinNewSize;
+    } else if (desired_young_size > max_young_size) {
+      // Need to increase both young and old generation
+      initial_young_size = max_young_size;
+      initial_old_size = InitialHeapSize - max_young_size;
+    } else if (desired_young_size < MinNewSize) {
+      // Need to decrease both young and old generation
+      initial_young_size = MinNewSize;
+      initial_old_size = InitialHeapSize - MinNewSize;
+    } else {
+      // The young generation boundaries allow us to only update the
+      // young generation.
+      initial_young_size = desired_young_size;
+    }
+
+    log_trace(gc, heap)("2: Minimum young " SIZE_FORMAT "  Initial young " SIZE_FORMAT "  Maximum young " SIZE_FORMAT,
+                        MinNewSize, initial_young_size, max_young_size);
+  }
+
+  // Write back to flags if necessary.
+  if (NewSize != initial_young_size) {
+    FLAG_SET_ERGO(size_t, NewSize, initial_young_size);
+  }
+
+  if (MaxNewSize != max_young_size) {
+    FLAG_SET_ERGO(size_t, MaxNewSize, max_young_size);
+  }
+
+  if (OldSize != initial_old_size) {
+    FLAG_SET_ERGO(size_t, OldSize, initial_old_size);
+  }
+
+  log_trace(gc, heap)("Minimum old " SIZE_FORMAT "  Initial old " SIZE_FORMAT "  Maximum old " SIZE_FORMAT,
+                      MinOldSize, OldSize, MaxOldSize);
+
+  DEBUG_ONLY(assert_size_info();)
+}
+
+#ifdef ASSERT
+void GenArguments::assert_flags() {
+  GCArguments::assert_flags();
+  assert(NewSize >= MinNewSize, "Ergonomics decided on a too small young gen size");
+  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
+  assert(NewSize % GenAlignment == 0, "NewSize alignment");
+  assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
+  assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
+  assert(OldSize % GenAlignment == 0, "OldSize alignment");
+}
+
+void GenArguments::assert_size_info() {
+  GCArguments::assert_size_info();
+  // GenArguments::initialize_size_info may update the MaxNewSize
+  assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
+  assert(MinNewSize <= NewSize, "Ergonomics decided on incompatible minimum and initial young gen sizes");
+  assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+  assert(MinNewSize % GenAlignment == 0, "_min_young_size alignment");
+  assert(NewSize % GenAlignment == 0, "_initial_young_size alignment");
+  assert(MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
+  assert(MinNewSize <= bound_minus_alignment(MinNewSize, MinHeapSize, GenAlignment),
+      "Ergonomics made minimum young generation larger than minimum heap");
+  assert(NewSize <=  bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment),
+      "Ergonomics made initial young generation larger than initial heap");
+  assert(MaxNewSize <= bound_minus_alignment(MaxNewSize, MaxHeapSize, GenAlignment),
+      "Ergonomics made maximum young generation lager than maximum heap");
+  assert(MinOldSize <= OldSize, "Ergonomics decided on incompatible minimum and initial old gen sizes");
+  assert(OldSize <= MaxOldSize, "Ergonomics decided on incompatible initial and maximum old gen sizes");
+  assert(MaxOldSize % GenAlignment == 0, "MaxOldSize alignment");
+  assert(OldSize % GenAlignment == 0, "OldSize alignment");
+  assert(MaxHeapSize <= (MaxNewSize + MaxOldSize), "Total maximum heap sizes must be sum of generation maximum sizes");
+  assert(MinNewSize + MinOldSize <= MinHeapSize, "Minimum generation sizes exceed minimum heap size");
+  assert(NewSize + OldSize == InitialHeapSize, "Initial generation sizes should match initial heap size");
+  assert(MaxNewSize + MaxOldSize == MaxHeapSize, "Maximum generation sizes should match maximum heap size");
+}
+#endif // ASSERT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/genArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_GENARGUMENTS_HPP
+#define SHARE_GC_SHARED_GENARGUMENTS_HPP
+
+#include "gc/shared/gcArguments.hpp"
+#include "utilities/debug.hpp"
+
+extern size_t MinNewSize;
+
+extern size_t MinOldSize;
+extern size_t MaxOldSize;
+
+extern size_t GenAlignment;
+
+class GenArguments : public GCArguments {
+  friend class TestGenCollectorPolicy; // Testing
+private:
+  virtual void initialize_alignments();
+  virtual void initialize_size_info();
+
+  // Return the (conservative) maximum heap alignment
+  virtual size_t conservative_max_heap_alignment();
+
+  DEBUG_ONLY(void assert_flags();)
+  DEBUG_ONLY(void assert_size_info();)
+
+  static size_t scale_by_NewRatio_aligned(size_t base_size, size_t alignment);
+
+protected:
+  virtual void initialize_heap_flags_and_sizes();
+};
+
+#endif // SHARE_GC_SHARED_GENARGUMENTS_HPP
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -42,6 +42,7 @@
 #include "gc/shared/gcPolicyCounters.hpp"
 #include "gc/shared/gcTrace.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/gcVMOperations.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
@@ -69,22 +70,23 @@
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
 #include "utilities/vmError.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
-GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy,
-                                   Generation::Name young,
+GenCollectedHeap::GenCollectedHeap(Generation::Name young,
                                    Generation::Name old,
                                    const char* policy_counters_name) :
   CollectedHeap(),
   _young_gen_spec(new GenerationSpec(young,
-                                     policy->initial_young_size(),
-                                     policy->max_young_size(),
-                                     policy->gen_alignment())),
+                                     NewSize,
+                                     MaxNewSize,
+                                     GenAlignment)),
   _old_gen_spec(new GenerationSpec(old,
-                                   policy->initial_old_size(),
-                                   policy->max_old_size(),
-                                   policy->gen_alignment())),
+                                   OldSize,
+                                   MaxOldSize,
+                                   GenAlignment)),
   _rem_set(NULL),
-  _gen_policy(policy),
   _soft_ref_gen_policy(),
   _gc_policy_counters(new GCPolicyCounters(policy_counters_name, 2, 2)),
   _full_collections_completed(0),
@@ -104,9 +106,7 @@
   char* heap_address;
   ReservedSpace heap_rs;
 
-  size_t heap_alignment = collector_policy()->heap_alignment();
-
-  heap_address = allocate(heap_alignment, &heap_rs);
+  heap_address = allocate(HeapAlignment, &heap_rs);
 
   if (!heap_rs.is_reserved()) {
     vm_shutdown_during_initialization(
@@ -167,7 +167,7 @@
   *heap_rs = Universe::reserve_heap(total_reserved, alignment);
 
   os::trace_page_sizes("Heap",
-                       collector_policy()->min_heap_byte_size(),
+                       MinHeapSize,
                        total_reserved,
                        alignment,
                        heap_rs->base(),
@@ -233,7 +233,7 @@
 // Update the _full_collections_completed counter
 // at the end of a stop-world full GC.
 unsigned int GenCollectedHeap::update_full_collections_completed() {
-  MonitorLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
   assert(_full_collections_completed <= _total_full_collections,
          "Can't complete more collections than were started");
   _full_collections_completed = _total_full_collections;
@@ -247,7 +247,7 @@
 // without synchronizing in any manner with the VM thread (which
 // may already have initiated a STW full collection "concurrently").
 unsigned int GenCollectedHeap::update_full_collections_completed(unsigned int count) {
-  MonitorLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
   assert((_full_collections_completed <= _total_full_collections) &&
          (count <= _total_full_collections),
          "Can't complete more collections than were started");
@@ -857,10 +857,16 @@
   if (_process_strong_tasks->try_claim_task(GCH_PS_jvmti_oops_do)) {
     JvmtiExport::oops_do(strong_roots);
   }
+#if INCLUDE_AOT
   if (UseAOT && _process_strong_tasks->try_claim_task(GCH_PS_aot_oops_do)) {
     AOTLoader::oops_do(strong_roots);
   }
-
+#endif
+#if INCLUDE_JVMCI
+  if (EnableJVMCI && _process_strong_tasks->try_claim_task(GCH_PS_jvmci_oops_do)) {
+    JVMCI::oops_do(strong_roots);
+  }
+#endif
   if (_process_strong_tasks->try_claim_task(GCH_PS_SystemDictionary_oops_do)) {
     SystemDictionary::oops_do(strong_roots);
   }
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -26,12 +26,12 @@
 #define SHARE_GC_SHARED_GENCOLLECTEDHEAP_HPP
 
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/generation.hpp"
 #include "gc/shared/oopStorageParState.hpp"
 #include "gc/shared/softRefGenPolicy.hpp"
 
 class AdaptiveSizePolicy;
+class CardTableRS;
 class GCPolicyCounters;
 class GenerationSpec;
 class StrongRootsScope;
@@ -41,7 +41,6 @@
 // A "GenCollectedHeap" is a CollectedHeap that uses generational
 // collection.  It has two generations, young and old.
 class GenCollectedHeap : public CollectedHeap {
-  friend class GenCollectorPolicy;
   friend class Generation;
   friend class DefNewGeneration;
   friend class TenuredGeneration;
@@ -75,9 +74,6 @@
   // The singleton CardTable Remembered Set.
   CardTableRS* _rem_set;
 
-  // The generational collector policy.
-  GenCollectorPolicy* _gen_policy;
-
   SoftRefGenPolicy _soft_ref_gen_policy;
 
   // The sizing of the heap is controlled by a sizing policy.
@@ -117,7 +113,8 @@
     GCH_PS_ClassLoaderDataGraph_oops_do,
     GCH_PS_jvmti_oops_do,
     GCH_PS_CodeCache_oops_do,
-    GCH_PS_aot_oops_do,
+    AOT_ONLY(GCH_PS_aot_oops_do COMMA)
+    JVMCI_ONLY(GCH_PS_jvmci_oops_do COMMA)
     GCH_PS_younger_gens,
     // Leave this one last.
     GCH_PS_NumElements
@@ -158,8 +155,7 @@
   // we absolutely __must__ clear soft refs?
   bool must_clear_all_soft_refs();
 
-  GenCollectedHeap(GenCollectorPolicy *policy,
-                   Generation::Name young,
+  GenCollectedHeap(Generation::Name young,
                    Generation::Name old,
                    const char* policy_counters_name);
 
@@ -185,11 +181,6 @@
   GenerationSpec* young_gen_spec() const;
   GenerationSpec* old_gen_spec() const;
 
-  // The generational collector policy.
-  GenCollectorPolicy* gen_policy() const { return _gen_policy; }
-
-  virtual CollectorPolicy* collector_policy() const { return gen_policy(); }
-
   virtual SoftRefPolicy* soft_ref_policy() { return &_soft_ref_gen_policy; }
 
   // Adaptive size policy
@@ -200,11 +191,6 @@
   // Performance Counter support
   GCPolicyCounters* counters()     { return _gc_policy_counters; }
 
-  // Return the (conservative) maximum heap alignment
-  static size_t conservative_max_heap_alignment() {
-    return Generation::GenGrain;
-  }
-
   size_t capacity() const;
   size_t used() const;
 
--- a/src/hotspot/share/gc/shared/generation.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/generation.cpp	Fri May 03 14:59:32 2019 -0400
@@ -33,6 +33,7 @@
 #include "gc/shared/genOopClosures.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/generation.hpp"
+#include "gc/shared/generationSpec.hpp"
 #include "gc/shared/space.inline.hpp"
 #include "gc/shared/spaceDecorator.hpp"
 #include "logging/log.hpp"
--- a/src/hotspot/share/gc/shared/generationSpec.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/generationSpec.cpp	Fri May 03 14:59:32 2019 -0400
@@ -42,31 +42,18 @@
   switch (name()) {
 #if INCLUDE_SERIALGC
     case Generation::DefNew:
-      return new DefNewGeneration(rs, init_size());
+      return new DefNewGeneration(rs, _init_size, _min_size, _max_size);
 
     case Generation::MarkSweepCompact:
-      return new TenuredGeneration(rs, init_size(), remset);
+      return new TenuredGeneration(rs, _init_size, _min_size, _max_size, remset);
 #endif
 
 #if INCLUDE_CMSGC
     case Generation::ParNew:
-      return new ParNewGeneration(rs, init_size());
+      return new ParNewGeneration(rs, _init_size, _min_size, _max_size);
 
     case Generation::ConcurrentMarkSweep: {
-      assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
-      if (remset == NULL) {
-        vm_exit_during_initialization("Rem set incompatibility.");
-      }
-      // Otherwise
-      // The constructor creates the CMSCollector if needed,
-      // else registers with an existing CMSCollector
-
-      ConcurrentMarkSweepGeneration* g = NULL;
-      g = new ConcurrentMarkSweepGeneration(rs, init_size(), remset);
-
-      g->initialize_performance_counters();
-
-      return g;
+      return new ConcurrentMarkSweepGeneration(rs, _init_size, _min_size, _max_size, remset);
     }
 #endif // INCLUDE_CMSGC
 
--- a/src/hotspot/share/gc/shared/generationSpec.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/generationSpec.hpp	Fri May 03 14:59:32 2019 -0400
@@ -37,6 +37,7 @@
 private:
   Generation::Name _name;
   size_t           _init_size;
+  size_t           _min_size;
   size_t           _max_size;
 
 public:
@@ -48,12 +49,10 @@
 
   Generation* init(ReservedSpace rs, CardTableRS* remset);
 
-  // Accessors
-  Generation::Name name()        const { return _name; }
-  size_t init_size()             const { return _init_size; }
-  void set_init_size(size_t size)      { _init_size = size; }
-  size_t max_size()              const { return _max_size; }
-  void set_max_size(size_t size)       { _max_size = size; }
+  Generation::Name name() const { return _name; }
+  size_t init_size()      const { return _init_size; }
+  size_t min_size()       const { return _min_size; }
+  size_t max_size()       const { return _max_size; }
 };
 
 typedef GenerationSpec* GenerationSpecPtr;
--- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,8 +23,9 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcConfig.hpp"
 #include "gc/shared/jvmFlagConstraintsGC.hpp"
 #include "gc/shared/plab.hpp"
@@ -313,12 +314,12 @@
 
 #if INCLUDE_G1GC
   if (UseG1GC) {
-    // For G1 GC, we don't know until G1CollectorPolicy is created.
+    // For G1 GC, we don't know until G1CollectedHeap is created.
     heap_alignment = MaxSizeForHeapAlignmentG1();
   } else
 #endif
   {
-    heap_alignment = CollectorPolicy::compute_heap_alignment();
+    heap_alignment = GCArguments::compute_heap_alignment();
   }
 
   return MaxSizeForAlignment(name, value, heap_alignment, verbose);
@@ -422,12 +423,12 @@
 
 JVMFlag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
   if (FLAG_IS_CMDLINE(SurvivorRatio) &&
-      (value > (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()))) {
+      (value > (MaxHeapSize / SpaceAlignment))) {
     JVMFlag::printError(verbose,
                         "SurvivorRatio (" UINTX_FORMAT ") must be "
                         "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
                         value,
-                        (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()));
+                        (MaxHeapSize / SpaceAlignment));
     return JVMFlag::VIOLATES_CONSTRAINT;
   } else {
     return JVMFlag::SUCCESS;
--- a/src/hotspot/share/gc/shared/memAllocator.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp	Fri May 03 14:59:32 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
@@ -198,20 +198,27 @@
     return;
   }
 
-  if (JvmtiExport::should_post_sampled_object_alloc()) {
-    // If we want to be sampling, protect the allocated object with a Handle
-    // before doing the callback. The callback is done in the destructor of
-    // the JvmtiSampledObjectAllocEventCollector.
+  // If we want to be sampling, protect the allocated object with a Handle
+  // before doing the callback. The callback is done in the destructor of
+  // the JvmtiSampledObjectAllocEventCollector.
+  size_t bytes_since_last = 0;
+
+  {
     PreserveObj obj_h(_thread, _obj_ptr);
     JvmtiSampledObjectAllocEventCollector collector;
     size_t size_in_bytes = _allocator._word_size * HeapWordSize;
     ThreadLocalAllocBuffer& tlab = _thread->tlab();
-    size_t bytes_since_last = _allocated_outside_tlab ? 0 : tlab.bytes_since_last_sample_point();
+
+    if (!_allocated_outside_tlab) {
+      bytes_since_last = tlab.bytes_since_last_sample_point();
+    }
+
     _thread->heap_sampler().check_for_sampling(obj_h(), size_in_bytes, bytes_since_last);
   }
 
   if (_tlab_end_reset_for_sample || _allocated_tlab_size != 0) {
-    _thread->tlab().set_sample_end();
+    // Tell tlab to forget bytes_since_last if we passed it to the heap sampler.
+    _thread->tlab().set_sample_end(bytes_since_last != 0);
   }
 }
 
@@ -283,12 +290,14 @@
   ThreadLocalAllocBuffer& tlab = _thread->tlab();
 
   if (JvmtiExport::should_post_sampled_object_alloc()) {
-    // Try to allocate the sampled object from TLAB, it is possible a sample
-    // point was put and the TLAB still has space.
     tlab.set_back_allocation_end();
     mem = tlab.allocate(_word_size);
+
+    // We set back the allocation sample point to try to allocate this, reset it
+    // when done.
+    allocation._tlab_end_reset_for_sample = true;
+
     if (mem != NULL) {
-      allocation._tlab_end_reset_for_sample = true;
       return mem;
     }
   }
--- a/src/hotspot/share/gc/shared/oopStorage.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp	Fri May 03 14:59:32 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
@@ -412,7 +412,7 @@
 // is empty, for ease of empty block deletion processing.
 
 oop* OopStorage::allocate() {
-  MutexLockerEx ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
 
   // Note: Without this we might never perform cleanup.  As it is,
   // cleanup is only requested here, when completing a concurrent
@@ -447,7 +447,7 @@
   assert_lock_strong(_allocation_mutex);
   Block* block;
   {
-    MutexUnlockerEx ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+    MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
     block = Block::new_block(this);
   }
   if (block == NULL) return false;
@@ -481,14 +481,14 @@
     if (block != NULL) {
       return block;
     } else if (reduce_deferred_updates()) {
-      MutexUnlockerEx ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
       notify_needs_cleanup();
     } else if (try_add_block()) {
       block = _allocation_list.head();
       assert(block != NULL, "invariant");
       return block;
     } else if (reduce_deferred_updates()) { // Once more before failure.
-      MutexUnlockerEx ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
       notify_needs_cleanup();
     } else {
       // Attempt to add a block failed, no other thread added a block,
@@ -765,10 +765,10 @@
          "%s: active_mutex must have lower rank than allocation_mutex", _name);
   assert(Service_lock->rank() < _active_mutex->rank(),
          "%s: active_mutex must have higher rank than Service_lock", _name);
-  assert(_active_mutex->_safepoint_check_required != Mutex::_safepoint_check_always,
-         "%s: active mutex requires safepoint check", _name);
-  assert(_allocation_mutex->_safepoint_check_required != Mutex::_safepoint_check_always,
-         "%s: allocation mutex requires safepoint check", _name);
+  assert(_active_mutex->_safepoint_check_required == Mutex::_safepoint_check_never,
+         "%s: active mutex requires never safepoint check", _name);
+  assert(_allocation_mutex->_safepoint_check_required == Mutex::_safepoint_check_never,
+         "%s: allocation mutex requires never safepoint check", _name);
 }
 
 void OopStorage::delete_empty_block(const Block& block) {
@@ -812,13 +812,13 @@
   // Avoid re-notification if already notified.
   const uint notified = needs_cleanup_notified;
   if (Atomic::xchg(notified, &_needs_cleanup) != notified) {
-    MonitorLockerEx ml(Service_lock, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(Service_lock, Monitor::_no_safepoint_check_flag);
     ml.notify_all();
   }
 }
 
 bool OopStorage::delete_empty_blocks() {
-  MutexLockerEx ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
 
   // Clear the request before processing.
   Atomic::store(needs_cleanup_none, &_needs_cleanup);
@@ -837,7 +837,7 @@
     // might become available while we're working.
     if (reduce_deferred_updates()) {
       // Be safepoint-polite while looping.
-      MutexUnlockerEx ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
       ThreadBlockInVM tbiv(JavaThread::current());
     } else {
       Block* block = _allocation_list.tail();
@@ -850,7 +850,7 @@
 
       // Try to delete the block.  First, try to remove from _active_array.
       {
-        MutexLockerEx aml(_active_mutex, Mutex::_no_safepoint_check_flag);
+        MutexLocker aml(_active_mutex, Mutex::_no_safepoint_check_flag);
         // Don't interfere with an active concurrent iteration.
         // Instead, give up immediately.  There is more work to do,
         // but don't re-notify, to avoid useless spinning of the
@@ -861,7 +861,7 @@
       // Remove block from _allocation_list and delete it.
       _allocation_list.unlink(*block);
       // Be safepoint-polite while deleting and looping.
-      MutexUnlockerEx ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
       delete_empty_block(*block);
       ThreadBlockInVM tbiv(JavaThread::current());
     }
@@ -878,7 +878,7 @@
   const Block* block = find_block_or_null(ptr);
   if (block != NULL) {
     // Prevent block deletion and _active_array modification.
-    MutexLockerEx ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
     // Block could be a false positive, so get index carefully.
     size_t index = Block::active_index_safe(block);
     if ((index < _active_array->block_count()) &&
@@ -953,7 +953,7 @@
 
 void OopStorage::BasicParState::update_concurrent_iteration_count(int value) {
   if (_concurrent) {
-    MutexLockerEx ml(_storage->_active_mutex, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(_storage->_active_mutex, Mutex::_no_safepoint_check_flag);
     _storage->_concurrent_iteration_count += value;
     assert(_storage->_concurrent_iteration_count >= 0, "invariant");
   }
--- a/src/hotspot/share/gc/shared/owstTaskTerminator.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/owstTaskTerminator.cpp	Fri May 03 14:59:32 2019 -0400
@@ -74,7 +74,7 @@
         }
       }
     } else {
-      _blocker->wait(true, WorkStealingSleepMillis);
+      _blocker->wait_without_safepoint_check(WorkStealingSleepMillis);
 
       if (_offered_termination == _n_threads) {
         _blocker->unlock();
@@ -151,9 +151,9 @@
                                   p2i(Thread::current()), yield_count);
       yield_count = 0;
 
-      MonitorLockerEx locker(_blocker, Mutex::_no_safepoint_check_flag);
+      MonitorLocker locker(_blocker, Mutex::_no_safepoint_check_flag);
       _spin_master = NULL;
-      locker.wait(Mutex::_no_safepoint_check_flag, WorkStealingSleepMillis);
+      locker.wait(WorkStealingSleepMillis);
       if (_spin_master == NULL) {
         _spin_master = Thread::current();
       } else {
@@ -167,7 +167,7 @@
     size_t tasks = tasks_in_queue_set();
     bool exit = exit_termination(tasks, terminator);
     {
-      MonitorLockerEx locker(_blocker, Mutex::_no_safepoint_check_flag);
+      MonitorLocker locker(_blocker, Mutex::_no_safepoint_check_flag);
       // Termination condition reached
       if (_offered_termination == _n_threads) {
         _spin_master = NULL;
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp	Fri May 03 14:59:32 2019 -0400
@@ -30,6 +30,9 @@
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 StringDedupCleaningTask::StringDedupCleaningTask(BoolObjectClosure* is_alive,
                                                  OopClosure* keep_alive,
@@ -158,6 +161,27 @@
   }
 }
 
+#if INCLUDE_JVMCI
+JVMCICleaningTask::JVMCICleaningTask() :
+  _cleaning_claimed(0) {
+}
+
+bool JVMCICleaningTask::claim_cleaning_task() {
+  if (_cleaning_claimed) {
+    return false;
+  }
+
+  return Atomic::cmpxchg(1, &_cleaning_claimed, 0) == 0;
+}
+
+void JVMCICleaningTask::work(bool unloading_occurred) {
+  // One worker will clean JVMCI metadata handles.
+  if (unloading_occurred && EnableJVMCI && claim_cleaning_task()) {
+    JVMCI::do_unloading(unloading_occurred);
+  }
+}
+#endif // INCLUDE_JVMCI
+
 ParallelCleaningTask::ParallelCleaningTask(BoolObjectClosure* is_alive,
                                            uint num_workers,
                                            bool unloading_occurred,
@@ -166,11 +190,16 @@
   _unloading_occurred(unloading_occurred),
   _string_dedup_task(is_alive, NULL, resize_dedup_table),
   _code_cache_task(num_workers, is_alive, unloading_occurred),
+  JVMCI_ONLY(_jvmci_cleaning_task() COMMA)
   _klass_cleaning_task() {
 }
 
 // The parallel work done by all worker threads.
 void ParallelCleaningTask::work(uint worker_id) {
+  // Clean JVMCI metadata handles.
+  // Execute this task first because it is serial task.
+  JVMCI_ONLY(_jvmci_cleaning_task.work(_unloading_occurred);)
+
   // Do first pass of code cache cleaning.
   _code_cache_task.work(worker_id);
 
--- a/src/hotspot/share/gc/shared/parallelCleaning.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/parallelCleaning.hpp	Fri May 03 14:59:32 2019 -0400
@@ -87,6 +87,20 @@
   void work();
 };
 
+#if INCLUDE_JVMCI
+class JVMCICleaningTask : public StackObj {
+  volatile int       _cleaning_claimed;
+
+public:
+  JVMCICleaningTask();
+  // Clean JVMCI metadata handles.
+  void work(bool unloading_occurred);
+
+private:
+  bool claim_cleaning_task();
+};
+#endif
+
 // Do cleanup of some weakly held data in the same parallel task.
 // Assumes a non-moving context.
 class ParallelCleaningTask : public AbstractGangTask {
@@ -94,6 +108,9 @@
   bool                    _unloading_occurred;
   StringDedupCleaningTask _string_dedup_task;
   CodeCacheUnloadingTask  _code_cache_task;
+#if INCLUDE_JVMCI
+  JVMCICleaningTask       _jvmci_cleaning_task;
+#endif
   KlassCleaningTask       _klass_cleaning_task;
 
 public:
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp	Fri May 03 14:59:32 2019 -0400
@@ -305,7 +305,7 @@
 }
 
 void PtrQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
-  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
   cbn->set_next(NULL);
   if (_completed_buffers_tail == NULL) {
     assert(_completed_buffers_head == NULL, "Well-formedness");
@@ -328,7 +328,7 @@
 }
 
 BufferNode* PtrQueueSet::get_completed_buffer(size_t stop_at) {
-  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
 
   if (_n_completed_buffers <= stop_at) {
     return NULL;
@@ -354,7 +354,7 @@
 void PtrQueueSet::abandon_completed_buffers() {
   BufferNode* buffers_to_delete = NULL;
   {
-    MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+    MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
     buffers_to_delete = _completed_buffers_head;
     _completed_buffers_head = NULL;
     _completed_buffers_tail = NULL;
@@ -389,7 +389,7 @@
 // must share the monitor.
 void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
   assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
-  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
   if (_completed_buffers_tail == NULL) {
     assert(_completed_buffers_head == NULL, "Well-formedness");
     _completed_buffers_head = src->_completed_buffers_head;
@@ -415,7 +415,7 @@
 }
 
 void PtrQueueSet::notify_if_necessary() {
-  MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+  MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
   if (_n_completed_buffers > _process_completed_buffers_threshold) {
     _process_completed_buffers = true;
     if (_notify_when_complete)
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Fri May 03 14:59:32 2019 -0400
@@ -172,7 +172,7 @@
 #endif // ASSERT
   // Update the global state, synchronized with threads list management.
   {
-    MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
     _all_active = active;
   }
 
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Fri May 03 14:59:32 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
@@ -477,7 +477,7 @@
 
   // Delayed update to avoid contention on the table lock
   if (removed > 0) {
-    MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
     _table->_entries -= removed;
     _entries_removed += removed;
   }
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp	Fri May 03 14:59:32 2019 -0400
@@ -189,7 +189,7 @@
     // Protect the table from concurrent access. Also note that this lock
     // acts as a fence for _table, which could have been replaced by a new
     // instance if the table was resized or rehashed.
-    MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
     return _table->lookup_or_add_inner(value, latin1, hash);
   }
 
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -66,10 +66,10 @@
   }
 };
 
-// The CDS archive does not include the string dedupication table. Only the string
+// The CDS archive does not include the string deduplication table. Only the string
 // table is saved in the archive. The shared strings from CDS archive need to be
-// added to the string dedupication table before deduplication occurs. That is
-// done in the begining of the StringDedupThread (see StringDedupThread::do_deduplication()).
+// added to the string deduplication table before deduplication occurs. That is
+// done in the beginning of the StringDedupThread (see StringDedupThread::do_deduplication()).
 void StringDedupThread::deduplicate_shared_strings(StringDedupStat* stat) {
   StringDedupSharedClosure sharedStringDedup(stat);
   StringTable::shared_oops_do(&sharedStringDedup);
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,7 +33,11 @@
 void StringDedupThreadImpl<S>::do_deduplication() {
   S total_stat;
 
-  deduplicate_shared_strings(&total_stat);
+  {
+    // Block safepoints while deduplicating shared strings
+    SuspendibleThreadSetJoiner sts_join;
+    deduplicate_shared_strings(&total_stat);
+  }
 
   // Main loop
   for (;;) {
--- a/src/hotspot/share/gc/shared/suspendibleThreadSet.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/suspendibleThreadSet.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, 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
@@ -48,9 +48,9 @@
 
 void SuspendibleThreadSet::join() {
   assert(!Thread::current()->is_suspendible_thread(), "Thread already joined");
-  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
   while (_suspend_all) {
-    ml.wait(Mutex::_no_safepoint_check_flag);
+    ml.wait();
   }
   _nthreads++;
   DEBUG_ONLY(Thread::current()->set_suspendible_thread();)
@@ -58,7 +58,7 @@
 
 void SuspendibleThreadSet::leave() {
   assert(Thread::current()->is_suspendible_thread(), "Thread not joined");
-  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
   assert(_nthreads > 0, "Invalid");
   DEBUG_ONLY(Thread::current()->clear_suspendible_thread();)
   _nthreads--;
@@ -70,7 +70,7 @@
 
 void SuspendibleThreadSet::yield() {
   assert(Thread::current()->is_suspendible_thread(), "Must have joined");
-  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
   if (_suspend_all) {
     _nthreads_stopped++;
     if (is_synchronized()) {
@@ -82,7 +82,7 @@
       _synchronize_wakeup->signal();
     }
     while (_suspend_all) {
-      ml.wait(Mutex::_no_safepoint_check_flag);
+      ml.wait();
     }
     assert(_nthreads_stopped > 0, "Invalid");
     _nthreads_stopped--;
@@ -95,7 +95,7 @@
     _suspend_all_start = os::elapsedTime();
   }
   {
-    MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
     assert(!_suspend_all, "Only one at a time");
     _suspend_all = true;
     if (is_synchronized()) {
@@ -118,7 +118,7 @@
   _synchronize_wakeup->wait();
 
 #ifdef ASSERT
-  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
   assert(_suspend_all, "STS not synchronizing");
   assert(is_synchronized(), "STS not synchronized");
 #endif
@@ -126,7 +126,7 @@
 
 void SuspendibleThreadSet::desynchronize() {
   assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
-  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
   assert(_suspend_all, "STS not synchronizing");
   assert(is_synchronized(), "STS not synchronized");
   _suspend_all = false;
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Fri May 03 14:59:32 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
@@ -281,17 +281,21 @@
             _fast_refill_waste * HeapWordSize);
 }
 
-void ThreadLocalAllocBuffer::set_sample_end() {
+void ThreadLocalAllocBuffer::set_sample_end(bool reset_byte_accumulation) {
   size_t heap_words_remaining = pointer_delta(_end, _top);
   size_t bytes_until_sample = thread()->heap_sampler().bytes_until_sample();
   size_t words_until_sample = bytes_until_sample / HeapWordSize;
 
+  if (reset_byte_accumulation) {
+    _bytes_since_last_sample_point = 0;
+  }
+
   if (heap_words_remaining > words_until_sample) {
     HeapWord* new_end = _top + words_until_sample;
     set_end(new_end);
-    _bytes_since_last_sample_point = bytes_until_sample;
+    _bytes_since_last_sample_point += bytes_until_sample;
   } else {
-    _bytes_since_last_sample_point = heap_words_remaining * HeapWordSize;
+    _bytes_since_last_sample_point += heap_words_remaining * HeapWordSize;
   }
 }
 
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp	Fri May 03 14:59:32 2019 -0400
@@ -171,7 +171,7 @@
   void initialize();
 
   void set_back_allocation_end();
-  void set_sample_end();
+  void set_sample_end(bool reset_byte_accumulation);
 
   static size_t refill_waste_limit_increment()   { return TLABWasteIncrement; }
 
--- a/src/hotspot/share/gc/shared/workgroup.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shared/workgroup.cpp	Fri May 03 14:59:32 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
@@ -200,7 +200,7 @@
   }
 
   void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) {
-    MutexLockerEx ml(_monitor, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
 
     _task        = task;
     _num_workers = num_workers;
@@ -210,7 +210,7 @@
 
     // Wait for them to finish.
     while (_finished < _num_workers) {
-      _monitor->wait(/* no_safepoint_check */ true);
+      ml.wait();
     }
 
     _task        = NULL;
@@ -220,10 +220,10 @@
   }
 
   WorkData worker_wait_for_task() {
-    MonitorLockerEx ml(_monitor, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
 
     while (_num_workers == 0 || _started == _num_workers) {
-      _monitor->wait(/* no_safepoint_check */ true);
+      _monitor->wait();
     }
 
     _started++;
@@ -235,7 +235,7 @@
   }
 
   void worker_done_with_task() {
-    MonitorLockerEx ml(_monitor, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
 
     _finished++;
 
@@ -300,8 +300,6 @@
   assert(_gang != NULL, "No gang to run in");
   os::set_priority(this, NearMaxPriority);
   log_develop_trace(gc, workgang)("Running gang worker for gang %s id %u", gang()->name(), id());
-  // The VM thread should not execute here because MutexLocker's are used
-  // as (opposed to MutexLockerEx's).
   assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
          " of a work gang");
 }
@@ -369,7 +367,7 @@
 }
 
 bool WorkGangBarrierSync::enter() {
-  MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
   if (should_reset()) {
     // The should_reset() was set and we are the first worker to enter
     // the sync barrier. We will zero the n_completed() count which
@@ -389,17 +387,17 @@
     // should_reset() flag and the barrier will be reset the first
     // time a worker enters it again.
     set_should_reset(true);
-    monitor()->notify_all();
+    ml.notify_all();
   } else {
     while (n_completed() != n_workers() && !aborted()) {
-      monitor()->wait(/* no_safepoint_check */ true);
+      ml.wait();
     }
   }
   return !aborted();
 }
 
 void WorkGangBarrierSync::abort() {
-  MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
+  MutexLocker x(monitor(), Mutex::_no_safepoint_check_flag);
   set_aborted();
   monitor()->notify_all();
 }
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/workerPolicy.hpp"
 #include "gc/shenandoah/shenandoahArguments.hpp"
 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
@@ -198,6 +198,19 @@
   return align;
 }
 
+void ShenandoahArguments::initialize_alignments() {
+  // Need to setup sizes early to get correct alignments.
+  ShenandoahHeapRegion::setup_sizes(InitialHeapSize, MaxHeapSize);
+
+  // This is expected by our algorithm for ShenandoahHeap::heap_region_containing().
+  size_t align = ShenandoahHeapRegion::region_size_bytes();
+  if (UseLargePages) {
+    align = MAX2(align, os::large_page_size());
+  }
+  SpaceAlignment = align;
+  HeapAlignment = align;
+}
+
 CollectedHeap* ShenandoahArguments::create_heap() {
-  return create_heap_with_policy<ShenandoahHeap, ShenandoahCollectorPolicy>();
+  return new ShenandoahHeap(new ShenandoahCollectorPolicy());
 }
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -30,11 +30,11 @@
 class CollectedHeap;
 
 class ShenandoahArguments : public GCArguments {
-public:
-  virtual void initialize();
+private:
+  virtual void initialize_alignments();
 
+  virtual void initialize();
   virtual size_t conservative_max_heap_alignment();
-
   virtual CollectedHeap* create_heap();
 };
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Fri May 03 14:59:32 2019 -0400
@@ -79,4 +79,16 @@
   inline void do_oop_work(T* p);
 };
 
+#ifdef ASSERT
+class ShenandoahAssertNotForwardedClosure : public OopClosure {
+private:
+  template <class T>
+  inline void do_oop_work(T* p);
+
+public:
+  inline void do_oop(narrowOop* p);
+  inline void do_oop(oop* p);
+};
+#endif // ASSERT
+
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -107,4 +107,18 @@
   do_oop_work(p);
 }
 
+#ifdef ASSERT
+template <class T>
+void ShenandoahAssertNotForwardedClosure::do_oop_work(T* p) {
+  T o = RawAccess<>::oop_load(p);
+  if (!CompressedOops::is_null(o)) {
+    oop obj = CompressedOops::decode_not_null(o);
+    shenandoah_assert_not_forwarded(p, obj);
+  }
+}
+
+void ShenandoahAssertNotForwardedClosure::do_oop(narrowOop* p) { do_oop_work(p); }
+void ShenandoahAssertNotForwardedClosure::do_oop(oop* p)       { do_oop_work(p); }
+#endif
+
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp	Fri May 03 14:59:32 2019 -0400
@@ -30,22 +30,51 @@
 #include "runtime/atomic.hpp"
 #include "utilities/copy.hpp"
 
-ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, HeapWord* heap_base) :
+ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, char* heap_base, size_t size) :
   _map_size(heap->num_regions()),
   _region_size_bytes_shift(ShenandoahHeapRegion::region_size_bytes_shift()),
-  _cset_map(NEW_C_HEAP_ARRAY(jbyte, _map_size, mtGC)),
-  _biased_cset_map(_cset_map - ((uintx)heap_base >> _region_size_bytes_shift)),
+  _map_space(align_up(((uintx)heap_base + size) >> _region_size_bytes_shift, os::vm_allocation_granularity())),
+  _cset_map(_map_space.base() + ((uintx)heap_base >> _region_size_bytes_shift)),
+  _biased_cset_map(_map_space.base()),
   _heap(heap),
   _garbage(0),
   _live_data(0),
   _used(0),
   _region_count(0),
   _current_index(0) {
-  // Use 1-byte data type
-  STATIC_ASSERT(sizeof(jbyte) == 1);
+
+  // The collection set map is reserved to cover the entire heap *and* zero addresses.
+  // This is needed to accept in-cset checks for both heap oops and NULLs, freeing
+  // high-performance code from checking for NULL first.
+  //
+  // Since heap_base can be far away, committing the entire map would waste memory.
+  // Therefore, we only commit the parts that are needed to operate: the heap view,
+  // and the zero page.
+  //
+  // Note: we could instead commit the entire map, and piggyback on OS virtual memory
+  // subsystem for mapping not-yet-written-to pages to a single physical backing page,
+  // but this is not guaranteed, and would confuse NMT and other memory accounting tools.
+
+  MemTracker::record_virtual_memory_type(_map_space.base(), mtGC);
+
+  size_t page_size = (size_t)os::vm_page_size();
 
-  // Initialize cset map
+  if (!_map_space.special()) {
+    // Commit entire pages that cover the heap cset map.
+    char* bot_addr = align_down(_cset_map, page_size);
+    char* top_addr = align_up(_cset_map + _map_size, page_size);
+    os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), false,
+                              "Unable to commit collection set bitmap: heap");
+
+    // Commit the zero page, if not yet covered by heap cset map.
+    if (bot_addr != _biased_cset_map) {
+      os::commit_memory_or_exit(_biased_cset_map, page_size, false,
+                                "Unable to commit collection set bitmap: zero page");
+    }
+  }
+
   Copy::zero_to_bytes(_cset_map, _map_size);
+  Copy::zero_to_bytes(_biased_cset_map, page_size);
 }
 
 void ShenandoahCollectionSet::add_region(ShenandoahHeapRegion* r) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,9 +33,10 @@
 private:
   size_t const          _map_size;
   size_t const          _region_size_bytes_shift;
-  jbyte* const          _cset_map;
+  ReservedSpace         _map_space;
+  char* const           _cset_map;
   // Bias cset map's base address for fast test if an oop is in cset
-  jbyte* const          _biased_cset_map;
+  char* const           _biased_cset_map;
 
   ShenandoahHeap* const _heap;
 
@@ -49,7 +50,7 @@
   DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
 
 public:
-  ShenandoahCollectionSet(ShenandoahHeap* heap, HeapWord* heap_base);
+  ShenandoahCollectionSet(ShenandoahHeap* heap, char* heap_base, size_t size);
 
   // Add region to collection set
   void add_region(ShenandoahHeapRegion* r);
@@ -88,7 +89,10 @@
   void clear();
 
 private:
-  jbyte* biased_map_address() const {
+  char* map_address() const {
+    return _cset_map;
+  }
+  char* biased_map_address() const {
     return _biased_cset_map;
   }
 };
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -42,24 +42,10 @@
 
   Copy::zero_to_bytes(_degen_points, sizeof(size_t) * ShenandoahHeap::_DEGENERATED_LIMIT);
 
-  ShenandoahHeapRegion::setup_sizes(initial_heap_byte_size(), max_heap_byte_size());
-
-  initialize_all();
-
   _tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer();
 
 }
 
-void ShenandoahCollectorPolicy::initialize_alignments() {
-  // This is expected by our algorithm for ShenandoahHeap::heap_region_containing().
-  size_t align = ShenandoahHeapRegion::region_size_bytes();
-  if (UseLargePages) {
-    align = MAX2(align, os::large_page_size());
-  }
-  _space_alignment = align;
-  _heap_alignment = align;
-}
-
 void ShenandoahCollectorPolicy::record_explicit_to_concurrent() {
   _explicit_concurrent++;
 }
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp	Fri May 03 14:59:32 2019 -0400
@@ -24,12 +24,12 @@
 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTORPOLICY_HPP
 #define SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTORPOLICY_HPP
 
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shenandoah/shenandoahHeap.hpp"
 #include "gc/shenandoah/shenandoahTracer.hpp"
+#include "memory/allocation.hpp"
 #include "utilities/ostream.hpp"
 
-class ShenandoahCollectorPolicy: public CollectorPolicy {
+class ShenandoahCollectorPolicy : public CHeapObj<mtGC> {
 private:
   size_t _success_concurrent_gcs;
   size_t _success_degenerated_gcs;
@@ -52,8 +52,6 @@
 public:
   ShenandoahCollectorPolicy();
 
-  void initialize_alignments();
-
   // TODO: This is different from gc_end: that one encompasses one VM operation.
   // These two encompass the entire cycle.
   void record_cycle_start();
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri May 03 14:59:32 2019 -0400
@@ -360,7 +360,7 @@
   if (ShenandoahConcurrentScanCodeRoots && claim_codecache()) {
     ShenandoahObjToScanQueue* q = task_queues()->queue(worker_id);
     if (!_heap->unload_classes()) {
-      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       // TODO: We can not honor StringDeduplication here, due to lock ranking
       // inversion. So, we may miss some deduplication candidates.
       if (_heap->has_forwarded_objects()) {
@@ -661,15 +661,13 @@
 // anything to them.
 void ShenandoahConcurrentMark::weak_roots_work() {
   WorkGang* workers = _heap->workers();
-  ShenandoahIsAliveSelector is_alive;
-
-  if (_heap->has_forwarded_objects()) {
-    ShenandoahWeakUpdateClosure cl;
-    WeakProcessor::weak_oops_do(workers, is_alive.is_alive_closure(), &cl, 1);
-  } else {
-    ShenandoahWeakAssertNotForwardedClosure cl;
-    WeakProcessor::weak_oops_do(workers, is_alive.is_alive_closure(), &cl, 1);
-  }
+  OopClosure* keep_alive = &do_nothing_cl;
+#ifdef ASSERT
+  ShenandoahWeakAssertNotForwardedClosure verify_cl;
+  keep_alive = &verify_cl;
+#endif
+  ShenandoahIsAliveClosure is_alive;
+  WeakProcessor::weak_oops_do(workers, &is_alive, keep_alive, 1);
 }
 
 void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -508,7 +508,7 @@
 void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
   _requested_gc_cause = cause;
   _gc_requested.set();
-  MonitorLockerEx ml(&_gc_waiters_lock);
+  MonitorLocker ml(&_gc_waiters_lock);
   while (_gc_requested.is_set()) {
     ml.wait();
   }
@@ -528,7 +528,7 @@
     heap->cancel_gc(GCCause::_allocation_failure);
   }
 
-  MonitorLockerEx ml(&_alloc_failure_waiters_lock);
+  MonitorLocker ml(&_alloc_failure_waiters_lock);
   while (is_alloc_failure_gc()) {
     ml.wait();
   }
@@ -549,7 +549,7 @@
 
 void ShenandoahControlThread::notify_alloc_failure_waiters() {
   _alloc_failure_gc.unset();
-  MonitorLockerEx ml(&_alloc_failure_waiters_lock);
+  MonitorLocker ml(&_alloc_failure_waiters_lock);
   ml.notify_all();
 }
 
@@ -563,7 +563,7 @@
 
 void ShenandoahControlThread::notify_gc_waiters() {
   _gc_requested.unset();
-  MonitorLockerEx ml(&_gc_waiters_lock);
+  MonitorLocker ml(&_gc_waiters_lock);
   ml.notify_all();
 }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 #include "memory/allocation.hpp"
 
+#include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcTimer.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
 #include "gc/shared/memAllocator.hpp"
@@ -66,6 +67,7 @@
 #include "gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp"
 
 #include "memory/metaspace.hpp"
+#include "runtime/globals.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/safepointMechanism.hpp"
 #include "runtime/vmThread.hpp"
@@ -139,10 +141,10 @@
   // Figure out heap sizing
   //
 
-  size_t init_byte_size = collector_policy()->initial_heap_byte_size();
-  size_t min_byte_size  = collector_policy()->min_heap_byte_size();
-  size_t max_byte_size  = collector_policy()->max_heap_byte_size();
-  size_t heap_alignment = collector_policy()->heap_alignment();
+  size_t init_byte_size = InitialHeapSize;
+  size_t min_byte_size  = MinHeapSize;
+  size_t max_byte_size  = MaxHeapSize;
+  size_t heap_alignment = HeapAlignment;
 
   size_t reg_size_bytes = ShenandoahHeapRegion::region_size_bytes();
 
@@ -259,7 +261,7 @@
 
   _regions = NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, _num_regions, mtGC);
   _free_set = new ShenandoahFreeSet(this, _num_regions);
-  _collection_set = new ShenandoahCollectionSet(this, (HeapWord*)sh_rs.base());
+  _collection_set = new ShenandoahCollectionSet(this, sh_rs.base(), sh_rs.size());
 
   {
     ShenandoahHeapLocker locker(lock());
@@ -537,6 +539,15 @@
                p2i(reserved_region().start()),
                p2i(reserved_region().end()));
 
+  ShenandoahCollectionSet* cset = collection_set();
+  st->print_cr("Collection set:");
+  if (cset != NULL) {
+    st->print_cr(" - map (vanilla): " PTR_FORMAT, p2i(cset->map_address()));
+    st->print_cr(" - map (biased):  " PTR_FORMAT, p2i(cset->biased_map_address()));
+  } else {
+    st->print_cr(" (NULL)");
+  }
+
   st->cr();
   MetaspaceUtils::print_on(st);
 
@@ -1150,10 +1161,6 @@
   //assert(false, "Shouldn't need to do full collections");
 }
 
-CollectorPolicy* ShenandoahHeap::collector_policy() const {
-  return _shenandoah_policy;
-}
-
 HeapWord* ShenandoahHeap::block_start(const void* addr) const {
   Space* sp = heap_region_containing(addr);
   if (sp != NULL) {
@@ -1480,8 +1487,13 @@
   if (!cancelled_gc()) {
     concurrent_mark()->finish_mark_from_roots(/* full_gc = */ false);
 
-    if (has_forwarded_objects()) {
-      concurrent_mark()->update_roots(ShenandoahPhaseTimings::update_roots);
+    // Degen may be caused by failed evacuation of roots
+    if (is_degenerated_gc_in_progress() && has_forwarded_objects()) {
+      concurrent_mark()->update_roots(ShenandoahPhaseTimings::degen_gc_update_roots);
+    }
+
+    if (ShenandoahVerify) {
+      verifier()->verify_roots_no_forwarded();
     }
 
     stop_concurrent_marking();
@@ -1533,6 +1545,7 @@
       }
 
       if (ShenandoahVerify) {
+        verifier()->verify_roots_no_forwarded();
         verifier()->verify_during_evacuation();
       }
     } else {
@@ -2169,8 +2182,8 @@
   assert(!cancelled_gc(), "Should have been done right before");
 
   concurrent_mark()->update_roots(is_degenerated_gc_in_progress() ?
-                                 ShenandoahPhaseTimings::degen_gc_update_roots:
-                                 ShenandoahPhaseTimings::final_update_refs_roots);
+                                  ShenandoahPhaseTimings::degen_gc_update_roots:
+                                  ShenandoahPhaseTimings::final_update_refs_roots);
 
   ShenandoahGCPhase final_update_refs(ShenandoahPhaseTimings::final_update_refs_recycle);
 
@@ -2179,6 +2192,7 @@
   set_update_refs_in_progress(false);
 
   if (ShenandoahVerify) {
+    verifier()->verify_roots_no_forwarded();
     verifier()->verify_after_updaterefs();
   }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -479,7 +479,6 @@
   MemoryUsage memory_usage();
   GCTracer* tracer();
   GCTimer* gc_timer() const;
-  CollectorPolicy* collector_policy() const;
 
 // ---------- Reference processing
 //
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 03 14:59:32 2019 -0400
@@ -42,26 +42,6 @@
 #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::resolved_method_table, ShenandoahPhaseTimings::ResolvedMethodTableRoots},
-  {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)),
@@ -84,32 +64,16 @@
     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);
-    }
+    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+    ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings,
+                                                                           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);
@@ -123,6 +87,13 @@
   ObjectSynchronizer::oops_do(oops);
   SystemDictionary::oops_do(oops);
 
+  AlwaysTrueClosure always_true;
+  WeakProcessor::weak_oops_do(&always_true, oops);
+
+  if (ShenandoahStringDedup::is_enabled()) {
+    ShenandoahStringDedup::oops_do_slow(oops);
+  }
+
   // Do thread roots the last. This allows verification code to find
   // any broken objects from those special roots first, not the accidental
   // dangling reference from the thread root.
@@ -243,7 +214,9 @@
   _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
   _srs(n_workers),
   _phase(phase),
-  _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()) {
+  _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
+  _weak_processor_timings(n_workers),
+  _weak_processor_task(&_weak_processor_timings, n_workers) {
   heap->phase_timings()->record_workers_start(_phase);
   if (ShenandoahStringDedup::is_enabled()) {
     StringDedup::gc_prologue(false);
@@ -255,6 +228,12 @@
   if (ShenandoahStringDedup::is_enabled()) {
     StringDedup::gc_epilogue();
   }
+
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+  assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
+  ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings,
+                                                                         worker_times);
+
   ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
 }
 
@@ -262,13 +241,19 @@
                                                      CodeBlobClosure* blobs,
                                                      uint worker_id) {
 
+  AlwaysTrueClosure always_true;
   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
   {
     bool is_par = n_workers() > 1;
     ResourceMark rm;
     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
+    Threads::possibly_parallel_oops_do(is_par, oops, NULL);
+  }
 
-    Threads::possibly_parallel_oops_do(is_par, oops, NULL);
+  {
+    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+    CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
+    _cld_iterator.root_cld_do(&clds, &clds);
   }
 
   if (blobs != NULL) {
@@ -277,8 +262,7 @@
   }
 
   if (ShenandoahStringDedup::is_enabled()) {
-    ShenandoahForwardedIsAliveClosure is_alive;
-    ShenandoahStringDedup::parallel_oops_do(&is_alive, oops, worker_id);
+    ShenandoahStringDedup::parallel_oops_do(&always_true, oops, worker_id);
   }
 
   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Universe_oops_do)) {
@@ -298,6 +282,11 @@
     JvmtiExport::weak_oops_do(&is_alive, oops);
   }
 
+  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_JNIHandles_oops_do)) {
+    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
+    JNIHandles::oops_do(oops);
+  }
+
   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_SystemDictionary_oops_do)) {
     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
     SystemDictionary::oops_do(oops);
@@ -308,6 +297,7 @@
     ObjectSynchronizer::oops_do(oops);
   }
 
+  _weak_processor_task.work<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, oops);
 }
 
 uint ShenandoahRootEvacuator::n_workers() const {
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri May 03 14:59:32 2019 -0400
@@ -119,6 +119,9 @@
   StrongRootsScope _srs;
   ShenandoahPhaseTimings::Phase _phase;
   ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
+  ParallelCLDRootIterator _cld_iterator;
+  WeakProcessorPhaseTimes _weak_processor_timings;
+  WeakProcessor::Task     _weak_processor_task;
 
   enum Shenandoah_evacuate_roots_tasks {
     SHENANDOAH_EVAC_Universe_oops_do,
@@ -126,6 +129,7 @@
     SHENANDOAH_EVAC_Management_oops_do,
     SHENANDOAH_EVAC_SystemDictionary_oops_do,
     SHENANDOAH_EVAC_jvmti_oops_do,
+    SHENANDOAH_EVAC_JNIHandles_oops_do,
     // Leave this one last.
     SHENANDOAH_EVAC_NumElements
   };
--- a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.cpp	Fri May 03 14:59:32 2019 -0400
@@ -48,7 +48,7 @@
 }
 
 ShenandoahStrDedupQueue::~ShenandoahStrDedupQueue() {
-  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
   for (size_t index = 0; index < num_queues(); index ++) {
     release_buffers(queue_at(index));
   }
@@ -58,9 +58,9 @@
 }
 
 void ShenandoahStrDedupQueue::wait_impl() {
-  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
   while (_consumer_queue == NULL && !_cancel) {
-    ml.wait(Mutex::_no_safepoint_check_flag);
+    ml.wait();
     assert(_consumer_queue == NULL, "Why wait?");
     _consumer_queue = _published_queues;
     _published_queues = NULL;
@@ -68,7 +68,7 @@
 }
 
 void ShenandoahStrDedupQueue::cancel_wait_impl() {
-  MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
   _cancel = true;
   ml.notify();
 }
@@ -105,11 +105,11 @@
   ShenandoahQueueBuffer* buf = queue_at((size_t)worker_id);
 
   if (buf == NULL) {
-    MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
     buf = new_buffer();
     set_producer_buffer(buf, worker_id);
   } else if (buf->is_full()) {
-    MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
     buf->set_next(_published_queues);
     _published_queues = buf;
     buf = new_buffer();
@@ -125,7 +125,7 @@
   assert(Thread::current() == StringDedupThread::thread(), "Must be dedup thread");
   while (true) {
     if (_consumer_queue == NULL) {
-      MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+      MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
       _consumer_queue = _published_queues;
       _published_queues = NULL;
     }
@@ -163,7 +163,7 @@
   } while (obj == NULL);
 
   if (to_release != NULL) {
-    MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
     release_buffers(to_release);
   }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp	Fri May 03 14:59:32 2019 -0400
@@ -183,3 +183,47 @@
   ShenandoahThreadLocalData::set_worker_id(thr, ShenandoahThreadLocalData::INVALID_WORKER_ID);
 #endif
 }
+
+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::resolved_method_table, ShenandoahPhaseTimings::ResolvedMethodTableRoots},
+  {WeakProcessorPhases::vm,                    ShenandoahPhaseTimings::VMWeakRoots}
+};
+
+STATIC_ASSERT(sizeof(phase_mapping) / sizeof(PhaseMap) == WeakProcessorPhases::phase_count);
+
+void ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(WeakProcessorPhaseTimes* weak_processing_timings,
+                                                                            ShenandoahWorkerTimings* sh_worker_times) {
+  assert(weak_processing_timings->max_threads() == weak_processing_timings->max_threads(), "Must match");
+  for (uint index = 0; index < WeakProcessorPhases::phase_count; index ++) {
+    weak_processing_phase_to_shenandoah_phase(phase_mapping[index]._weak_processor_phase,
+                                              weak_processing_timings,
+                                              phase_mapping[index]._shenandoah_phase,
+                                              sh_worker_times);
+  }
+}
+
+void ShenandoahTimingConverter::weak_processing_phase_to_shenandoah_phase(WeakProcessorPhases::Phase wpp,
+                                                                          WeakProcessorPhaseTimes* weak_processing_timings,
+                                                                          ShenandoahPhaseTimings::GCParPhases spp,
+                                                                          ShenandoahWorkerTimings* sh_worker_times) {
+  if (WeakProcessorPhases::is_serial(wpp)) {
+    sh_worker_times->record_time_secs(spp, 0, weak_processing_timings->phase_time_sec(wpp));
+  } else {
+    for (uint index = 0; index < weak_processing_timings->max_threads(); index ++) {
+      sh_worker_times->record_time_secs(spp, index, weak_processing_timings->worker_time_sec(index, wpp));
+    }
+  }
+}
--- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp	Fri May 03 14:59:32 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
@@ -24,14 +24,14 @@
 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
 #define SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
 
-#include "jfr/jfrEvents.hpp"
-
 #include "gc/shared/gcCause.hpp"
+#include "gc/shared/gcVMOperations.hpp"
 #include "gc/shared/isGCActiveMark.hpp"
 #include "gc/shared/suspendibleThreadSet.hpp"
-#include "gc/shared/gcVMOperations.hpp"
+#include "gc/shared/weakProcessorPhaseTimes.hpp"
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
+#include "jfr/jfrEvents.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/vmThread.hpp"
@@ -175,4 +175,15 @@
   }
 };
 
+class ShenandoahTimingConverter : public AllStatic {
+public:
+  static void weak_processing_timing_to_shenandoah_timing(WeakProcessorPhaseTimes* weak_processing_timings,
+                                                          ShenandoahWorkerTimings* sh_worker_times);
+private:
+  static void weak_processing_phase_to_shenandoah_phase(WeakProcessorPhases::Phase wpp,
+                                                        WeakProcessorPhaseTimes* weak_processing_timings,
+                                                        ShenandoahPhaseTimings::GCParPhases spp,
+                                                        ShenandoahWorkerTimings* sh_worker_times);
+};
+
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp	Fri May 03 14:59:32 2019 -0400
@@ -919,3 +919,31 @@
           _verify_gcstate_stable       // full gc cleaned up everything
   );
 }
+
+class ShenandoahVerifyNoForwared : public OopClosure {
+private:
+  template <class T>
+  void do_oop_work(T* p) {
+    T o = RawAccess<>::oop_load(p);
+    if (!CompressedOops::is_null(o)) {
+      oop obj = CompressedOops::decode_not_null(o);
+      oop fwd = (oop) ShenandoahBrooksPointer::get_raw_unchecked(obj);
+      if (!oopDesc::equals_raw(obj, fwd)) {
+        ShenandoahAsserts::print_failure(ShenandoahAsserts::_safe_all, obj, p, NULL,
+                                         "Verify Roots", "Should not be forwarded", __FILE__, __LINE__);
+      }
+    }
+  }
+
+public:
+  void do_oop(narrowOop* p) { do_oop_work(p); }
+  void do_oop(oop* p)       { do_oop_work(p); }
+};
+
+void ShenandoahVerifier::verify_roots_no_forwarded() {
+  guarantee(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "only when nothing else happens");
+  ShenandoahRootProcessor rp(_heap, 1, ShenandoahPhaseTimings::_num_phases); // no need for stats
+  ShenandoahVerifyNoForwared cl;
+  rp.process_all_roots_slow(&cl);
+}
+
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp	Fri May 03 14:59:32 2019 -0400
@@ -186,6 +186,9 @@
   void verify_after_traversal();
   void verify_after_degenerated();
   void verify_generic(VerifyOption option);
+
+  // Roots should only contain to-space oops
+  void verify_roots_no_forwarded();
 };
 
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHVERIFIER_HPP
--- a/src/hotspot/share/gc/z/zAddress.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zAddress.cpp	Fri May 03 14:59:32 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
@@ -22,27 +22,47 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zAddress.hpp"
 #include "gc/z/zGlobals.hpp"
-#include "runtime/thread.hpp"
 
-void ZAddressMasks::set_good_mask(uintptr_t mask) {
-  uintptr_t old_bad_mask = ZAddressBadMask;
+void ZAddress::set_good_mask(uintptr_t mask) {
   ZAddressGoodMask = mask;
   ZAddressBadMask = ZAddressGoodMask ^ ZAddressMetadataMask;
   ZAddressWeakBadMask = (ZAddressGoodMask | ZAddressMetadataRemapped | ZAddressMetadataFinalizable) ^ ZAddressMetadataMask;
 }
 
-void ZAddressMasks::initialize() {
+void ZAddress::initialize() {
+  ZAddressSpaceStart = ZPlatformAddressSpaceStart();
+  ZAddressSpaceEnd = ZPlatformAddressSpaceEnd();
+  ZAddressSpaceSize = ZAddressSpaceEnd - ZAddressSpaceStart;
+
+  ZAddressReservedStart = ZPlatformAddressReservedStart();
+  ZAddressReservedEnd = ZPlatformAddressReservedEnd();
+  ZAddressReservedSize = ZAddressReservedEnd - ZAddressReservedStart;
+
+  ZAddressBase = ZPlatformAddressBase();
+
+  ZAddressOffsetBits = ZPlatformAddressOffsetBits();
+  ZAddressOffsetMask = (((uintptr_t)1 << ZAddressOffsetBits) - 1) << ZAddressOffsetShift;
+  ZAddressOffsetMax = (uintptr_t)1 << ZAddressOffsetBits;
+
+  ZAddressMetadataShift = ZPlatformAddressMetadataShift();
+  ZAddressMetadataMask = (((uintptr_t)1 << ZAddressMetadataBits) - 1) << ZAddressMetadataShift;
+
+  ZAddressMetadataMarked0 = (uintptr_t)1 << (ZAddressMetadataShift + 0);
+  ZAddressMetadataMarked1 = (uintptr_t)1 << (ZAddressMetadataShift + 1);
+  ZAddressMetadataRemapped = (uintptr_t)1 << (ZAddressMetadataShift + 2);
+  ZAddressMetadataFinalizable = (uintptr_t)1 << (ZAddressMetadataShift + 3);
+
   ZAddressMetadataMarked = ZAddressMetadataMarked0;
   set_good_mask(ZAddressMetadataRemapped);
 }
 
-void ZAddressMasks::flip_to_marked() {
+void ZAddress::flip_to_marked() {
   ZAddressMetadataMarked ^= (ZAddressMetadataMarked0 | ZAddressMetadataMarked1);
   set_good_mask(ZAddressMetadataMarked);
 }
 
-void ZAddressMasks::flip_to_remapped() {
+void ZAddress::flip_to_remapped() {
   set_good_mask(ZAddressMetadataRemapped);
 }
--- a/src/hotspot/share/gc/z/zAddress.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zAddress.hpp	Fri May 03 14:59:32 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,7 +27,17 @@
 #include "memory/allocation.hpp"
 
 class ZAddress : public AllStatic {
+  friend class ZAddressTest;
+
+private:
+  static void set_good_mask(uintptr_t mask);
+
 public:
+  static void initialize();
+
+  static void flip_to_marked();
+  static void flip_to_remapped();
+
   static bool is_null(uintptr_t value);
   static bool is_bad(uintptr_t value);
   static bool is_good(uintptr_t value);
@@ -52,16 +62,4 @@
   static uintptr_t remapped_or_null(uintptr_t value);
 };
 
-class ZAddressMasks : public AllStatic {
-  friend class ZAddressTest;
-
-private:
-  static void set_good_mask(uintptr_t mask);
-
-public:
-  static void initialize();
-  static void flip_to_marked();
-  static void flip_to_remapped();
-};
-
 #endif // SHARE_GC_Z_ZADDRESS_HPP
--- a/src/hotspot/share/gc/z/zAddress.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zAddress.inline.hpp	Fri May 03 14:59:32 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
@@ -27,7 +27,6 @@
 #include "gc/z/zAddress.hpp"
 #include "gc/z/zGlobals.hpp"
 #include "utilities/macros.hpp"
-#include OS_CPU_HEADER_INLINE(gc/z/zAddress)
 
 inline bool ZAddress::is_null(uintptr_t value) {
   return value == 0;
@@ -82,6 +81,10 @@
   return value & ZAddressMetadataRemapped;
 }
 
+inline uintptr_t ZAddress::address(uintptr_t value) {
+  return value | ZAddressBase;
+}
+
 inline uintptr_t ZAddress::offset(uintptr_t value) {
   return value & ZAddressOffsetMask;
 }
--- a/src/hotspot/share/gc/z/zArguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zArguments.cpp	Fri May 03 14:59:32 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
@@ -24,19 +24,24 @@
 #include "precompiled.hpp"
 #include "gc/z/zArguments.hpp"
 #include "gc/z/zCollectedHeap.hpp"
-#include "gc/z/zCollectorPolicy.hpp"
 #include "gc/z/zWorkers.hpp"
-#include "gc/shared/gcArguments.inline.hpp"
+#include "gc/shared/gcArguments.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 
-size_t ZArguments::conservative_max_heap_alignment() {
-  return 0;
+void ZArguments::initialize_alignments() {
+  SpaceAlignment = ZGranuleSize;
+  HeapAlignment = SpaceAlignment;
 }
 
 void ZArguments::initialize() {
   GCArguments::initialize();
 
+  // Check max heap size
+  if (MaxHeapSize > ZMaxHeapSize) {
+    vm_exit_during_initialization("Java heap too large");
+  }
+
   // Enable NUMA by default
   if (FLAG_IS_DEFAULT(UseNUMA)) {
     FLAG_SET_DEFAULT(UseNUMA, true);
@@ -95,6 +100,10 @@
   initialize_platform();
 }
 
+size_t ZArguments::conservative_max_heap_alignment() {
+  return 0;
+}
+
 CollectedHeap* ZArguments::create_heap() {
-  return create_heap_with_policy<ZCollectedHeap, ZCollectorPolicy>();
+  return new ZCollectedHeap();
 }
--- a/src/hotspot/share/gc/z/zArguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zArguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -32,7 +32,8 @@
 private:
   void initialize_platform();
 
-public:
+  virtual void initialize_alignments();
+
   virtual void initialize();
   virtual size_t conservative_max_heap_alignment();
   virtual CollectedHeap* create_heap();
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -40,8 +40,7 @@
   return (ZCollectedHeap*)heap;
 }
 
-ZCollectedHeap::ZCollectedHeap(ZCollectorPolicy* policy) :
-    _collector_policy(policy),
+ZCollectedHeap::ZCollectedHeap() :
     _soft_ref_policy(),
     _barrier_set(),
     _initialize(&_barrier_set),
@@ -56,7 +55,7 @@
 }
 
 const char* ZCollectedHeap::name() const {
-  return ZGCName;
+  return ZName;
 }
 
 jint ZCollectedHeap::initialize() {
@@ -64,8 +63,8 @@
     return JNI_ENOMEM;
   }
 
-  initialize_reserved_region((HeapWord*)ZAddressReservedStart(),
-                             (HeapWord*)ZAddressReservedEnd());
+  initialize_reserved_region((HeapWord*)ZAddressReservedStart,
+                             (HeapWord*)ZAddressReservedEnd);
 
   return JNI_OK;
 }
@@ -80,10 +79,6 @@
   _stat->stop();
 }
 
-CollectorPolicy* ZCollectedHeap::collector_policy() const {
-  return _collector_policy;
-}
-
 SoftRefPolicy* ZCollectedHeap::soft_ref_policy() {
   return &_soft_ref_policy;
 }
@@ -100,6 +95,10 @@
   return _heap.used();
 }
 
+size_t ZCollectedHeap::unused() const {
+  return _heap.unused();
+}
+
 bool ZCollectedHeap::is_maximal_no_gc() const {
   // Not supported
   ShouldNotReachHere();
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/softRefPolicy.hpp"
 #include "gc/z/zBarrierSet.hpp"
-#include "gc/z/zCollectorPolicy.hpp"
 #include "gc/z/zDirector.hpp"
 #include "gc/z/zDriver.hpp"
 #include "gc/z/zInitialize.hpp"
@@ -39,7 +38,6 @@
   friend class VMStructs;
 
 private:
-  ZCollectorPolicy* _collector_policy;
   SoftRefPolicy     _soft_ref_policy;
   ZBarrierSet       _barrier_set;
   ZInitialize       _initialize;
@@ -56,19 +54,19 @@
 public:
   static ZCollectedHeap* heap();
 
-  ZCollectedHeap(ZCollectorPolicy* policy);
+  ZCollectedHeap();
   virtual Name kind() const;
   virtual const char* name() const;
   virtual jint initialize();
   virtual void initialize_serviceability();
   virtual void stop();
 
-  virtual CollectorPolicy* collector_policy() const;
   virtual SoftRefPolicy* soft_ref_policy();
 
   virtual size_t max_capacity() const;
   virtual size_t capacity() const;
   virtual size_t used() const;
+  virtual size_t unused() const;
 
   virtual bool is_maximal_no_gc() const;
   virtual bool is_in(const void* p) const;
--- a/src/hotspot/share/gc/z/zCollectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * 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/zCollectorPolicy.hpp"
-#include "gc/z/zGlobals.hpp"
-
-void ZCollectorPolicy::initialize_alignments() {
-  _space_alignment = ZGranuleSize;
-  _heap_alignment = _space_alignment;
-}
--- a/src/hotspot/share/gc/z/zCollectorPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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.
- */
-
-#ifndef SHARE_GC_Z_ZCOLLECTORPOLICY_HPP
-#define SHARE_GC_Z_ZCOLLECTORPOLICY_HPP
-
-#include "gc/shared/collectorPolicy.hpp"
-
-class ZCollectorPolicy : public CollectorPolicy {
-public:
-  virtual void initialize_alignments();
-};
-
-#endif // SHARE_GC_Z_ZCOLLECTORPOLICY_HPP
--- a/src/hotspot/share/gc/z/zGlobals.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zGlobals.cpp	Fri May 03 14:59:32 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
@@ -31,7 +31,28 @@
 const int& ZObjectAlignmentSmall      = MinObjAlignmentInBytes;
 
 uintptr_t ZAddressGoodMask;
-uintptr_t ZAddressBadMask             = 0;
+uintptr_t ZAddressBadMask;
 uintptr_t ZAddressWeakBadMask;
 
+uintptr_t ZAddressBase;
+
+size_t    ZAddressOffsetBits;
+uintptr_t ZAddressOffsetMask;
+size_t    ZAddressOffsetMax;
+
+size_t    ZAddressMetadataShift;
+uintptr_t ZAddressMetadataMask;
+
 uintptr_t ZAddressMetadataMarked;
+uintptr_t ZAddressMetadataMarked0;
+uintptr_t ZAddressMetadataMarked1;
+uintptr_t ZAddressMetadataRemapped;
+uintptr_t ZAddressMetadataFinalizable;
+
+uintptr_t ZAddressSpaceStart;
+uintptr_t ZAddressSpaceEnd;
+size_t    ZAddressSpaceSize;
+
+uintptr_t ZAddressReservedStart;
+uintptr_t ZAddressReservedEnd;
+size_t    ZAddressReservedSize;
--- a/src/hotspot/share/gc/z/zGlobals.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zGlobals.hpp	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,7 @@
 #include OS_CPU_HEADER(gc/z/zGlobals)
 
 // Collector name
-const char* const ZGCName                       = "The Z Garbage Collector";
+const char* const ZName                         = "The Z Garbage Collector";
 
 // Global phase state
 extern uint32_t   ZGlobalPhase;
@@ -44,6 +44,10 @@
 const size_t      ZGranuleSizeShift             = ZPlatformGranuleSizeShift;
 const size_t      ZGranuleSize                  = (size_t)1 << ZGranuleSizeShift;
 
+// Max heap size shift/size
+const size_t      ZMaxHeapSizeShift             = ZPlatformMaxHeapSizeShift;
+const size_t      ZMaxHeapSize                  = (size_t)1 << ZMaxHeapSizeShift;
+
 // Page types
 const uint8_t     ZPageTypeSmall                = 0;
 const uint8_t     ZPageTypeMedium               = 1;
@@ -71,38 +75,6 @@
 const int         ZObjectAlignmentMedium        = 1 << ZObjectAlignmentMediumShift;
 const int         ZObjectAlignmentLarge         = 1 << ZObjectAlignmentLargeShift;
 
-// Pointer part of address
-const uintptr_t   ZAddressOffsetShift           = 0;
-const uintptr_t   ZAddressOffsetBits            = ZPlatformAddressOffsetBits;
-const uintptr_t   ZAddressOffsetMask            = (((uintptr_t)1 << ZAddressOffsetBits) - 1) << ZAddressOffsetShift;
-const size_t      ZAddressOffsetMax             = (uintptr_t)1 << ZAddressOffsetBits;
-
-// Metadata part of address
-const uintptr_t   ZAddressMetadataShift         = ZPlatformAddressMetadataShift;
-const uintptr_t   ZAddressMetadataBits          = 4;
-const uintptr_t   ZAddressMetadataMask          = (((uintptr_t)1 << ZAddressMetadataBits) - 1) << ZAddressMetadataShift;
-
-// Metadata types
-const uintptr_t   ZAddressMetadataMarked0       = (uintptr_t)1 << (ZAddressMetadataShift + 0);
-const uintptr_t   ZAddressMetadataMarked1       = (uintptr_t)1 << (ZAddressMetadataShift + 1);
-const uintptr_t   ZAddressMetadataRemapped      = (uintptr_t)1 << (ZAddressMetadataShift + 2);
-const uintptr_t   ZAddressMetadataFinalizable   = (uintptr_t)1 << (ZAddressMetadataShift + 3);
-
-// Address space start/end/size
-const uintptr_t   ZAddressSpaceStart            = ZPlatformAddressSpaceStart;
-const uintptr_t   ZAddressSpaceSize             = ZPlatformAddressSpaceSize;
-const uintptr_t   ZAddressSpaceEnd              = ZAddressSpaceStart + ZAddressSpaceSize;
-
-// NMethod entry barrier
-const size_t      ZNMethodDisarmedOffset        = ZPlatformNMethodDisarmedOffset;
-
-// Cache line size
-const size_t      ZCacheLineSize                = ZPlatformCacheLineSize;
-
-// Reserved start/end
-uintptr_t ZAddressReservedStart();
-uintptr_t ZAddressReservedEnd();
-
 //
 // Good/Bad mask states
 // --------------------
@@ -119,8 +91,42 @@
 extern uintptr_t  ZAddressBadMask;
 extern uintptr_t  ZAddressWeakBadMask;
 
-// Marked state
+// Pointer base address
+extern uintptr_t  ZAddressBase;
+
+// Pointer part of address
+extern size_t     ZAddressOffsetBits;
+const  size_t     ZAddressOffsetShift           = 0;
+extern uintptr_t  ZAddressOffsetMask;
+extern size_t     ZAddressOffsetMax;
+
+// Metadata part of address
+const size_t      ZAddressMetadataBits          = 4;
+extern size_t     ZAddressMetadataShift;
+extern uintptr_t  ZAddressMetadataMask;
+
+// Metadata types
 extern uintptr_t  ZAddressMetadataMarked;
+extern uintptr_t  ZAddressMetadataMarked0;
+extern uintptr_t  ZAddressMetadataMarked1;
+extern uintptr_t  ZAddressMetadataRemapped;
+extern uintptr_t  ZAddressMetadataFinalizable;
+
+// Address space start/end/size
+extern uintptr_t  ZAddressSpaceStart;
+extern uintptr_t  ZAddressSpaceEnd;
+extern size_t     ZAddressSpaceSize;
+
+// Reserved space start/end
+extern uintptr_t  ZAddressReservedStart;
+extern uintptr_t  ZAddressReservedEnd;
+extern size_t     ZAddressReservedSize;
+
+// NMethod entry barrier
+const size_t      ZNMethodDisarmedOffset        = ZPlatformNMethodDisarmedOffset;
+
+// Cache line size
+const size_t      ZCacheLineSize                = ZPlatformCacheLineSize;
 
 // Mark stack space
 extern uintptr_t  ZMarkStackSpaceStart;
--- a/src/hotspot/share/gc/z/zHeap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zHeap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -133,6 +133,10 @@
   return _page_allocator.used();
 }
 
+size_t ZHeap::unused() const {
+  return _page_allocator.unused();
+}
+
 size_t ZHeap::allocated() const {
   return _page_allocator.allocated();
 }
@@ -169,7 +173,7 @@
 }
 
 bool ZHeap::is_in(uintptr_t addr) const {
-  if (addr < ZAddressReservedStart() || addr >= ZAddressReservedEnd()) {
+  if (addr < ZAddressReservedStart || addr >= ZAddressReservedEnd) {
     return false;
   }
 
@@ -265,13 +269,13 @@
 
 void ZHeap::flip_to_marked() {
   before_flip();
-  ZAddressMasks::flip_to_marked();
+  ZAddress::flip_to_marked();
   after_flip();
 }
 
 void ZHeap::flip_to_remapped() {
   before_flip();
-  ZAddressMasks::flip_to_remapped();
+  ZAddress::flip_to_remapped();
   after_flip();
 }
 
--- a/src/hotspot/share/gc/z/zHeap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zHeap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -94,6 +94,7 @@
   size_t used_high() const;
   size_t used_low() const;
   size_t used() const;
+  size_t unused() const;
   size_t allocated() const;
   size_t reclaimed() const;
 
--- a/src/hotspot/share/gc/z/zInitialize.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zInitialize.cpp	Fri May 03 14:59:32 2019 -0400
@@ -36,13 +36,13 @@
 #include "runtime/vm_version.hpp"
 
 ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
-  log_info(gc, init)("Initializing %s", ZGCName);
+  log_info(gc, init)("Initializing %s", ZName);
   log_info(gc, init)("Version: %s (%s)",
                      VM_Version::vm_release(),
                      VM_Version::jdk_debug_level());
 
   // Early initialization
-  ZAddressMasks::initialize();
+  ZAddress::initialize();
   ZNUMA::initialize();
   ZCPU::initialize();
   ZStatValue::initialize();
--- a/src/hotspot/share/gc/z/zMessagePort.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zMessagePort.inline.hpp	Fri May 03 14:59:32 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
@@ -79,7 +79,7 @@
 
   {
     // Enqueue message
-    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
     request.initialize(message, _seqnum);
     _queue.insert_last(&request);
     ml.notify();
@@ -96,13 +96,13 @@
     // thread have returned from sem_wait(). To avoid this race we are
     // forcing the waiting thread to acquire/release the lock held by the
     // posting thread. https://sourceware.org/bugzilla/show_bug.cgi?id=12674
-    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
   }
 }
 
 template <typename T>
 inline void ZMessagePort<T>::send_async(T message) {
-  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
   if (!_has_message) {
     // Post message
     _message = message;
@@ -113,11 +113,11 @@
 
 template <typename T>
 inline T ZMessagePort<T>::receive() {
-  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
 
   // Wait for message
   while (!_has_message && _queue.is_empty()) {
-    ml.wait(Monitor::_no_safepoint_check_flag);
+    ml.wait();
   }
 
   // Increment request sequence number
@@ -134,7 +134,7 @@
 
 template <typename T>
 inline void ZMessagePort<T>::ack() {
-  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
 
   if (!_has_message) {
     // Nothing to ack
--- a/src/hotspot/share/gc/z/zMetronome.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zMetronome.cpp	Fri May 03 14:59:32 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
@@ -53,10 +53,10 @@
     const uint64_t next_ms = _start_ms + (_interval_ms * _nticks);
     const int64_t timeout_ms = next_ms - now_ms;
 
-    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
     if (!_stopped && timeout_ms > 0) {
       // Wait
-      ml.wait(Monitor::_no_safepoint_check_flag, timeout_ms);
+      ml.wait(timeout_ms);
     } else {
       // Tick
       return !_stopped;
@@ -65,7 +65,7 @@
 }
 
 void ZMetronome::stop() {
-  MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
   _stopped = true;
   ml.notify();
 }
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp	Fri May 03 14:59:32 2019 -0400
@@ -195,7 +195,7 @@
   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
 
   while (_iteration.in_progress()) {
-    CodeCache_lock->wait(Monitor::_no_safepoint_check_flag);
+    CodeCache_lock->wait_without_safepoint_check();
   }
 }
 
@@ -209,7 +209,7 @@
 }
 
 void ZNMethodTable::nmethods_do_begin() {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
   // Do not allow the table to be deleted while iterating
   _safe_delete.enable_deferred_delete();
@@ -219,7 +219,7 @@
 }
 
 void ZNMethodTable::nmethods_do_end() {
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
   // Finish iteration
   _iteration.nmethods_do_end();
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp	Fri May 03 14:59:32 2019 -0400
@@ -37,6 +37,7 @@
 #include "runtime/init.hpp"
 
 static const ZStatCounter       ZCounterAllocationRate("Memory", "Allocation Rate", ZStatUnitBytesPerSecond);
+static const ZStatCounter       ZCounterPageCacheEvict("Memory", "Page Cache Evict", ZStatUnitBytesPerSecond);
 static const ZStatCriticalPhase ZCriticalPhaseAllocationStall("Allocation Stall");
 
 class ZPageAllocRequest : public StackObj {
@@ -133,6 +134,11 @@
   return _used;
 }
 
+size_t ZPageAllocator::unused() const {
+  const ssize_t unused = (ssize_t)_physical.capacity() - (ssize_t)_used - (ssize_t)_max_reserve;
+  return unused > 0 ? (size_t)unused : 0;
+}
+
 size_t ZPageAllocator::allocated() const {
   return _allocated;
 }
@@ -266,16 +272,6 @@
   pmem.clear();
 }
 
-void ZPageAllocator::flush_cache(size_t size) {
-  ZList<ZPage> list;
-
-  _cache.flush(&list, size);
-
-  for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
-    destroy_page(page);
-  }
-}
-
 void ZPageAllocator::check_out_of_memory_during_initialization() {
   if (!is_init_completed()) {
     vm_exit_during_initialization("java.lang.OutOfMemoryError", "Java heap too small");
@@ -308,8 +304,11 @@
   // Try ensure that physical memory is available
   const size_t unused = try_ensure_unused(size, flags.no_reserve());
   if (unused < size) {
-    // Flush cache to free up more physical memory
-    flush_cache(size - unused);
+    // Try evict pages from the cache
+    const size_t needed = size - unused;
+    if (_cache.available() >= needed) {
+      evict_cache(needed);
+    }
   }
 
   // Create new page and allocate physical memory
@@ -463,6 +462,61 @@
   satisfy_alloc_queue();
 }
 
+void ZPageAllocator::flush_cache(ZPageCacheFlushClosure* cl) {
+  ZList<ZPage> list;
+
+  _cache.flush(cl, &list);
+
+  for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
+    destroy_page(page);
+  }
+}
+
+class ZPageCacheEvictClosure : public ZPageCacheFlushClosure {
+private:
+  const size_t _requested;
+  size_t       _evicted;
+
+public:
+  ZPageCacheEvictClosure(size_t requested) :
+      _requested(requested),
+      _evicted(0) {}
+
+  virtual bool do_page(const ZPage* page) {
+    if (_evicted < _requested) {
+      // Evict page
+      _evicted += page->size();
+      return true;
+    }
+
+    // Don't evict page
+    return false;
+  }
+
+  size_t evicted() const {
+    return _evicted;
+  }
+};
+
+void ZPageAllocator::evict_cache(size_t requested) {
+  // Evict pages
+  ZPageCacheEvictClosure cl(requested);
+  flush_cache(&cl);
+
+  const size_t evicted = cl.evicted();
+  const size_t cached_after = _cache.available();
+  const size_t cached_before = cached_after + evicted;
+
+  log_info(gc, heap)("Page Cache: " SIZE_FORMAT "M(%.0lf%%)->" SIZE_FORMAT "M(%.0lf%%), "
+                     "Evicted: " SIZE_FORMAT "M, Requested: " SIZE_FORMAT "M",
+                     cached_before / M, percent_of(cached_before, max_capacity()),
+                     cached_after / M, percent_of(cached_after, max_capacity()),
+                     evicted / M, requested / M);
+
+  // Update statistics
+  ZStatInc(ZCounterPageCacheEvict, evicted);
+}
+
 void ZPageAllocator::enable_deferred_delete() const {
   _safe_delete.enable_deferred_delete();
 }
--- a/src/hotspot/share/gc/z/zPageAllocator.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zPageAllocator.hpp	Fri May 03 14:59:32 2019 -0400
@@ -67,7 +67,8 @@
   void destroy_page(ZPage* page);
 
   void flush_pre_mapped();
-  void flush_cache(size_t size);
+  void flush_cache(ZPageCacheFlushClosure* cl);
+  void evict_cache(size_t requested);
 
   void check_out_of_memory_during_initialization();
 
@@ -92,6 +93,7 @@
   size_t used_high() const;
   size_t used_low() const;
   size_t used() const;
+  size_t unused() const;
   size_t allocated() const;
   size_t reclaimed() const;
 
--- a/src/hotspot/share/gc/z/zPageCache.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zPageCache.cpp	Fri May 03 14:59:32 2019 -0400
@@ -32,7 +32,6 @@
 static const ZStatCounter ZCounterPageCacheHitL1("Memory", "Page Cache Hit L1", ZStatUnitOpsPerSecond);
 static const ZStatCounter ZCounterPageCacheHitL2("Memory", "Page Cache Hit L2", ZStatUnitOpsPerSecond);
 static const ZStatCounter ZCounterPageCacheMiss("Memory", "Page Cache Miss", ZStatUnitOpsPerSecond);
-static const ZStatCounter ZCounterPageCacheFlush("Memory", "Page Cache Flush", ZStatUnitBytesPerSecond);
 
 ZPageCache::ZPageCache() :
     _available(0),
@@ -130,64 +129,49 @@
   _available += page->size();
 }
 
-void ZPageCache::flush_list(ZList<ZPage>* from, size_t requested, ZList<ZPage>* to, size_t* flushed) {
-  while (*flushed < requested) {
-    // Flush least recently used
-    ZPage* const page = from->remove_last();
-    if (page == NULL) {
-      break;
-    }
+bool ZPageCache::flush_list_inner(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to) {
+  ZPage* const page = from->last();
+  if (page == NULL || !cl->do_page(page)) {
+    // Don't flush page
+    return false;
+  }
 
-    *flushed += page->size();
-    to->insert_last(page);
-  }
+  // Flush page
+  _available -= page->size();
+  from->remove(page);
+  to->insert_last(page);
+  return true;
 }
 
-void ZPageCache::flush_per_numa_lists(ZPerNUMA<ZList<ZPage> >* from, size_t requested, ZList<ZPage>* to, size_t* flushed) {
+void ZPageCache::flush_list(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to) {
+  while (flush_list_inner(cl, from, to));
+}
+
+void ZPageCache::flush_per_numa_lists(ZPageCacheFlushClosure* cl, ZPerNUMA<ZList<ZPage> >* from, ZList<ZPage>* to) {
   const uint32_t numa_count = ZNUMA::count();
-  uint32_t numa_empty = 0;
+  uint32_t numa_done = 0;
   uint32_t numa_next = 0;
 
   // Flush lists round-robin
-  while (*flushed < requested) {
-    ZPage* const page = from->get(numa_next).remove_last();
-
+  while (numa_done < numa_count) {
+    ZList<ZPage>* numa_list = from->addr(numa_next);
     if (++numa_next == numa_count) {
       numa_next = 0;
     }
 
-    if (page == NULL) {
-      // List is empty
-      if (++numa_empty == numa_count) {
-        // All lists are empty
-        break;
-      }
-
-      // Try next list
-      continue;
+    if (flush_list_inner(cl, numa_list, to)) {
+      // Not done
+      numa_done = 0;
+    } else {
+      // Done
+      numa_done++;
     }
-
-    // Flush page
-    numa_empty = 0;
-    *flushed += page->size();
-    to->insert_last(page);
   }
 }
 
-void ZPageCache::flush(ZList<ZPage>* to, size_t requested) {
-  size_t flushed = 0;
-
+void ZPageCache::flush(ZPageCacheFlushClosure* cl, ZList<ZPage>* to) {
   // Prefer flushing large, then medium and last small pages
-  flush_list(&_large, requested, to, &flushed);
-  flush_list(&_medium, requested, to, &flushed);
-  flush_per_numa_lists(&_small, requested, to, &flushed);
-
-  ZStatInc(ZCounterPageCacheFlush, flushed);
-
-  log_info(gc, heap)("Page Cache Flushed: "
-                     SIZE_FORMAT "M requested, "
-                     SIZE_FORMAT "M(" SIZE_FORMAT "M->" SIZE_FORMAT "M) flushed",
-                     requested / M, flushed / M , _available / M, (_available - flushed) / M);
-
-  _available -= flushed;
+  flush_list(cl, &_large, to);
+  flush_list(cl, &_medium, to);
+  flush_per_numa_lists(cl, &_small, to);
 }
--- a/src/hotspot/share/gc/z/zPageCache.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zPageCache.hpp	Fri May 03 14:59:32 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
@@ -29,10 +29,14 @@
 #include "gc/z/zValue.hpp"
 #include "memory/allocation.hpp"
 
+class ZPageCacheFlushClosure : public StackObj {
+public:
+  virtual bool do_page(const ZPage* page) = 0;
+};
+
 class ZPageCache {
 private:
   size_t                  _available;
-
   ZPerNUMA<ZList<ZPage> > _small;
   ZList<ZPage>            _medium;
   ZList<ZPage>            _large;
@@ -41,8 +45,9 @@
   ZPage* alloc_medium_page();
   ZPage* alloc_large_page(size_t size);
 
-  void flush_list(ZList<ZPage>* from, size_t requested, ZList<ZPage>* to, size_t* flushed);
-  void flush_per_numa_lists(ZPerNUMA<ZList<ZPage> >* from, size_t requested, ZList<ZPage>* to, size_t* flushed);
+  bool flush_list_inner(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to);
+  void flush_list(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to);
+  void flush_per_numa_lists(ZPageCacheFlushClosure* cl, ZPerNUMA<ZList<ZPage> >* from, ZList<ZPage>* to);
 
 public:
   ZPageCache();
@@ -52,7 +57,7 @@
   ZPage* alloc_page(uint8_t type, size_t size);
   void free_page(ZPage* page);
 
-  void flush(ZList<ZPage>* to, size_t requested);
+  void flush(ZPageCacheFlushClosure* cl, ZList<ZPage>* to);
 };
 
 #endif // SHARE_GC_Z_ZPAGECACHE_HPP
--- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp	Fri May 03 14:59:32 2019 -0400
@@ -450,7 +450,7 @@
 
   {
     // Heap_lock protects external pending list
-    MonitorLockerEx ml(Heap_lock);
+    MonitorLocker ml(Heap_lock);
 
     // Prepend internal pending list to external pending list
     *_pending_list_tail = Universe::swap_reference_pending_list(_pending_list.get());
--- a/src/hotspot/share/gc/z/zRuntimeWorkers.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zRuntimeWorkers.cpp	Fri May 03 14:59:32 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
@@ -48,13 +48,13 @@
     ZThread::set_runtime_worker();
 
     // Wait for all threads to start
-    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
     if (++_started == _nworkers) {
       // All threads started
       ml.notify_all();
     } else {
       while (_started != _nworkers) {
-        ml.wait(Monitor::_no_safepoint_check_flag);
+        ml.wait();
       }
     }
   }
--- a/src/hotspot/share/gc/z/zStat.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zStat.cpp	Fri May 03 14:59:32 2019 -0400
@@ -230,7 +230,7 @@
 // Stat unit printers
 //
 void ZStatUnitTime(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
-  log.print(" %10s: %-40s  "
+  log.print(" %10s: %-41s "
             "%9.3f / %-9.3f "
             "%9.3f / %-9.3f "
             "%9.3f / %-9.3f "
@@ -248,7 +248,7 @@
 }
 
 void ZStatUnitBytes(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
-  log.print(" %10s: %-40s  "
+  log.print(" %10s: %-41s "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
@@ -266,7 +266,7 @@
 }
 
 void ZStatUnitThreads(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
-  log.print(" %10s: %-40s  "
+  log.print(" %10s: %-41s "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
@@ -284,7 +284,7 @@
 }
 
 void ZStatUnitBytesPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
-  log.print(" %10s: %-40s  "
+  log.print(" %10s: %-41s "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
@@ -302,7 +302,7 @@
 }
 
 void ZStatUnitOpsPerSecond(LogTargetHandle log, const ZStatSampler& sampler, const ZStatSamplerHistory& history) {
-  log.print(" %10s: %-40s  "
+  log.print(" %10s: %-41s "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
             UINT64_FORMAT_W(9) " / " UINT64_FORMAT_W(-9) " "
--- a/src/hotspot/share/gc/z/zUnload.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zUnload.cpp	Fri May 03 14:59:32 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
@@ -130,7 +130,7 @@
   bool unloading_occurred;
 
   {
-    MutexLockerEx ml(ClassLoaderDataGraph_lock);
+    MutexLocker ml(ClassLoaderDataGraph_lock);
     unloading_occurred = SystemDictionary::do_unloading(ZStatPhase::timer());
   }
 
--- a/src/hotspot/share/gc/z/zVirtualMemory.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zVirtualMemory.cpp	Fri May 03 14:59:32 2019 -0400
@@ -24,11 +24,16 @@
 #include "precompiled.hpp"
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zVirtualMemory.inline.hpp"
+#include "logging/log.hpp"
 #include "services/memTracker.hpp"
 
 ZVirtualMemoryManager::ZVirtualMemoryManager() :
     _manager(),
     _initialized(false) {
+
+  log_info(gc, init)("Address Space: " PTR_FORMAT " - " PTR_FORMAT " (" SIZE_FORMAT "T)",
+                     ZAddressSpaceStart, ZAddressSpaceEnd, ZAddressSpaceSize / K / G);
+
   // Reserve address space
   if (!reserve(ZAddressSpaceStart, ZAddressSpaceSize)) {
     return;
--- a/src/hotspot/share/gc/z/zWorkers.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/gc/z/zWorkers.cpp	Fri May 03 14:59:32 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
@@ -86,13 +86,13 @@
     ZThread::set_worker();
 
     // Wait for all threads to start
-    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    MonitorLocker ml(&_monitor, Monitor::_no_safepoint_check_flag);
     if (++_started == _nworkers) {
       // All threads started
       ml.notify_all();
     } else {
       while (_started != _nworkers) {
-        ml.wait(Monitor::_no_safepoint_check_flag);
+        ml.wait();
       }
     }
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,287 @@
+/*
+ * 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 "jvm.h"
+#include "classfile/javaClasses.inline.hpp"
+#include "classfile/resolutionErrors.hpp"
+#include "interpreter/bootstrapInfo.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/cpCache.inline.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "oops/typeArrayOop.inline.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/vmThread.hpp"
+
+//------------------------------------------------------------------------------------------------------------------------
+// Implementation of BootstrapInfo
+
+BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index)
+  : _pool(pool),
+    _bss_index(bss_index),
+    _indy_index(indy_index),
+    // derived and eagerly cached:
+    _argc(      pool->bootstrap_argument_count_at(bss_index) ),
+    _name(      pool->uncached_name_ref_at(bss_index) ),
+    _signature( pool->uncached_signature_ref_at(bss_index) )
+{
+  _is_resolved = false;
+  assert(pool->tag_at(bss_index).has_bootstrap(), "");
+  assert(indy_index == -1 || pool->invokedynamic_bootstrap_ref_index_at(indy_index) == bss_index, "invalid bootstrap specifier index");
+}
+
+// If there is evidence this call site was already linked, set the
+// existing linkage data into result, or throw previous exception.
+// Return true if either action is taken, else false.
+bool BootstrapInfo::resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS) {
+  assert(_indy_index != -1, "");
+  ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry();
+  if (!cpce->is_f1_null()) {
+    methodHandle method(     THREAD, cpce->f1_as_method());
+    Handle       appendix(   THREAD, cpce->appendix_if_resolved(_pool));
+    result.set_handle(method, appendix, THREAD);
+    Exceptions::wrap_dynamic_exception(CHECK_false);
+    return true;
+  } else if (cpce->indy_resolution_failed()) {
+    int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index);
+    ConstantPool::throw_resolution_error(_pool, encoded_index, CHECK_false);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Resolve the bootstrap specifier in 3 steps:
+// - unpack the BSM by resolving the MH constant
+// - obtain the NameAndType description for the condy/indy
+// - prepare the BSM's static arguments
+Handle BootstrapInfo::resolve_bsm(TRAPS) {
+  if (_bsm.not_null())  return _bsm;
+  // The tag at the bootstrap method index must be a valid method handle or a method handle in error.
+  // If it is a MethodHandleInError, a resolution error will be thrown which will be wrapped if necessary
+  // with a BootstrapMethodError.
+  assert(_pool->tag_at(bsm_index()).is_method_handle() ||
+         _pool->tag_at(bsm_index()).is_method_handle_in_error(), "MH not present, classfile structural constraint");
+  oop bsm_oop = _pool->resolve_possibly_cached_constant_at(bsm_index(), THREAD);
+  Exceptions::wrap_dynamic_exception(CHECK_NH);
+  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm_oop), "classfile must supply a valid BSM");
+  _bsm = Handle(THREAD, bsm_oop);
+
+  // Obtain NameAndType information
+  resolve_bss_name_and_type(THREAD);
+  Exceptions::wrap_dynamic_exception(CHECK_NH);
+
+  // Prepare static arguments
+  resolve_args(THREAD);
+  Exceptions::wrap_dynamic_exception(CHECK_NH);
+
+  return _bsm;
+}
+
+// Resolve metadata from the JVM_Dynamic_info or JVM_InvokeDynamic_info's name and type information.
+void BootstrapInfo::resolve_bss_name_and_type(TRAPS) {
+  assert(_bsm.not_null(), "resolve_bsm first");
+  Symbol* name = this->name();
+  Symbol* type = this->signature();
+  _name_arg = java_lang_String::create_from_symbol(name, CHECK);
+  if (type->char_at(0) == '(') {
+    _type_arg = SystemDictionary::find_method_handle_type(type, caller(), CHECK);
+  } else {
+    _type_arg = SystemDictionary::find_java_mirror_for_type(type, caller(), SignatureStream::NCDFError, CHECK);
+  }
+}
+
+// Resolve the bootstrap method's static arguments and store the result in _arg_values.
+void BootstrapInfo::resolve_args(TRAPS) {
+  assert(_bsm.not_null(), "resolve_bsm first");
+
+  // if there are no static arguments, return leaving _arg_values as null
+  if (_argc == 0 && UseBootstrapCallInfo < 2) return;
+
+  bool use_BSCI;
+  switch (UseBootstrapCallInfo) {
+  default: use_BSCI = true;  break;  // stress mode
+  case 0:  use_BSCI = false; break;  // stress mode
+  case 1:                            // normal mode
+    // If we were to support an alternative mode of BSM invocation,
+    // we'd convert to pull mode here if the BSM could be a candidate
+    // for that alternative mode.  We can't easily test for things
+    // like varargs here, but we can get away with approximate testing,
+    // since the JDK runtime will make up the difference either way.
+    // For now, exercise the pull-mode path if the BSM is of arity 2,
+    // or if there is a potential condy loop (see below).
+    oop mt_oop = java_lang_invoke_MethodHandle::type(_bsm());
+    use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2);
+    break;
+  }
+
+  // Here's a reason to use BSCI even if it wasn't requested:
+  // If a condy uses a condy argument, we want to avoid infinite
+  // recursion (condy loops) in the C code.  It's OK in Java,
+  // because Java has stack overflow checking, so we punt
+  // potentially cyclic cases from C to Java.
+  if (!use_BSCI && _pool->tag_at(_bss_index).is_dynamic_constant()) {
+    bool found_unresolved_condy = false;
+    for (int i = 0; i < _argc; i++) {
+      int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
+      if (_pool->tag_at(arg_index).is_dynamic_constant()) {
+        // potential recursion point condy -> condy
+        bool found_it = false;
+        _pool->find_cached_constant_at(arg_index, found_it, CHECK);
+        if (!found_it) { found_unresolved_condy = true; break; }
+      }
+    }
+    if (found_unresolved_condy)
+      use_BSCI = true;
+  }
+
+  const int SMALL_ARITY = 5;
+  if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
+    // If there are only a few arguments, and none of them need linking,
+    // push them, instead of asking the JDK runtime to turn around and
+    // pull them, saving a JVM/JDK transition in some simple cases.
+    bool all_resolved = true;
+    for (int i = 0; i < _argc; i++) {
+      bool found_it = false;
+      int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
+      _pool->find_cached_constant_at(arg_index, found_it, CHECK);
+      if (!found_it) { all_resolved = false; break; }
+    }
+    if (all_resolved)
+      use_BSCI = false;
+  }
+
+  if (!use_BSCI) {
+    // return {arg...}; resolution of arguments is done immediately, before JDK code is called
+    objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), _argc, CHECK);
+    objArrayHandle args(THREAD, args_oop);
+    _pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK);
+    oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)NULL);
+    // try to discard the singleton array
+    if (arg_oop != NULL && !arg_oop->is_array()) {
+      // JVM treats arrays and nulls specially in this position,
+      // but other things are just single arguments
+      _arg_values = Handle(THREAD, arg_oop);
+    } else {
+      _arg_values = args;
+    }
+  } else {
+    // return {arg_count, pool_index}; JDK code must pull the arguments as needed
+    typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK);
+    ints_oop->int_at_put(0, _argc);
+    ints_oop->int_at_put(1, _bss_index);
+    _arg_values = Handle(THREAD, ints_oop);
+  }
+}
+
+// there must be a LinkageError pending; try to save it and then throw
+bool BootstrapInfo::save_and_throw_indy_exc(TRAPS) {
+  assert(HAS_PENDING_EXCEPTION, "");
+  assert(_indy_index != -1, "");
+  ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry();
+  int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index);
+  bool recorded_res_status = cpce->save_and_throw_indy_exc(_pool, _bss_index,
+                                                           encoded_index,
+                                                           pool()->tag_at(_bss_index),
+                                                           CHECK_false);
+  return recorded_res_status;
+}
+
+void BootstrapInfo::resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS) {
+  assert(is_resolved(), "");
+  result.set_handle(resolved_method(), resolved_appendix(), CHECK);
+}
+
+void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
+  ResourceMark rm;
+  char what[20];
+  st = st ? st : tty;
+
+  if (_indy_index != -1)
+    sprintf(what, "indy#%d", decode_indy_index());
+  else
+    sprintf(what, "condy");
+  bool have_msg = (msg != NULL && strlen(msg) > 0);
+  st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s",
+                (have_msg ? msg : ""), (have_msg ? " " : ""),
+                caller()->name()->as_C_string(),
+                what,  // "indy#42" or "condy"
+                _bss_index,
+                _name->as_C_string(),
+                _signature->as_C_string(),
+                (_type_arg.is_null() ? "" : "(resolved)"),
+                bsms_attr_index(),
+                bsm_index(), (_bsm.is_null() ? "" : "(resolved)"),
+                _argc, (_arg_values.is_null() ? "" : "(resolved)"));
+  if (_argc > 0) {
+    char argbuf[80];
+    argbuf[0] = 0;
+    for (int i = 0; i < _argc; i++) {
+      int pos = (int) strlen(argbuf);
+      if (pos + 20 > (int)sizeof(argbuf)) {
+        sprintf(argbuf + pos, "...");
+        break;
+      }
+      if (i > 0)  argbuf[pos++] = ',';
+      sprintf(argbuf+pos, "%d", arg_index(i));
+    }
+    st->print_cr("  argument indexes: {%s}", argbuf);
+  }
+  if (_bsm.not_null()) {
+    st->print("  resolved BSM: "); _bsm->print();
+  }
+
+  // How the array of resolved arguments is printed depends highly
+  // on how BootstrapInfo::resolve_args structures the array based on
+  // the use_BSCI setting.
+  if (_arg_values.not_null()) {
+    // Find the static arguments within the first element of _arg_values.
+    objArrayOop static_args = (objArrayOop)_arg_values();
+    if (!static_args->is_array()) {
+      assert(_argc == 1, "Invalid BSM _arg_values for non-array");
+      st->print("  resolved arg[0]: "); static_args->print();
+    } else if (static_args->is_objArray()) {
+      int lines = 0;
+      for (int i = 0; i < _argc; i++) {
+        oop x = static_args->obj_at(i);
+        if (x != NULL) {
+          if (++lines > 6) {
+            st->print_cr("  resolved arg[%d]: ...", i);
+            break;
+          }
+          st->print("  resolved arg[%d]: ", i); x->print();
+        }
+      }
+    } else if (static_args->is_typeArray()) {
+      typeArrayOop tmp_array = (typeArrayOop) static_args;
+      assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array");
+      st->print_cr("  resolved arg[0]: %d", tmp_array->int_at(0));
+      st->print_cr("  resolved arg[1]: %d", tmp_array->int_at(1));
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/interpreter/bootstrapInfo.hpp	Fri May 03 14:59:32 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.
+ *
+ */
+
+#ifndef SHARE_INTERPRETER_BOOTSTRAPINFO_HPP
+#define SHARE_INTERPRETER_BOOTSTRAPINFO_HPP
+
+#include "oops/constantPool.hpp"
+#include "oops/instanceKlass.hpp"
+
+// BootstrapInfo provides condensed information from the constant pool
+// necessary to invoke a bootstrap method.
+class BootstrapInfo : public StackObj {
+  constantPoolHandle _pool;     // constant pool containing the bootstrap specifier
+  const int   _bss_index;       // index of bootstrap specifier in CP (condy or indy)
+  const int   _indy_index;      // internal index of indy call site, or -1 if a condy call
+  const int   _argc;            // number of static arguments
+  Symbol*     _name;            // extracted from JVM_CONSTANT_NameAndType
+  Symbol*     _signature;
+
+  // pre-bootstrap resolution state:
+  Handle      _bsm;             // resolved bootstrap method
+  Handle      _name_arg;        // resolved String
+  Handle      _type_arg;        // resolved Class or MethodType
+  Handle      _arg_values;      // array of static arguments; null implies either
+                                // uresolved or zero static arguments are specified
+
+  // post-bootstrap resolution state:
+  bool        _is_resolved;       // set true when any of the next fields are set
+  Handle      _resolved_value;    // bind this as condy constant
+  methodHandle _resolved_method;  // bind this as indy behavior
+  Handle      _resolved_appendix; // extra opaque static argument for _resolved_method
+
+ public:
+  BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index = -1);
+
+  // accessors
+  const constantPoolHandle& pool() const{ return _pool; }
+  int bss_index() const                 { return _bss_index; }
+  int indy_index() const                { return _indy_index; }
+  int argc() const                      { return _argc; }
+  bool is_method_call() const           { return (_indy_index != -1); }
+  Symbol* name() const                  { return _name; }
+  Symbol* signature() const             { return _signature; }
+
+  // accessors to lazy state
+  Handle bsm() const                    { return _bsm; }
+  Handle name_arg() const               { return _name_arg; }
+  Handle type_arg() const               { return _type_arg; }
+  Handle arg_values() const             { return _arg_values; }
+  bool is_resolved() const              { return _is_resolved; }
+  Handle resolved_value() const         { assert(!is_method_call(), ""); return _resolved_value; }
+  methodHandle resolved_method() const  { assert(is_method_call(), "");  return _resolved_method; }
+  Handle resolved_appendix() const      { assert(is_method_call(), "");  return _resolved_appendix; }
+
+  // derived accessors
+  InstanceKlass* caller() const         { return _pool->pool_holder(); }
+  oop caller_mirror() const             { return caller()->java_mirror(); }
+  int decode_indy_index() const         { return ConstantPool::decode_invokedynamic_index(_indy_index); }
+  int bsms_attr_index() const           { return _pool->bootstrap_methods_attribute_index(_bss_index); }
+  int bsm_index() const                 { return _pool->bootstrap_method_ref_index_at(_bss_index); }
+  //int argc() is eagerly cached in _argc
+  int arg_index(int i) const            { return _pool->bootstrap_argument_index_at(_bss_index, i); }
+
+  // CP cache entry for call site (indy only)
+  ConstantPoolCacheEntry* invokedynamic_cp_cache_entry() const {
+    assert(is_method_call(), "");
+    return _pool->invokedynamic_cp_cache_entry_at(_indy_index);
+  }
+
+  // If there is evidence this call site was already linked, set the
+  // existing linkage data into result, or throw previous exception.
+  // Return true if either action is taken, else false.
+  bool resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS);
+  bool save_and_throw_indy_exc(TRAPS);
+  void resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS);
+
+  // pre-bootstrap resolution actions:
+  Handle resolve_bsm(TRAPS); // lazily compute _bsm and return it
+  void resolve_bss_name_and_type(TRAPS); // lazily compute _name/_type
+  void resolve_args(TRAPS);  // compute arguments
+
+  // setters for post-bootstrap results:
+  void set_resolved_value(Handle value) {
+    assert(!is_resolved() && !is_method_call(), "");
+    _is_resolved = true;
+    _resolved_value = value;
+  }
+  void set_resolved_method(methodHandle method, Handle appendix) {
+    assert(!is_resolved() && is_method_call(), "");
+    _is_resolved = true;
+    _resolved_method = method;
+    _resolved_appendix = appendix;
+  }
+
+  void print() { print_msg_on(tty); }
+  void print_msg_on(outputStream* st, const char* msg = NULL);
+};
+
+#endif // SHARE_INTERPRETER_BOOTSTRAPINFO_HPP
--- a/src/hotspot/share/interpreter/linkResolver.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/interpreter/linkResolver.cpp	Fri May 03 14:59:32 2019 -0400
@@ -32,6 +32,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
+#include "interpreter/bootstrapInfo.hpp"
 #include "interpreter/bytecode.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -1694,99 +1695,80 @@
   result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK);
 }
 
-void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
-  Symbol* method_name       = pool->name_ref_at(index);
-  Symbol* method_signature  = pool->signature_ref_at(index);
-  Klass* current_klass = pool->pool_holder();
-
-  // Resolve the bootstrap specifier (BSM + optional arguments).
-  Handle bootstrap_specifier;
-  // Check if CallSite has been bound already:
-  ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
+void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int indy_index, TRAPS) {
+  ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(indy_index);
   int pool_index = cpce->constant_pool_index();
 
-  if (cpce->is_f1_null()) {
-    if (cpce->indy_resolution_failed()) {
-      ConstantPool::throw_resolution_error(pool,
-                                           ResolutionErrorTable::encode_cpcache_index(index),
-                                           CHECK);
-    }
+  // Resolve the bootstrap specifier (BSM + optional arguments).
+  BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index);
+
+  // Check if CallSite has been bound already or failed already, and short circuit:
+  {
+    bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK);
+    if (is_done) return;
+  }
 
-    // The initial step in Call Site Specifier Resolution is to resolve the symbolic
-    // reference to a method handle which will be the bootstrap method for a dynamic
-    // call site.  If resolution for the java.lang.invoke.MethodHandle for the bootstrap
-    // method fails, then a MethodHandleInError is stored at the corresponding bootstrap
-    // method's CP index for the CONSTANT_MethodHandle_info.  So, there is no need to
-    // set the indy_rf flag since any subsequent invokedynamic instruction which shares
-    // this bootstrap method will encounter the resolution of MethodHandleInError.
-    oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD);
-    Exceptions::wrap_dynamic_exception(CHECK);
-    assert(bsm_info != NULL, "");
-    // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
-    bootstrap_specifier = Handle(THREAD, bsm_info);
-  }
-  if (!cpce->is_f1_null()) {
-    methodHandle method(     THREAD, cpce->f1_as_method());
-    Handle       appendix(   THREAD, cpce->appendix_if_resolved(pool));
-    result.set_handle(method, appendix, THREAD);
-    Exceptions::wrap_dynamic_exception(CHECK);
-    return;
-  }
+  // The initial step in Call Site Specifier Resolution is to resolve the symbolic
+  // reference to a method handle which will be the bootstrap method for a dynamic
+  // call site.  If resolution for the java.lang.invoke.MethodHandle for the bootstrap
+  // method fails, then a MethodHandleInError is stored at the corresponding bootstrap
+  // method's CP index for the CONSTANT_MethodHandle_info.  So, there is no need to
+  // set the indy_rf flag since any subsequent invokedynamic instruction which shares
+  // this bootstrap method will encounter the resolution of MethodHandleInError.
+
+  resolve_dynamic_call(result, bootstrap_specifier, CHECK);
 
   if (TraceMethodHandles) {
-    ResourceMark rm(THREAD);
-    tty->print_cr("resolve_invokedynamic #%d %s %s in %s",
-                  ConstantPool::decode_invokedynamic_index(index),
-                  method_name->as_C_string(), method_signature->as_C_string(),
-                  current_klass->name()->as_C_string());
-    tty->print("  BSM info: "); bootstrap_specifier->print();
+    bootstrap_specifier.print_msg_on(tty, "resolve_invokedynamic");
   }
 
-  resolve_dynamic_call(result, pool_index, bootstrap_specifier, method_name,
-                       method_signature, current_klass, THREAD);
-  if (HAS_PENDING_EXCEPTION && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
-    int encoded_index = ResolutionErrorTable::encode_cpcache_index(index);
-    bool recorded_res_status = cpce->save_and_throw_indy_exc(pool, pool_index,
-                                                             encoded_index,
-                                                             pool()->tag_at(pool_index),
-                                                             CHECK);
-    if (!recorded_res_status) {
-      // Another thread got here just before we did.  So, either use the method
-      // that it resolved or throw the LinkageError exception that it threw.
-      if (!cpce->is_f1_null()) {
-        methodHandle method(     THREAD, cpce->f1_as_method());
-        Handle       appendix(   THREAD, cpce->appendix_if_resolved(pool));
-        result.set_handle(method, appendix, THREAD);
-        Exceptions::wrap_dynamic_exception(CHECK);
-      } else {
-        assert(cpce->indy_resolution_failed(), "Resolution failure flag not set");
-        ConstantPool::throw_resolution_error(pool, encoded_index, CHECK);
-      }
-      return;
-    }
-    assert(cpce->indy_resolution_failed(), "Resolution failure flag wasn't set");
-  }
+  // The returned linkage result is provisional up to the moment
+  // the interpreter or runtime performs a serialized check of
+  // the relevant CPCE::f1 field.  This is done by the caller
+  // of this method, via CPCE::set_dynamic_call, which uses
+  // an ObjectLocker to do the final serialization of updates
+  // to CPCE state, including f1.
 }
 
 void LinkResolver::resolve_dynamic_call(CallInfo& result,
-                                        int pool_index,
-                                        Handle bootstrap_specifier,
-                                        Symbol* method_name, Symbol* method_signature,
-                                        Klass* current_klass,
+                                        BootstrapInfo& bootstrap_specifier,
                                         TRAPS) {
-  // JSR 292:  this must resolve to an implicitly generated method MH.linkToCallSite(*...)
+  // JSR 292:  this must resolve to an implicitly generated method
+  // such as MH.linkToCallSite(*...) or some other call-site shape.
   // The appendix argument is likely to be a freshly-created CallSite.
-  Handle       resolved_appendix;
-  methodHandle resolved_method =
-    SystemDictionary::find_dynamic_call_site_invoker(current_klass,
-                                                     pool_index,
-                                                     bootstrap_specifier,
-                                                     method_name, method_signature,
-                                                     &resolved_appendix,
-                                                     THREAD);
-  Exceptions::wrap_dynamic_exception(CHECK);
-  result.set_handle(resolved_method, resolved_appendix, THREAD);
-  Exceptions::wrap_dynamic_exception(CHECK);
+  // It may also be a MethodHandle from an unwrapped ConstantCallSite,
+  // or any other reference.  The resolved_method as well as the appendix
+  // are both recorded together via CallInfo::set_handle.
+  SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD);
+  Exceptions::wrap_dynamic_exception(THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
+      // Let any random low-level IE or SOE or OOME just bleed through.
+      // Basically we pretend that the bootstrap method was never called,
+      // if it fails this way:  We neither record a successful linkage,
+      // nor do we memorize a LE for posterity.
+      return;
+    }
+    // JVMS 5.4.3 says: If an attempt by the Java Virtual Machine to resolve
+    // a symbolic reference fails because an error is thrown that is an
+    // instance of LinkageError (or a subclass), then subsequent attempts to
+    // resolve the reference always fail with the same error that was thrown
+    // as a result of the initial resolution attempt.
+     bool recorded_res_status = bootstrap_specifier.save_and_throw_indy_exc(CHECK);
+     if (!recorded_res_status) {
+       // Another thread got here just before we did.  So, either use the method
+       // that it resolved or throw the LinkageError exception that it threw.
+       bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK);
+       if (is_done) return;
+     }
+     assert(bootstrap_specifier.invokedynamic_cp_cache_entry()->indy_resolution_failed(),
+            "Resolution failure flag wasn't set");
+  }
+
+  bootstrap_specifier.resolve_newly_linked_invokedynamic(result, CHECK);
+  // Exceptions::wrap_dynamic_exception not used because
+  // set_handle doesn't throw linkage errors
 }
 
 // Selected method is abstract.
--- a/src/hotspot/share/interpreter/linkResolver.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/interpreter/linkResolver.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,6 +25,7 @@
 #ifndef SHARE_INTERPRETER_LINKRESOLVER_HPP
 #define SHARE_INTERPRETER_LINKRESOLVER_HPP
 
+#include "interpreter/bootstrapInfo.hpp"
 #include "oops/method.hpp"
 
 // All the necessary definitions for run-time link resolution.
@@ -77,6 +78,7 @@
                   CallKind kind,
                   int index, TRAPS);
 
+  friend class BootstrapInfo;
   friend class LinkResolver;
 
  public:
@@ -311,9 +313,8 @@
                                      bool check_null_and_abstract, TRAPS);
   static void resolve_handle_call   (CallInfo& result,
                                      const LinkInfo& link_info, TRAPS);
-  static void resolve_dynamic_call  (CallInfo& result, int pool_index, Handle bootstrap_specifier,
-                                     Symbol* method_name, Symbol* method_signature,
-                                     Klass* current_klass, TRAPS);
+  static void resolve_dynamic_call  (CallInfo& result,
+                                     BootstrapInfo& bootstrap_specifier, TRAPS);
 
   // same as above for compile-time resolution; but returns null handle instead of throwing
   // an exception on error also, does not initialize klass (i.e., no side effects)
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Fri May 03 14:59:32 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
@@ -40,6 +40,9 @@
 #include "runtime/thread.hpp"
 #include "services/management.hpp"
 #include "utilities/align.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 RootSetClosure::RootSetClosure(EdgeQueue* edge_queue) :
   _edge_queue(edge_queue) {
@@ -104,4 +107,5 @@
   Management::oops_do(closure);
   StringTable::oops_do(closure);
   AOTLoader::oops_do(closure);
+  JVMCI_ONLY(JVMCI::oops_do(closure);)
 }
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Fri May 03 14:59:32 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
@@ -136,7 +136,7 @@
  public:
   StackTraceWrite(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer) :
     _stack_trace_repo(stack_trace_repo), _writer(writer), _count(0) {
-    JfrStacktrace_lock->lock();
+    JfrStacktrace_lock->lock_without_safepoint_check();
   }
   ~StackTraceWrite() {
     assert(JfrStacktrace_lock->owned_by_self(), "invariant");
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Fri May 03 14:59:32 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
@@ -40,6 +40,9 @@
 #include "runtime/vframe_hp.hpp"
 #include "services/management.hpp"
 #include "utilities/growableArray.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 class ReferenceLocateClosure : public OopClosure {
  protected:
@@ -102,6 +105,7 @@
   bool do_management_roots();
   bool do_string_table_roots();
   bool do_aot_loader_roots();
+  JVMCI_ONLY(bool do_jvmci_roots();)
 
   bool do_roots();
 
@@ -188,6 +192,15 @@
   return rcl.complete();
 }
 
+#if INCLUDE_JVMCI
+bool ReferenceToRootClosure::do_jvmci_roots() {
+  assert(!complete(), "invariant");
+  ReferenceLocateClosure rcl(_callback, OldObjectRoot::_jvmci, OldObjectRoot::_type_undetermined, NULL);
+  JVMCI::oops_do(&rcl);
+  return rcl.complete();
+}
+#endif
+
 bool ReferenceToRootClosure::do_roots() {
   assert(!complete(), "invariant");
   assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
@@ -238,6 +251,13 @@
     return true;
   }
 
+#if INCLUDE_JVMCI
+  if (do_jvmci_roots()) {
+   _complete = true;
+    return true;
+  }
+#endif
+
   return false;
 }
 
--- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp	Fri May 03 14:59:32 2019 -0400
@@ -43,6 +43,7 @@
     _code_cache,
     _string_table,
     _aot,
+    JVMCI_ONLY(_jvmci COMMA)
     _number_of_systems
   };
 
@@ -81,6 +82,10 @@
         return "String Table";
       case _aot:
         return "AOT";
+#if INCLUDE_JVMCI
+      case _jvmci:
+        return "JVMCI";
+#endif
       default:
         ShouldNotReachHere();
     }
--- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp	Fri May 03 14:59:32 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
@@ -409,7 +409,7 @@
   JfrTicks time_stamp = JfrTicks::now();
   {
     // Collect allocation statistics while holding threads lock
-    MutexLockerEx ml(Threads_lock);
+    MutexLocker ml(Threads_lock);
     for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
       allocated.append(jt->cooked_allocated_bytes());
       thread_ids.append(JFR_THREAD_ID(jt));
--- a/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp	Fri May 03 14:59:32 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
@@ -27,6 +27,7 @@
 #include "code/nmethod.hpp"
 #include "code/pcDesc.hpp"
 #include "jfr/periodic/sampling/jfrCallTrace.hpp"
+#include "jfr/utilities/jfrTypes.hpp"
 #include "oops/method.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/frame.inline.hpp"
@@ -37,7 +38,7 @@
   assert(top_frame.cb() != NULL, "invariant");
   RegisterMap map(_thread, false);
   frame candidate = top_frame;
-  for (int i = 0; i < MaxJavaStackTraceDepth * 2; ++i) {
+  for (u4 i = 0; i < MAX_STACK_DEPTH * 2; ++i) {
     if (candidate.is_entry_frame()) {
       JavaCallWrapper *jcw = candidate.entry_frame_call_wrapper_if_safe(_thread);
       if (jcw == NULL || jcw->is_first_frame()) {
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri May 03 14:59:32 2019 -0400
@@ -347,7 +347,7 @@
   jt->clear_trace_flag();
   JfrThreadLocal* const tl = jt->jfr_thread_local();
   if (tl->is_trace_block()) {
-    MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
     JfrThreadSampler::transition_block()->notify_all();
   }
 }
@@ -395,9 +395,9 @@
   JfrThreadLocal* const tl = thread->jfr_thread_local();
   tl->set_trace_block();
   {
-    MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(transition_block(), Mutex::_no_safepoint_check_flag);
     while (thread->is_trace_suspend()) {
-      transition_block()->wait(true);
+      ml.wait();
     }
     tl->clear_trace_block();
   }
@@ -516,7 +516,7 @@
     elapsedTimer sample_time;
     sample_time.start();
     {
-      MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
+      MutexLocker tlock(Threads_lock, Mutex::_no_safepoint_check_flag);
       ThreadsListHandle tlh;
       // Resolve a sample session relative start position index into the thread list array.
       // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp	Fri May 03 14:59:32 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
@@ -149,8 +149,8 @@
 
 void JfrTypeManager::write_type_set() {
   // can safepoint here because of Module_lock
-  MutexLockerEx cld_lock(SafepointSynchronize::is_at_safepoint() ? NULL : ClassLoaderDataGraph_lock);
-  MutexLockerEx lock(SafepointSynchronize::is_at_safepoint() ? NULL : Module_lock);
+  MutexLocker cld_lock(SafepointSynchronize::is_at_safepoint() ? NULL : ClassLoaderDataGraph_lock);
+  MutexLocker lock(SafepointSynchronize::is_at_safepoint() ? NULL : Module_lock);
 
   JfrCheckpointWriter writer(true, true, Thread::current());
   TypeSet set;
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Fri May 03 14:59:32 2019 -0400
@@ -325,7 +325,7 @@
 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);
+  MutexLocker 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));
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Fri May 03 14:59:32 2019 -0400
@@ -135,7 +135,7 @@
   ResourceMark rm(jt);
   const char* const canonical_chunk_path = JfrJavaSupport::c_str(path, jt);
   {
-    MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
     if (NULL == canonical_chunk_path && !_chunkwriter->is_valid()) {
       // new output is NULL and current output is NULL
       return;
--- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp	Fri May 03 14:59:32 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
@@ -27,6 +27,7 @@
 #include "jfr/recorder/service/jfrMemorySizer.hpp"
 #include "jfr/recorder/service/jfrOptionSet.hpp"
 #include "jfr/utilities/jfrAllocation.hpp"
+#include "jfr/utilities/jfrTypes.hpp"
 #include "logging/log.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -106,10 +107,6 @@
   return _stack_depth;
 }
 
-static const u4 STACK_DEPTH_DEFAULT = 64;
-static const u4 MIN_STACK_DEPTH = 1;
-static const u4 MAX_STACK_DEPTH = 2048;
-
 void JfrOptionSet::set_stackdepth(u4 depth) {
   if (depth < MIN_STACK_DEPTH) {
     _stack_depth = MIN_STACK_DEPTH;
--- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp	Fri May 03 14:59:32 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
@@ -110,14 +110,14 @@
 void JfrPostBox::synchronous_post(int msg) {
   assert(is_synchronous(msg), "invariant");
   assert(!JfrMsg_lock->owned_by_self(), "should not hold JfrMsg_lock here!");
-  MutexLockerEx msg_lock(JfrMsg_lock);
+  MonitorLocker msg_lock(JfrMsg_lock);
   deposit(msg);
   // serial_id is used to check when what we send in has been processed.
   // _msg_read_serial is read under JfrMsg_lock protection.
   const uintptr_t serial_id = OrderAccess::load_acquire(&_msg_read_serial) + 1;
-  JfrMsg_lock->notify_all();
+  msg_lock.notify_all();
   while (!is_message_processed(serial_id)) {
-    JfrMsg_lock->wait();
+    msg_lock.wait();
   }
 }
 
@@ -168,6 +168,6 @@
 
 // safeguard to ensure no threads are left waiting
 void JfrPostBox::notify_collection_stop() {
-  MutexLockerEx msg_lock(JfrMsg_lock);
+  MutexLocker msg_lock(JfrMsg_lock);
   JfrMsg_lock->notify_all();
 }
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Fri May 03 14:59:32 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
@@ -110,8 +110,8 @@
       }
       if (_thread->is_Java_thread()) {
         // in order to allow the system to move to a safepoint
-        MutexLockerEx msg_lock(JfrMsg_lock);
-        JfrMsg_lock->wait(false, rotation_retry_sleep_millis);
+        MutexLocker msg_lock(JfrMsg_lock);
+        JfrMsg_lock->wait(rotation_retry_sleep_millis);
       }
       else {
         os::naked_short_sleep(rotation_retry_sleep_millis);
@@ -341,7 +341,7 @@
   assert(!_chunkwriter.is_valid(), "invariant");
   assert(!JfrStream_lock->owned_by_self(), "invariant");
   JfrChunkRotation::on_rotation();
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   if (!_repository.open_chunk(vm_error)) {
     assert(!_chunkwriter.is_valid(), "invariant");
     _storage.control().set_to_disk(false);
@@ -363,7 +363,7 @@
 
 void JfrRecorderService::serialize_storage_from_in_memory_recording() {
   assert(!JfrStream_lock->owned_by_self(), "not holding stream lock!");
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   _storage.write();
 }
 
@@ -422,7 +422,7 @@
 //              release stream lock
 //
 void JfrRecorderService::pre_safepoint_write() {
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   assert(_chunkwriter.is_valid(), "invariant");
   _checkpoint_manager.write_types();
   _checkpoint_manager.write_epoch_transition_mspace();
@@ -457,7 +457,7 @@
 //
 void JfrRecorderService::safepoint_write() {
   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   write_object_sample_stacktrace(_stack_trace_repository);
   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
   write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
@@ -493,7 +493,7 @@
   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
   _checkpoint_manager.write_type_set();
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   // serialize any outstanding checkpoint memory
   _checkpoint_manager.write();
   // serialize the metadata descriptor event and close out the chunk
@@ -526,7 +526,7 @@
 void JfrRecorderService::process_full_buffers() {
   if (_chunkwriter.is_valid()) {
     assert(!JfrStream_lock->owned_by_self(), "invariant");
-    MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
     _storage.write_full();
   }
 }
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThreadLoop.cpp	Fri May 03 14:59:32 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
@@ -50,12 +50,12 @@
     bool done = false;
     int msgs = 0;
     JfrRecorderService service;
-    MutexLockerEx msg_lock(JfrMsg_lock);
+    MutexLocker msg_lock(JfrMsg_lock);
 
     // JFR MESSAGE LOOP PROCESSING - BEGIN
     while (!done) {
       if (post_box.is_empty()) {
-        JfrMsg_lock->wait(false);
+        JfrMsg_lock->wait();
       }
       msgs = post_box.collect();
       JfrMsg_lock->unlock();
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Fri May 03 14:59:32 2019 -0400
@@ -69,8 +69,8 @@
   }
 
   // handle general case
-  int loop_count = 0;
-  int loop_max = MaxJavaStackTraceDepth * 2;
+  u4 loop_count = 0;
+  u4 loop_max = MAX_STACK_DEPTH * 2;
   do {
     loop_count++;
     // By the time we get here we should never see unsafe but better safe then segv'd
@@ -123,7 +123,7 @@
 }
 
 size_t JfrStackTraceRepository::clear() {
-  MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
   if (_entries == 0) {
     return 0;
   }
@@ -142,7 +142,7 @@
 }
 
 traceid JfrStackTraceRepository::add_trace(const JfrStackTrace& stacktrace) {
-  MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
   const size_t index = stacktrace._hash % TABLE_SIZE;
   const StackTrace* table_entry = _table[index];
 
@@ -238,7 +238,7 @@
 }
 
 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
-  MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
   assert(_entries > 0, "invariant");
   int count = 0;
   for (u4 i = 0; i < TABLE_SIZE; ++i) {
--- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp	Fri May 03 14:59:32 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
@@ -321,7 +321,7 @@
   assert(buffer != NULL, "invariant");
   assert(buffer->retired(), "invariant");
   assert(age_mspace != NULL, "invariant");
-  MutexLockerEx lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
   JfrAgeNode* age_node = get_free_age_node(age_mspace, thread);
   if (age_node == NULL) {
     age_node = new_age_node(buffer, age_mspace, thread);
@@ -623,7 +623,7 @@
     assert(tail->next() == NULL, "invariant");
     assert(head != NULL, "invariant");
     assert(head->prev() == NULL, "invariant");
-    MutexLockerEx buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
     age_mspace->insert_free_tail(head, tail, count);
   }
 }
@@ -674,7 +674,7 @@
   JfrAgeNode* head;
   {
     // fetch age list
-    MutexLockerEx buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
     count = age_mspace->full_count();
     head = age_mspace->clear_full();
     control.reset_full();
--- a/src/hotspot/share/jfr/utilities/jfrTypes.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jfr/utilities/jfrTypes.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,6 +33,9 @@
 typedef int fio_fd;
 const int invalid_fd = -1;
 const jlong invalid_offset = -1;
+const u4 STACK_DEPTH_DEFAULT = 64;
+const u4 MIN_STACK_DEPTH = 1;
+const u4 MAX_STACK_DEPTH = 2048;
 
 enum EventStartTime {
   UNTIMED,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jniAccessMark.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,49 @@
+/*
+ * 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_JVMCI_JNIACCESSMARK_INLINE_HPP
+#define SHARE_JVMCI_JNIACCESSMARK_INLINE_HPP
+
+#include "jvmci/jvmciEnv.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+
+// Wrapper for a JNI call into the JVMCI shared library.
+// This performs a ThreadToNativeFromVM transition so that the VM
+// will not be blocked if the call takes a long time (e.g., due
+// to a GC in the shared library).
+class JNIAccessMark : public StackObj {
+ private:
+  ThreadToNativeFromVM ttnfv;
+  HandleMark hm;
+  JNIEnv* _env;
+ public:
+  inline JNIAccessMark(JVMCIEnv* jvmci_env) :
+    ttnfv(JavaThread::current()), hm(JavaThread::current()) {
+    _env = jvmci_env->_env;
+  }
+  JNIEnv* env() const { return _env; }
+  JNIEnv* operator () () const { return _env; }
+};
+
+#endif // SHARE_JVMCI_JNIACCESSMARK_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmci.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,151 @@
+/*
+ * 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 "classfile/systemDictionary.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/oopStorage.inline.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmci_globals.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/metadataHandleBlock.hpp"
+
+OopStorage* JVMCI::_object_handles = NULL;
+MetadataHandleBlock* JVMCI::_metadata_handles = NULL;
+JVMCIRuntime* JVMCI::_compiler_runtime = NULL;
+JVMCIRuntime* JVMCI::_java_runtime = NULL;
+
+bool JVMCI::can_initialize_JVMCI() {
+  // Initializing JVMCI requires the module system to be initialized past phase 3.
+  // The JVMCI API itself isn't available until phase 2 and ServiceLoader (which
+  // JVMCI initialization requires) isn't usable until after phase 3. Testing
+  // whether the system loader is initialized satisfies all these invariants.
+  if (SystemDictionary::java_system_loader() == NULL) {
+    return false;
+  }
+  assert(Universe::is_module_initialized(), "must be");
+  return true;
+}
+
+void JVMCI::initialize_compiler(TRAPS) {
+  if (JVMCILibDumpJNIConfig) {
+    JNIJVMCI::initialize_ids(NULL);
+    ShouldNotReachHere();
+  }
+
+  JVMCI::compiler_runtime()->call_getCompiler(CHECK);
+}
+
+void JVMCI::initialize_globals() {
+  _object_handles = new OopStorage("JVMCI Global Oop Handles",
+                                   JVMCIGlobalAlloc_lock,
+                                   JVMCIGlobalActive_lock);
+  _metadata_handles = MetadataHandleBlock::allocate_block();
+  if (UseJVMCINativeLibrary) {
+    // There are two runtimes.
+    _compiler_runtime = new JVMCIRuntime();
+    _java_runtime = new JVMCIRuntime();
+  } else {
+    // There is only a single runtime
+    _java_runtime = _compiler_runtime = new JVMCIRuntime();
+  }
+}
+
+OopStorage* JVMCI::object_handles() {
+  assert(_object_handles != NULL, "Uninitialized");
+  return _object_handles;
+}
+
+jobject JVMCI::make_global(const Handle& obj) {
+  assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
+  assert(oopDesc::is_oop(obj()), "not an oop");
+  oop* ptr = object_handles()->allocate();
+  jobject res = NULL;
+  if (ptr != NULL) {
+    assert(*ptr == NULL, "invariant");
+    NativeAccess<>::oop_store(ptr, obj());
+    res = reinterpret_cast<jobject>(ptr);
+  } else {
+    vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
+                          "Cannot create JVMCI oop handle");
+  }
+  return res;
+}
+
+bool JVMCI::is_global_handle(jobject handle) {
+  const oop* ptr = reinterpret_cast<oop*>(handle);
+  return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
+}
+
+jmetadata JVMCI::allocate_handle(const methodHandle& handle) {
+  assert(_metadata_handles != NULL, "uninitialized");
+  MutexLocker ml(JVMCI_lock);
+  return _metadata_handles->allocate_handle(handle);
+}
+
+jmetadata JVMCI::allocate_handle(const constantPoolHandle& handle) {
+  assert(_metadata_handles != NULL, "uninitialized");
+  MutexLocker ml(JVMCI_lock);
+  return _metadata_handles->allocate_handle(handle);
+}
+
+void JVMCI::release_handle(jmetadata handle) {
+  MutexLocker ml(JVMCI_lock);
+  _metadata_handles->chain_free_list(handle);
+}
+
+void JVMCI::oops_do(OopClosure* f) {
+  if (_object_handles != NULL) {
+    _object_handles->oops_do(f);
+  }
+}
+
+void JVMCI::metadata_do(void f(Metadata*)) {
+  if (_metadata_handles != NULL) {
+    _metadata_handles->metadata_do(f);
+  }
+}
+
+void JVMCI::do_unloading(bool unloading_occurred) {
+  if (_metadata_handles != NULL && unloading_occurred) {
+    _metadata_handles->do_unloading();
+  }
+}
+
+bool JVMCI::is_compiler_initialized() {
+  return compiler_runtime()->is_HotSpotJVMCIRuntime_initialized();
+}
+
+void JVMCI::shutdown() {
+  if (compiler_runtime() != NULL) {
+    compiler_runtime()->shutdown();
+  }
+}
+
+bool JVMCI::shutdown_called() {
+  if (compiler_runtime() != NULL) {
+    return compiler_runtime()->shutdown_called();
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmci.hpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,106 @@
+/*
+ * 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_JVMCI_JVMCI_HPP
+#define SHARE_JVMCI_JVMCI_HPP
+
+#include "compiler/compilerDefinitions.hpp"
+#include "utilities/exceptions.hpp"
+
+class BoolObjectClosure;
+class constantPoolHandle;
+class JavaThread;
+class JVMCIEnv;
+class JVMCIRuntime;
+class Metadata;
+class MetadataHandleBlock;
+class OopClosure;
+class OopStorage;
+
+struct _jmetadata;
+typedef struct _jmetadata *jmetadata;
+
+class JVMCI : public AllStatic {
+  friend class JVMCIRuntime;
+  friend class JVMCIEnv;
+
+ private:
+  // Handles to objects in the HotSpot heap.
+  static OopStorage* _object_handles;
+
+  static OopStorage* object_handles();
+
+  // Handles to Metadata objects.
+  static MetadataHandleBlock* _metadata_handles;
+
+  // Access to the HotSpotJVMCIRuntime used by the CompileBroker.
+  static JVMCIRuntime* _compiler_runtime;
+
+  // Access to the HotSpotJVMCIRuntime used by Java code running on the
+  // HotSpot heap. It will be the same as _compiler_runtime if
+  // UseJVMCINativeLibrary is false
+  static JVMCIRuntime* _java_runtime;
+
+ public:
+  enum CodeInstallResult {
+     ok,
+     dependencies_failed,
+     dependencies_invalid,
+     cache_full,
+     code_too_large
+  };
+
+  static void do_unloading(bool unloading_occurred);
+
+  static void metadata_do(void f(Metadata*));
+
+  static void oops_do(OopClosure* f);
+
+  static void shutdown();
+
+  static bool shutdown_called();
+
+  static bool is_compiler_initialized();
+
+  /**
+   * Determines if the VM is sufficiently booted to initialize JVMCI.
+   */
+  static bool can_initialize_JVMCI();
+
+  static void initialize_globals();
+
+  static void initialize_compiler(TRAPS);
+
+  static jobject make_global(const Handle& obj);
+  static bool is_global_handle(jobject handle);
+
+  static jmetadata allocate_handle(const methodHandle& handle);
+  static jmetadata allocate_handle(const constantPoolHandle& handle);
+
+  static void release_handle(jmetadata handle);
+
+  static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; }
+  static JVMCIRuntime* java_runtime()     { return _java_runtime; }
+};
+
+#endif // SHARE_JVMCI_JVMCI_HPP
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Fri May 03 14:59:32 2019 -0400
@@ -22,28 +22,13 @@
  */
 
 #include "precompiled.hpp"
-#include "asm/register.hpp"
-#include "classfile/vmSymbols.hpp"
 #include "code/compiledIC.hpp"
-#include "code/vmreg.inline.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/disassembler.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "jvmci/jvmciCompiler.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "memory/allocation.inline.hpp"
-#include "oops/arrayOop.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
-#include "oops/typeArrayOop.inline.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/javaCalls.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/safepointMechanism.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/align.hpp"
 
@@ -51,30 +36,25 @@
 // Allocate them with new so they are never destroyed (otherwise, a
 // forced exit could destroy these objects while they are still in
 // use).
-ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
-ConstantIntValue*      CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
-ConstantIntValue*      CodeInstaller::_int_0_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue((jint)0);
-ConstantIntValue*      CodeInstaller::_int_1_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
-ConstantIntValue*      CodeInstaller::_int_2_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
-LocationValue*         CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
+ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtJVMCI) ConstantOopWriteValue(NULL);
+ConstantIntValue*      CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(-1);
+ConstantIntValue*      CodeInstaller::_int_0_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue((jint)0);
+ConstantIntValue*      CodeInstaller::_int_1_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(1);
+ConstantIntValue*      CodeInstaller::_int_2_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(2);
+LocationValue*         CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtJVMCI) LocationValue(Location());
 
-Method* getMethodFromHotSpotMethod(oop hotspot_method) {
-  assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass()), "sanity");
-  return CompilerToVM::asMethod(hotspot_method);
-}
-
-VMReg getVMRegFromLocation(Handle location, int total_frame_size, TRAPS) {
+VMReg CodeInstaller::getVMRegFromLocation(JVMCIObject location, int total_frame_size, JVMCI_TRAPS) {
   if (location.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
 
-  Handle reg(THREAD, code_Location::reg(location));
-  jint offset = code_Location::offset(location);
+  JVMCIObject reg = jvmci_env()->get_code_Location_reg(location);
+  jint offset = jvmci_env()->get_code_Location_offset(location);
 
-  if (reg.not_null()) {
+  if (reg.is_non_null()) {
     // register
-    jint number = code_Register::number(reg);
-    VMReg vmReg = CodeInstaller::get_hotspot_reg(number, CHECK_NULL);
+    jint number = jvmci_env()->get_code_Register_number(reg);
+    VMReg vmReg = CodeInstaller::get_hotspot_reg(number, JVMCI_CHECK_NULL);
     if (offset % 4 == 0) {
       return vmReg->next(offset / 4);
     } else {
@@ -102,71 +82,45 @@
   }
 }
 
-objArrayOop CodeInstaller::sites() {
-  return (objArrayOop) JNIHandles::resolve(_sites_handle);
-}
-
-arrayOop CodeInstaller::code() {
-  return (arrayOop) JNIHandles::resolve(_code_handle);
-}
-
-arrayOop CodeInstaller::data_section() {
-  return (arrayOop) JNIHandles::resolve(_data_section_handle);
-}
-
-objArrayOop CodeInstaller::data_section_patches() {
-  return (objArrayOop) JNIHandles::resolve(_data_section_patches_handle);
-}
-
-#ifndef PRODUCT
-objArrayOop CodeInstaller::comments() {
-  return (objArrayOop) JNIHandles::resolve(_comments_handle);
-}
-#endif
-
-oop CodeInstaller::word_kind() {
-  return JNIHandles::resolve(_word_kind_handle);
-}
-
 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo
-OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) {
-  Handle reference_map(THREAD, DebugInfo::referenceMap(debug_info));
+OopMap* CodeInstaller::create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS) {
+  JVMCIObject reference_map = jvmci_env()->get_DebugInfo_referenceMap(debug_info);
   if (reference_map.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (!reference_map->is_a(HotSpotReferenceMap::klass())) {
-    JVMCI_ERROR_NULL("unknown reference map: %s", reference_map->klass()->signature_name());
+  if (!jvmci_env()->isa_HotSpotReferenceMap(reference_map)) {
+    JVMCI_ERROR_NULL("unknown reference map: %s", jvmci_env()->klass_name(reference_map));
   }
-  if (!_has_wide_vector && SharedRuntime::is_wide_vector(HotSpotReferenceMap::maxRegisterSize(reference_map))) {
+  if (!_has_wide_vector && SharedRuntime::is_wide_vector(jvmci_env()->get_HotSpotReferenceMap_maxRegisterSize(reference_map))) {
     if (SharedRuntime::polling_page_vectors_safepoint_handler_blob() == NULL) {
       JVMCI_ERROR_NULL("JVMCI is producing code using vectors larger than the runtime supports");
     }
     _has_wide_vector = true;
   }
   OopMap* map = new OopMap(_total_frame_size, _parameter_count);
-  objArrayHandle objects(THREAD, HotSpotReferenceMap::objects(reference_map));
-  objArrayHandle derivedBase(THREAD, HotSpotReferenceMap::derivedBase(reference_map));
-  typeArrayHandle sizeInBytes(THREAD, HotSpotReferenceMap::sizeInBytes(reference_map));
+  JVMCIObjectArray objects = jvmci_env()->get_HotSpotReferenceMap_objects(reference_map);
+  JVMCIObjectArray derivedBase = jvmci_env()->get_HotSpotReferenceMap_derivedBase(reference_map);
+  JVMCIPrimitiveArray sizeInBytes = jvmci_env()->get_HotSpotReferenceMap_sizeInBytes(reference_map);
   if (objects.is_null() || derivedBase.is_null() || sizeInBytes.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (objects->length() != derivedBase->length() || objects->length() != sizeInBytes->length()) {
-    JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", objects->length(), derivedBase->length(), sizeInBytes->length());
+  if (JVMCIENV->get_length(objects) != JVMCIENV->get_length(derivedBase) || JVMCIENV->get_length(objects) != JVMCIENV->get_length(sizeInBytes)) {
+    JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", JVMCIENV->get_length(objects), JVMCIENV->get_length(derivedBase), JVMCIENV->get_length(sizeInBytes));
   }
-  for (int i = 0; i < objects->length(); i++) {
-    Handle location(THREAD, objects->obj_at(i));
-    Handle baseLocation(THREAD, derivedBase->obj_at(i));
-    int bytes = sizeInBytes->int_at(i);
+  for (int i = 0; i < JVMCIENV->get_length(objects); i++) {
+    JVMCIObject location = JVMCIENV->get_object_at(objects, i);
+    JVMCIObject baseLocation = JVMCIENV->get_object_at(derivedBase, i);
+    jint bytes = JVMCIENV->get_int_at(sizeInBytes, i);
 
-    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, CHECK_NULL);
-    if (baseLocation.not_null()) {
+    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, JVMCI_CHECK_NULL);
+    if (baseLocation.is_non_null()) {
       // derived oop
 #ifdef _LP64
       if (bytes == 8) {
 #else
       if (bytes == 4) {
 #endif
-        VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size, CHECK_NULL);
+        VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size, JVMCI_CHECK_NULL);
         map->set_derived_oop(vmReg, baseReg);
       } else {
         JVMCI_ERROR_NULL("invalid derived oop size in ReferenceMap: %d", bytes);
@@ -187,16 +141,16 @@
     }
   }
 
-  Handle callee_save_info(THREAD, (oop) DebugInfo::calleeSaveInfo(debug_info));
-  if (callee_save_info.not_null()) {
-    objArrayHandle registers(THREAD, RegisterSaveLayout::registers(callee_save_info));
-    typeArrayHandle slots(THREAD, RegisterSaveLayout::slots(callee_save_info));
-    for (jint i = 0; i < slots->length(); i++) {
-      Handle jvmci_reg (THREAD, registers->obj_at(i));
-      jint jvmci_reg_number = code_Register::number(jvmci_reg);
-      VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, CHECK_NULL);
+  JVMCIObject callee_save_info = jvmci_env()->get_DebugInfo_calleeSaveInfo(debug_info);
+  if (callee_save_info.is_non_null()) {
+    JVMCIObjectArray registers = jvmci_env()->get_RegisterSaveLayout_registers(callee_save_info);
+    JVMCIPrimitiveArray slots = jvmci_env()->get_RegisterSaveLayout_slots(callee_save_info);
+    for (jint i = 0; i < JVMCIENV->get_length(slots); i++) {
+      JVMCIObject jvmci_reg = JVMCIENV->get_object_at(registers, i);
+      jint jvmci_reg_number = jvmci_env()->get_code_Register_number(jvmci_reg);
+      VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, JVMCI_CHECK_NULL);
       // HotSpot stack slots are 4 bytes
-      jint jvmci_slot = slots->int_at(i);
+      jint jvmci_slot = JVMCIENV->get_int_at(slots, i);
       jint hotspot_slot = jvmci_slot * VMRegImpl::slots_per_word;
       VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot);
       map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg);
@@ -211,7 +165,8 @@
 }
 
 #if INCLUDE_AOT
-AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+AOTOopRecorder::AOTOopRecorder(CodeInstaller* code_inst, Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+  _code_inst = code_inst;
   _meta_refs = new GrowableArray<jobject>();
 }
 
@@ -225,6 +180,7 @@
 
 int AOTOopRecorder::find_index(Metadata* h) {
   JavaThread* THREAD = JavaThread::current();
+  JVMCIEnv* JVMCIENV = _code_inst->jvmci_env();
   int oldCount = metadata_count();
   int index =  this->OopRecorder::find_index(h);
   int newCount = metadata_count();
@@ -237,18 +193,18 @@
   vmassert(index + 1 == newCount, "must be last");
 
   JVMCIKlassHandle klass(THREAD);
-  oop result = NULL;
+  JVMCIObject result;
   guarantee(h != NULL,
             "If DebugInformationRecorder::describe_scope passes NULL oldCount == newCount must hold.");
   if (h->is_klass()) {
     klass = (Klass*) h;
-    result = CompilerToVM::get_jvmci_type(klass, CATCH);
+    result = JVMCIENV->get_jvmci_type(klass, JVMCI_CATCH);
   } else if (h->is_method()) {
     Method* method = (Method*) h;
     methodHandle mh(method);
-    result = CompilerToVM::get_jvmci_method(method, CATCH);
+    result = JVMCIENV->get_jvmci_method(method, JVMCI_CATCH);
   }
-  jobject ref = JNIHandles::make_local(THREAD, result);
+  jobject ref = JVMCIENV->get_jobject(result);
   record_meta_ref(ref, index);
 
   return index;
@@ -272,43 +228,43 @@
 }
 #endif // INCLUDE_AOT
 
-void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
+void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS) {
   /*
    * This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
    * class is in general not equal to the pointer of the subclass. When patching metaspace pointers,
    * the compiler expects a direct pointer to the subclass (Klass* or Method*), not a pointer to the
    * base class (Metadata* or MetaspaceObj*).
    */
-  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
-  if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
-    Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
-    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass));
+  JVMCIObject obj = jvmci_env()->get_HotSpotMetaspaceConstantImpl_metaspaceObject(constant);
+  if (jvmci_env()->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    Klass* klass = JVMCIENV->asKlass(obj);
+    assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass));
     int index = _oop_recorder->find_index(klass);
     section->relocate(dest, metadata_Relocation::spec(index));
     TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
     return klass;
-  } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj);
-    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method));
+  } else if (jvmci_env()->isa_HotSpotResolvedJavaMethodImpl(obj)) {
+    Method* method = jvmci_env()->asMethod(obj);
+    assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method));
     int index = _oop_recorder->find_index(method);
     section->relocate(dest, metadata_Relocation::spec(index));
     TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string());
     return method;
   } else {
-    JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", obj->klass()->signature_name());
+    JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", jvmci_env()->klass_name(obj));
   }
 }
 
 #ifdef _LP64
-narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
-  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
-  assert(HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected uncompressed pointer");
+narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS) {
+  JVMCIObject obj = jvmci_env()->get_HotSpotMetaspaceConstantImpl_metaspaceObject(constant);
+  assert(jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected uncompressed pointer");
 
-  if (!obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
-    JVMCI_ERROR_0("unexpected compressed pointer of type %s", obj->klass()->signature_name());
+  if (!jvmci_env()->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    JVMCI_ERROR_0("unexpected compressed pointer of type %s", jvmci_env()->klass_name(obj));
   }
 
-  Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+  Klass* klass = JVMCIENV->asKlass(obj);
   int index = _oop_recorder->find_index(klass);
   section->relocate(dest, metadata_Relocation::spec(index));
   TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
@@ -316,34 +272,34 @@
 }
 #endif
 
-Location::Type CodeInstaller::get_oop_type(Thread* thread, Handle value) {
-  Handle valueKind(thread, Value::valueKind(value));
-  Handle platformKind(thread, ValueKind::platformKind(valueKind));
+Location::Type CodeInstaller::get_oop_type(JVMCIObject value) {
+  JVMCIObject valueKind = jvmci_env()->get_Value_valueKind(value);
+  JVMCIObject platformKind = jvmci_env()->get_ValueKind_platformKind(valueKind);
 
-  if (platformKind == word_kind()) {
+  if (jvmci_env()->equals(platformKind, word_kind())) {
     return Location::oop;
   } else {
     return Location::narrowoop;
   }
 }
 
-ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS) {
+ScopeValue* CodeInstaller::get_scope_value(JVMCIObject value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, JVMCI_TRAPS) {
   second = NULL;
   if (value.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
-  } else if (value == Value::ILLEGAL()) {
+    JVMCI_THROW_NULL(NullPointerException);
+  } else if (JVMCIENV->equals(value, jvmci_env()->get_Value_ILLEGAL())) {
     if (type != T_ILLEGAL) {
       JVMCI_ERROR_NULL("unexpected illegal value, expected %s", basictype_to_str(type));
     }
     return _illegal_value;
-  } else if (value->is_a(RegisterValue::klass())) {
-    Handle reg(THREAD, RegisterValue::reg(value));
-    jint number = code_Register::number(reg);
-    VMReg hotspotRegister = get_hotspot_reg(number, CHECK_NULL);
+  } else if (jvmci_env()->isa_RegisterValue(value)) {
+    JVMCIObject reg = jvmci_env()->get_RegisterValue_reg(value);
+    jint number = jvmci_env()->get_code_Register_number(reg);
+    VMReg hotspotRegister = get_hotspot_reg(number, JVMCI_CHECK_NULL);
     if (is_general_purpose_reg(hotspotRegister)) {
       Location::Type locationType;
       if (type == T_OBJECT) {
-        locationType = get_oop_type(THREAD, value);
+        locationType = get_oop_type(value);
       } else if (type == T_LONG) {
         locationType = Location::lng;
       } else if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
@@ -372,15 +328,15 @@
       }
       return value;
     }
-  } else if (value->is_a(StackSlot::klass())) {
-    jint offset = StackSlot::offset(value);
-    if (StackSlot::addFrameSize(value)) {
+  } else if (jvmci_env()->isa_StackSlot(value)) {
+    jint offset = jvmci_env()->get_StackSlot_offset(value);
+    if (jvmci_env()->get_StackSlot_addFrameSize(value)) {
       offset += _total_frame_size;
     }
 
     Location::Type locationType;
     if (type == T_OBJECT) {
-      locationType = get_oop_type(THREAD, value);
+      locationType = get_oop_type(value);
     } else if (type == T_LONG) {
       locationType = Location::lng;
     } else if (type == T_DOUBLE) {
@@ -395,19 +351,18 @@
       second = value;
     }
     return value;
-  } else if (value->is_a(JavaConstant::klass())) {
-    if (value->is_a(PrimitiveConstant::klass())) {
-      if (value->is_a(RawConstant::klass())) {
-        jlong prim = PrimitiveConstant::primitive(value);
+  } else if (jvmci_env()->isa_JavaConstant(value)) {
+    if (jvmci_env()->isa_PrimitiveConstant(value)) {
+      if (jvmci_env()->isa_RawConstant(value)) {
+        jlong prim = jvmci_env()->get_PrimitiveConstant_primitive(value);
         return new ConstantLongValue(prim);
       } else {
-        Handle primitive_constant_kind(THREAD, PrimitiveConstant::kind(value));
-        BasicType constantType = JVMCIRuntime::kindToBasicType(primitive_constant_kind, CHECK_NULL);
+        BasicType constantType = jvmci_env()->kindToBasicType(jvmci_env()->get_PrimitiveConstant_kind(value), JVMCI_CHECK_NULL);
         if (type != constantType) {
           JVMCI_ERROR_NULL("primitive constant type doesn't match, expected %s but got %s", basictype_to_str(type), basictype_to_str(constantType));
         }
         if (type == T_INT || type == T_FLOAT) {
-          jint prim = (jint)PrimitiveConstant::primitive(value);
+          jint prim = (jint)jvmci_env()->get_PrimitiveConstant_primitive(value);
           switch (prim) {
             case -1: return _int_m1_scope_value;
             case  0: return _int_0_scope_value;
@@ -416,33 +371,33 @@
             default: return new ConstantIntValue(prim);
           }
         } else if (type == T_LONG || type == T_DOUBLE) {
-          jlong prim = PrimitiveConstant::primitive(value);
+          jlong prim = jvmci_env()->get_PrimitiveConstant_primitive(value);
           second = _int_1_scope_value;
           return new ConstantLongValue(prim);
         } else {
           JVMCI_ERROR_NULL("unexpected primitive constant type %s", basictype_to_str(type));
         }
       }
-    } else if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) {
+    } else if (jvmci_env()->isa_NullConstant(value) || jvmci_env()->isa_HotSpotCompressedNullConstant(value)) {
       if (type == T_OBJECT) {
         return _oop_null_scope_value;
       } else {
         JVMCI_ERROR_NULL("unexpected null constant, expected %s", basictype_to_str(type));
       }
-    } else if (value->is_a(HotSpotObjectConstantImpl::klass())) {
+    } else if (jvmci_env()->isa_HotSpotObjectConstantImpl(value)) {
       if (type == T_OBJECT) {
-        oop obj = HotSpotObjectConstantImpl::object(value);
+        Handle obj = jvmci_env()->asConstant(value, JVMCI_CHECK_NULL);
         if (obj == NULL) {
           JVMCI_ERROR_NULL("null value must be in NullConstant");
         }
-        return new ConstantOopWriteValue(JNIHandles::make_local(obj));
+        return new ConstantOopWriteValue(JNIHandles::make_local(obj()));
       } else {
         JVMCI_ERROR_NULL("unexpected object constant, expected %s", basictype_to_str(type));
       }
     }
-  } else if (value->is_a(VirtualObject::klass())) {
+  } else if (jvmci_env()->isa_VirtualObject(value)) {
     if (type == T_OBJECT) {
-      int id = VirtualObject::id(value);
+      int id = jvmci_env()->get_VirtualObject_id(value);
       if (0 <= id && id < objects->length()) {
         ScopeValue* object = objects->at(id);
         if (object != NULL) {
@@ -455,26 +410,22 @@
     }
   }
 
-  JVMCI_ERROR_NULL("unexpected value in scope: %s", value->klass()->signature_name())
+  JVMCI_ERROR_NULL("unexpected value in scope: %s", jvmci_env()->klass_name(value))
 }
 
-void CodeInstaller::record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
-  // Might want a HandleMark here.
-  Handle type(THREAD, VirtualObject::type(value));
-  int id = VirtualObject::id(value);
-  oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
-  Klass* klass = java_lang_Class::as_Klass(javaMirror);
+void CodeInstaller::record_object_value(ObjectValue* sv, JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS) {
+  JVMCIObject type = jvmci_env()->get_VirtualObject_type(value);
+  int id = jvmci_env()->get_VirtualObject_id(value);
+  Klass* klass = JVMCIENV->asKlass(type);
   bool isLongArray = klass == Universe::longArrayKlassObj();
 
-  objArrayHandle values(THREAD, VirtualObject::values(value));
-  objArrayHandle slotKinds(THREAD, VirtualObject::slotKinds(value));
-  for (jint i = 0; i < values->length(); i++) {
-    HandleMark hm(THREAD);
+  JVMCIObjectArray values = jvmci_env()->get_VirtualObject_values(value);
+  JVMCIObjectArray slotKinds = jvmci_env()->get_VirtualObject_slotKinds(value);
+  for (jint i = 0; i < JVMCIENV->get_length(values); i++) {
     ScopeValue* cur_second = NULL;
-    Handle object(THREAD, values->obj_at(i));
-    Handle slot_kind (THREAD, slotKinds->obj_at(i));
-    BasicType type = JVMCIRuntime::kindToBasicType(slot_kind, CHECK);
-    ScopeValue* value = get_scope_value(object, type, objects, cur_second, CHECK);
+    JVMCIObject object = JVMCIENV->get_object_at(values, i);
+    BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+    ScopeValue* value = get_scope_value(object, type, objects, cur_second, JVMCI_CHECK);
 
     if (isLongArray && cur_second == NULL) {
       // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
@@ -490,68 +441,65 @@
   }
 }
 
-MonitorValue* CodeInstaller::get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
+MonitorValue* CodeInstaller::get_monitor_value(JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS) {
   if (value.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (!value->is_a(StackLockValue::klass())) {
-    JVMCI_ERROR_NULL("Monitors must be of type StackLockValue, got %s", value->klass()->signature_name());
+  if (!jvmci_env()->isa_StackLockValue(value)) {
+    JVMCI_ERROR_NULL("Monitors must be of type StackLockValue, got %s", jvmci_env()->klass_name(value));
   }
 
   ScopeValue* second = NULL;
-  Handle stack_lock_owner(THREAD, StackLockValue::owner(value));
-  ScopeValue* owner_value = get_scope_value(stack_lock_owner, T_OBJECT, objects, second, CHECK_NULL);
+  ScopeValue* owner_value = get_scope_value(jvmci_env()->get_StackLockValue_owner(value), T_OBJECT, objects, second, JVMCI_CHECK_NULL);
   assert(second == NULL, "monitor cannot occupy two stack slots");
 
-  Handle stack_lock_slot(THREAD, StackLockValue::slot(value));
-  ScopeValue* lock_data_value = get_scope_value(stack_lock_slot, T_LONG, objects, second, CHECK_NULL);
+  ScopeValue* lock_data_value = get_scope_value(jvmci_env()->get_StackLockValue_slot(value), T_LONG, objects, second, JVMCI_CHECK_NULL);
   assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
   assert(lock_data_value->is_location(), "invalid monitor location");
   Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
 
   bool eliminated = false;
-  if (StackLockValue::eliminated(value)) {
+  if (jvmci_env()->get_StackLockValue_eliminated(value)) {
     eliminated = true;
   }
 
   return new MonitorValue(owner_value, lock_data_loc, eliminated);
 }
 
-void CodeInstaller::initialize_dependencies(oop compiled_code, OopRecorder* recorder, TRAPS) {
+void CodeInstaller::initialize_dependencies(JVMCIObject compiled_code, OopRecorder* oop_recorder, JVMCI_TRAPS) {
   JavaThread* thread = JavaThread::current();
-  assert(THREAD == thread, "");
   CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL;
-  _oop_recorder = recorder;
+  _oop_recorder = oop_recorder;
   _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL);
-  objArrayHandle assumptions(THREAD, HotSpotCompiledCode::assumptions(compiled_code));
-  if (!assumptions.is_null()) {
-    int length = assumptions->length();
+  JVMCIObjectArray assumptions = jvmci_env()->get_HotSpotCompiledCode_assumptions(compiled_code);
+  if (assumptions.is_non_null()) {
+    int length = JVMCIENV->get_length(assumptions);
     for (int i = 0; i < length; ++i) {
-      Handle assumption(THREAD, assumptions->obj_at(i));
-      if (!assumption.is_null()) {
-        if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
-          assumption_NoFinalizableSubclass(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
-          assumption_ConcreteSubtype(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_LeafType::klass()) {
-          assumption_LeafType(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
-          assumption_ConcreteMethod(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
-          assumption_CallSiteTargetValue(THREAD, assumption);
+      JVMCIObject assumption = JVMCIENV->get_object_at(assumptions, i);
+      if (assumption.is_non_null()) {
+        if (jvmci_env()->isa_Assumptions_NoFinalizableSubclass(assumption)) {
+          assumption_NoFinalizableSubclass(assumption);
+        } else if (jvmci_env()->isa_Assumptions_ConcreteSubtype(assumption)) {
+          assumption_ConcreteSubtype(assumption);
+        } else if (jvmci_env()->isa_Assumptions_LeafType(assumption)) {
+          assumption_LeafType(assumption);
+        } else if (jvmci_env()->isa_Assumptions_ConcreteMethod(assumption)) {
+          assumption_ConcreteMethod(assumption);
+        } else if (jvmci_env()->isa_Assumptions_CallSiteTargetValue(assumption)) {
+          assumption_CallSiteTargetValue(assumption, JVMCI_CHECK);
         } else {
-          JVMCI_ERROR("unexpected Assumption subclass %s", assumption->klass()->signature_name());
+          JVMCI_ERROR("unexpected Assumption subclass %s", jvmci_env()->klass_name(assumption));
         }
       }
     }
   }
   if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
-    objArrayHandle methods(THREAD, HotSpotCompiledCode::methods(compiled_code));
-    if (!methods.is_null()) {
-      int length = methods->length();
+    JVMCIObjectArray methods = jvmci_env()->get_HotSpotCompiledCode_methods(compiled_code);
+    if (methods.is_non_null()) {
+      int length = JVMCIENV->get_length(methods);
       for (int i = 0; i < length; ++i) {
-        Handle method_handle(THREAD, methods->obj_at(i));
-        methodHandle method = getMethodFromHotSpotMethod(method_handle());
+        JVMCIObject method_handle = JVMCIENV->get_object_at(methods, i);
+        methodHandle method = jvmci_env()->asMethod(method_handle);
         _dependencies->assert_evol_method(method());
       }
     }
@@ -581,16 +529,16 @@
   assert(_buffer == NULL, "can only be used once");
   assert(_size == 0, "can only be used once");
   if (bytes >= RelocBuffer::stack_size) {
-    _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtInternal);
+    _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtJVMCI);
   }
   _size = bytes;
 }
 
-JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS) {
+  assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
   CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
-  jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
-  AOTOopRecorder* recorder = new AOTOopRecorder(&_arena, true);
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+  AOTOopRecorder* recorder = new AOTOopRecorder(this, &_arena, true);
+  initialize_dependencies(compiled_code, recorder, JVMCI_CHECK_OK);
 
   metadata.set_oop_recorder(recorder);
 
@@ -599,9 +547,9 @@
   _constants = buffer.consts();
   buffer.set_immutable_PIC(_immutable_pic_compilation);
 
-  initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
-  if (result != JVMCIEnv::ok) {
+  initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
+  JVMCI::CodeInstallResult result = initialize_buffer(buffer, false, JVMCI_CHECK_OK);
+  if (result != JVMCI::ok) {
     return result;
   }
 
@@ -618,16 +566,24 @@
   reloc_buffer->ensure_size(buffer.total_relocation_size());
   size_t size = (size_t) buffer.copy_relocations_to(reloc_buffer->begin(), (CodeBuffer::csize_t) reloc_buffer->size(), true);
   reloc_buffer->set_size(size);
-  return JVMCIEnv::ok;
+  return JVMCI::ok;
 }
 #endif // INCLUDE_AOT
 
 // constructor used to create a method
-JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
+    JVMCIObject target,
+    JVMCIObject compiled_code,
+    CodeBlob*& cb,
+    JVMCIObject installed_code,
+    FailedSpeculation** failed_speculations,
+    char* speculations,
+    int speculations_len,
+    JVMCI_TRAPS) {
+
   CodeBuffer buffer("JVMCI Compiler CodeBuffer");
-  jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
   OopRecorder* recorder = new OopRecorder(&_arena, true);
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+  initialize_dependencies(compiled_code, recorder, JVMCI_CHECK_OK);
 
   // Get instructions and constants CodeSections early because we need it.
   _instructions = buffer.insts();
@@ -636,44 +592,55 @@
   buffer.set_immutable_PIC(_immutable_pic_compilation);
 #endif
 
-  initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
-  if (result != JVMCIEnv::ok) {
+  initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
+  JVMCI::CodeInstallResult result = initialize_buffer(buffer, true, JVMCI_CHECK_OK);
+  if (result != JVMCI::ok) {
     return result;
   }
 
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
 
-  if (!compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
-    oop stubName = HotSpotCompiledCode::name(compiled_code_obj);
-    if (stubName == NULL) {
+  if (!jvmci_env()->isa_HotSpotCompiledNmethod(compiled_code)) {
+    JVMCIObject stubName = jvmci_env()->get_HotSpotCompiledCode_name(compiled_code);
+    if (stubName.is_null()) {
       JVMCI_ERROR_OK("stub should have a name");
     }
-    char* name = strdup(java_lang_String::as_utf8_string(stubName));
+    char* name = strdup(jvmci_env()->as_utf8_string(stubName));
     cb = RuntimeStub::new_runtime_stub(name,
                                        &buffer,
                                        CodeOffsets::frame_never_safe,
                                        stack_slots,
                                        _debug_recorder->_oopmaps,
                                        false);
-    result = JVMCIEnv::ok;
+    result = JVMCI::ok;
   } else {
-    nmethod* nm = NULL;
-    methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code));
-    jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code);
-    jint id = HotSpotCompiledNmethod::id(compiled_code);
-    bool has_unsafe_access = HotSpotCompiledNmethod::hasUnsafeAccess(compiled_code) == JNI_TRUE;
-    JVMCIEnv* env = (JVMCIEnv*) (address) HotSpotCompiledNmethod::jvmciEnv(compiled_code);
+    JVMCICompileState* compile_state = (JVMCICompileState*) (address) jvmci_env()->get_HotSpotCompiledNmethod_compileState(compiled_code);
+    if (compile_state != NULL) {
+      jvmci_env()->set_compile_state(compile_state);
+    }
+
+    methodHandle method = jvmci_env()->asMethod(jvmci_env()->get_HotSpotCompiledNmethod_method(compiled_code));
+    jint entry_bci = jvmci_env()->get_HotSpotCompiledNmethod_entryBCI(compiled_code);
+    bool has_unsafe_access = jvmci_env()->get_HotSpotCompiledNmethod_hasUnsafeAccess(compiled_code) == JNI_TRUE;
+    jint id = jvmci_env()->get_HotSpotCompiledNmethod_id(compiled_code);
     if (id == -1) {
       // Make sure a valid compile_id is associated with every compile
       id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
+      jvmci_env()->set_HotSpotCompiledNmethod_id(compiled_code, id);
     }
-    result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
-                                       stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-                                       compiler, _debug_recorder, _dependencies, env, id,
-                                       has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
+    if (!jvmci_env()->isa_HotSpotNmethod(installed_code)) {
+      JVMCI_THROW_MSG_(IllegalArgumentException, "InstalledCode object must be a HotSpotNmethod when installing a HotSpotCompiledNmethod", JVMCI::ok);
+    }
+
+    JVMCIObject mirror = installed_code;
+    nmethod* nm = NULL;
+    result = runtime()->register_method(jvmci_env(), method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
+                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+                                        compiler, _debug_recorder, _dependencies, id,
+                                        has_unsafe_access, _has_wide_vector, compiled_code, mirror,
+                                        failed_speculations, speculations, speculations_len);
     cb = nm->as_codeblob_or_null();
-    if (nm != NULL && env == NULL) {
+    if (nm != NULL && compile_state == NULL) {
       DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
       bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
       if (!printnmethods && (PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers)) {
@@ -690,10 +657,10 @@
   return result;
 }
 
-void CodeInstaller::initialize_fields(oop target, oop compiled_code, TRAPS) {
-  if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
-    Handle hotspotJavaMethod(THREAD, HotSpotCompiledNmethod::method(compiled_code));
-    methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod());
+void CodeInstaller::initialize_fields(JVMCIObject target, JVMCIObject compiled_code, JVMCI_TRAPS) {
+  if (jvmci_env()->isa_HotSpotCompiledNmethod(compiled_code)) {
+    JVMCIObject hotspotJavaMethod = jvmci_env()->get_HotSpotCompiledNmethod_method(compiled_code);
+    methodHandle method = jvmci_env()->asMethod(hotspotJavaMethod);
     _parameter_count = method->size_of_parameters();
     TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string());
   } else {
@@ -701,18 +668,18 @@
     // Only used in OopMap constructor for non-product builds
     _parameter_count = 0;
   }
-  _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code));
+  _sites_handle = jvmci_env()->get_HotSpotCompiledCode_sites(compiled_code);
 
-  _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code));
-  _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code);
-  _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code);
+  _code_handle = jvmci_env()->get_HotSpotCompiledCode_targetCode(compiled_code);
+  _code_size = jvmci_env()->get_HotSpotCompiledCode_targetCodeSize(compiled_code);
+  _total_frame_size = jvmci_env()->get_HotSpotCompiledCode_totalFrameSize(compiled_code);
 
-  oop deoptRescueSlot = HotSpotCompiledCode::deoptRescueSlot(compiled_code);
-  if (deoptRescueSlot == NULL) {
+  JVMCIObject deoptRescueSlot = jvmci_env()->get_HotSpotCompiledCode_deoptRescueSlot(compiled_code);
+  if (deoptRescueSlot.is_null()) {
     _orig_pc_offset = -1;
   } else {
-    _orig_pc_offset = StackSlot::offset(deoptRescueSlot);
-    if (StackSlot::addFrameSize(deoptRescueSlot)) {
+    _orig_pc_offset = jvmci_env()->get_StackSlot_offset(deoptRescueSlot);
+    if (jvmci_env()->get_StackSlot_addFrameSize(deoptRescueSlot)) {
       _orig_pc_offset += _total_frame_size;
     }
     if (_orig_pc_offset < 0) {
@@ -721,62 +688,61 @@
   }
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
-  _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code));
-  if ((_constants->alignment() % HotSpotCompiledCode::dataSectionAlignment(compiled_code)) != 0) {
-    JVMCI_ERROR("invalid data section alignment: %d", HotSpotCompiledCode::dataSectionAlignment(compiled_code));
+  _data_section_handle = jvmci_env()->get_HotSpotCompiledCode_dataSection(compiled_code);
+  if ((_constants->alignment() % jvmci_env()->get_HotSpotCompiledCode_dataSectionAlignment(compiled_code)) != 0) {
+    JVMCI_ERROR("invalid data section alignment: %d", jvmci_env()->get_HotSpotCompiledCode_dataSectionAlignment(compiled_code));
   }
-  _constants_size = data_section()->length();
+  _constants_size = JVMCIENV->get_length(data_section());
 
-  _data_section_patches_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSectionPatches(compiled_code));
+  _data_section_patches_handle = jvmci_env()->get_HotSpotCompiledCode_dataSectionPatches(compiled_code);
 
 #ifndef PRODUCT
-  _comments_handle = JNIHandles::make_local(HotSpotCompiledCode::comments(compiled_code));
+  _comments_handle = jvmci_env()->get_HotSpotCompiledCode_comments(compiled_code);
 #endif
 
   _next_call_type = INVOKE_INVALID;
 
   _has_wide_vector = false;
 
-  oop arch = TargetDescription::arch(target);
-  _word_kind_handle = JNIHandles::make_local(Architecture::wordKind(arch));
+  JVMCIObject arch = jvmci_env()->get_TargetDescription_arch(target);
+  _word_kind_handle = jvmci_env()->get_Architecture_wordKind(arch);
 }
 
-int CodeInstaller::estimate_stubs_size(TRAPS) {
+int CodeInstaller::estimate_stubs_size(JVMCI_TRAPS) {
   // Estimate the number of static and aot call stubs that might be emitted.
   int static_call_stubs = 0;
   int aot_call_stubs = 0;
   int trampoline_stubs = 0;
-  objArrayOop sites = this->sites();
-  for (int i = 0; i < sites->length(); i++) {
-    oop site = sites->obj_at(i);
-    if (site != NULL) {
-      if (site->is_a(site_Mark::klass())) {
-        oop id_obj = site_Mark::id(site);
-        if (id_obj != NULL) {
-          if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
-            JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+  JVMCIObjectArray sites = this->sites();
+  for (int i = 0; i < JVMCIENV->get_length(sites); i++) {
+    JVMCIObject site = JVMCIENV->get_object_at(sites, i);
+    if (!site.is_null()) {
+      if (jvmci_env()->isa_site_Mark(site)) {
+        JVMCIObject id_obj = jvmci_env()->get_site_Mark_id(site);
+        if (id_obj.is_non_null()) {
+          if (!jvmci_env()->is_boxing_object(T_INT, id_obj)) {
+            JVMCI_ERROR_0("expected Integer id, got %s", jvmci_env()->klass_name(id_obj));
           }
-          jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+          jint id = jvmci_env()->get_boxed_value(T_INT, id_obj).i;
           switch (id) {
-          case INVOKEINTERFACE:
-          case INVOKEVIRTUAL:
-            trampoline_stubs++;
-            break;
-          case INVOKESTATIC:
-          case INVOKESPECIAL:
-            static_call_stubs++;
-            trampoline_stubs++;
-            break;
-          default:
-            break;
+            case INVOKEINTERFACE:
+            case INVOKEVIRTUAL:
+              trampoline_stubs++;
+              break;
+            case INVOKESTATIC:
+            case INVOKESPECIAL:
+              static_call_stubs++;
+              trampoline_stubs++;
+              break;
+            default:
+              break;
           }
         }
       }
 #if INCLUDE_AOT
-      if (UseAOT && site->is_a(site_Call::klass())) {
-        oop target = site_Call::target(site);
-        InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
-        if (!target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+      if (UseAOT && jvmci_env()->isa_site_Call(site)) {
+        JVMCIObject target = jvmci_env()-> get_site_Call_target(site);
+        if (!jvmci_env()->isa_HotSpotForeignCallTarget(target)) {
           // Add far aot trampolines.
           aot_call_stubs++;
         }
@@ -793,25 +759,25 @@
 }
 
 // perform data and call relocation on the CodeBuffer
-JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, JVMCI_TRAPS) {
   HandleMark hm;
-  objArrayHandle sites(THREAD, this->sites());
-  int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
+  JVMCIObjectArray sites = this->sites();
+  int locs_buffer_size = JVMCIENV->get_length(sites) * (relocInfo::length_limit + sizeof(relocInfo));
 
   // Allocate enough space in the stub section for the static call
   // stubs.  Stubs have extra relocs but they are managed by the stub
   // section itself so they don't need to be accounted for in the
   // locs_buffer above.
-  int stubs_size = estimate_stubs_size(CHECK_OK);
+  int stubs_size = estimate_stubs_size(JVMCI_CHECK_OK);
   int total_size = align_up(_code_size, buffer.insts()->alignment()) + align_up(_constants_size, buffer.consts()->alignment()) + align_up(stubs_size, buffer.stubs()->alignment());
 
   if (check_size && total_size > JVMCINMethodSizeLimit) {
-    return JVMCIEnv::code_too_large;
+    return JVMCI::code_too_large;
   }
 
   buffer.initialize(total_size, locs_buffer_size);
   if (buffer.blob() == NULL) {
-    return JVMCIEnv::cache_full;
+    return JVMCI::cache_full;
   }
   buffer.initialize_stubs_size(stubs_size);
   buffer.initialize_consts_size(_constants_size);
@@ -823,49 +789,49 @@
 
   // copy the constant data into the newly created CodeBuffer
   address end_data = _constants->start() + _constants_size;
-  memcpy(_constants->start(), data_section()->base(T_BYTE), _constants_size);
+  JVMCIENV->copy_bytes_to(data_section(), (jbyte*) _constants->start(), 0, _constants_size);
   _constants->set_end(end_data);
 
   // copy the code into the newly created CodeBuffer
   address end_pc = _instructions->start() + _code_size;
   guarantee(_instructions->allocates2(end_pc), "initialize should have reserved enough space for all the code");
-  memcpy(_instructions->start(), code()->base(T_BYTE), _code_size);
+  JVMCIENV->copy_bytes_to(code(), (jbyte*) _instructions->start(), 0, _code_size);
   _instructions->set_end(end_pc);
 
-  for (int i = 0; i < data_section_patches()->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle patch(THREAD, data_section_patches()->obj_at(i));
+  for (int i = 0; i < JVMCIENV->get_length(data_section_patches()); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject patch = JVMCIENV->get_object_at(data_section_patches(), i);
     if (patch.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    Handle reference(THREAD, site_DataPatch::reference(patch));
+    JVMCIObject reference = jvmci_env()->get_site_DataPatch_reference(patch);
     if (reference.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    if (!reference->is_a(site_ConstantReference::klass())) {
-      JVMCI_ERROR_OK("invalid patch in data section: %s", reference->klass()->signature_name());
+    if (!jvmci_env()->isa_site_ConstantReference(reference)) {
+      JVMCI_ERROR_OK("invalid patch in data section: %s", jvmci_env()->klass_name(reference));
     }
-    Handle constant(THREAD, site_ConstantReference::constant(reference));
+    JVMCIObject constant = jvmci_env()->get_site_ConstantReference_constant(reference);
     if (constant.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    address dest = _constants->start() + site_Site::pcOffset(patch);
-    if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+    address dest = _constants->start() + jvmci_env()->get_site_Site_pcOffset(patch);
+    if (jvmci_env()->isa_HotSpotMetaspaceConstantImpl(constant)) {
+      if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
 #ifdef _LP64
-        *((narrowKlass*) dest) = record_narrow_metadata_reference(_constants, dest, constant, CHECK_OK);
+        *((narrowKlass*) dest) = record_narrow_metadata_reference(_constants, dest, constant, JVMCI_CHECK_OK);
 #else
         JVMCI_ERROR_OK("unexpected compressed Klass* in 32-bit mode");
 #endif
       } else {
-        *((void**) dest) = record_metadata_reference(_constants, dest, constant, CHECK_OK);
+        *((void**) dest) = record_metadata_reference(_constants, dest, constant, JVMCI_CHECK_OK);
       }
-    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
-      Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+    } else if (jvmci_env()->isa_HotSpotObjectConstantImpl(constant)) {
+      Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK_OK);
       jobject value = JNIHandles::make_local(obj());
       int oop_index = _oop_recorder->find_index(value);
 
-      if (HotSpotObjectConstantImpl::compressed(constant)) {
+      if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
 #ifdef _LP64
         _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const);
 #else
@@ -875,46 +841,48 @@
         _constants->relocate(dest, oop_Relocation::spec(oop_index));
       }
     } else {
-      JVMCI_ERROR_OK("invalid constant in data section: %s", constant->klass()->signature_name());
+      JVMCI_ERROR_OK("invalid constant in data section: %s", jvmci_env()->klass_name(constant));
     }
   }
   jint last_pc_offset = -1;
-  for (int i = 0; i < sites->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle site(THREAD, sites->obj_at(i));
+  for (int i = 0; i < JVMCIENV->get_length(sites); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject site = JVMCIENV->get_object_at(sites, i);
     if (site.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
 
-    jint pc_offset = site_Site::pcOffset(site);
+    jint pc_offset = jvmci_env()->get_site_Site_pcOffset(site);
 
-    if (site->is_a(site_Call::klass())) {
+    if (jvmci_env()->isa_site_Call(site)) {
       TRACE_jvmci_4("call at %i", pc_offset);
-      site_Call(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_Infopoint::klass())) {
+      site_Call(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_Infopoint(site)) {
       // three reasons for infopoints denote actual safepoints
-      oop reason = site_Infopoint::reason(site);
-      if (site_InfopointReason::SAFEPOINT() == reason || site_InfopointReason::CALL() == reason || site_InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+      JVMCIObject reason = jvmci_env()->get_site_Infopoint_reason(site);
+      if (JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_SAFEPOINT()) ||
+          JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_CALL()) ||
+          JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_IMPLICIT_EXCEPTION())) {
         TRACE_jvmci_4("safepoint at %i", pc_offset);
-        site_Safepoint(buffer, pc_offset, site, CHECK_OK);
+        site_Safepoint(buffer, pc_offset, site, JVMCI_CHECK_OK);
         if (_orig_pc_offset < 0) {
           JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot");
         }
       } else {
         TRACE_jvmci_4("infopoint at %i", pc_offset);
-        site_Infopoint(buffer, pc_offset, site, CHECK_OK);
+        site_Infopoint(buffer, pc_offset, site, JVMCI_CHECK_OK);
       }
-    } else if (site->is_a(site_DataPatch::klass())) {
+    } else if (jvmci_env()->isa_site_DataPatch(site)) {
       TRACE_jvmci_4("datapatch at %i", pc_offset);
-      site_DataPatch(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_Mark::klass())) {
+      site_DataPatch(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_Mark(site)) {
       TRACE_jvmci_4("mark at %i", pc_offset);
-      site_Mark(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_ExceptionHandler::klass())) {
+      site_Mark(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_ExceptionHandler(site)) {
       TRACE_jvmci_4("exceptionhandler at %i", pc_offset);
       site_ExceptionHandler(pc_offset, site);
     } else {
-      JVMCI_ERROR_OK("unexpected site subclass: %s", site->klass()->signature_name());
+      JVMCI_ERROR_OK("unexpected site subclass: %s", jvmci_env()->klass_name(site));
     }
     last_pc_offset = pc_offset;
 
@@ -926,61 +894,62 @@
   }
 
 #ifndef PRODUCT
-  if (comments() != NULL) {
-    for (int i = 0; i < comments()->length(); i++) {
-      oop comment = comments()->obj_at(i);
-      assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
-      jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
-      char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
+  if (comments().is_non_null()) {
+    for (int i = 0; i < JVMCIENV->get_length(comments()); i++) {
+      JVMCIObject comment = JVMCIENV->get_object_at(comments(), i);
+      assert(jvmci_env()->isa_HotSpotCompiledCode_Comment(comment), "cce");
+      jint offset = jvmci_env()->get_HotSpotCompiledCode_Comment_pcOffset(comment);
+      const char* text = jvmci_env()->as_utf8_string(jvmci_env()->get_HotSpotCompiledCode_Comment_text(comment));
       buffer.block_comment(offset, text);
     }
   }
 #endif
-  return JVMCIEnv::ok;
+  return JVMCI::ok;
 }
 
-void CodeInstaller::assumption_NoFinalizableSubclass(Thread* thread, Handle assumption) {
-  Handle receiverType_handle (thread, Assumptions_NoFinalizableSubclass::receiverType(assumption()));
-  Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle));
+void CodeInstaller::assumption_NoFinalizableSubclass(JVMCIObject assumption) {
+  JVMCIObject receiverType_handle = jvmci_env()->get_Assumptions_NoFinalizableSubclass_receiverType(assumption);
+  Klass* receiverType = jvmci_env()->asKlass(receiverType_handle);
   _dependencies->assert_has_no_finalizable_subclasses(receiverType);
 }
 
-void CodeInstaller::assumption_ConcreteSubtype(Thread* thread, Handle assumption) {
-  Handle context_handle (thread, Assumptions_ConcreteSubtype::context(assumption()));
-  Handle subtype_handle (thread, Assumptions_ConcreteSubtype::subtype(assumption()));
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
-  Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle));
+void CodeInstaller::assumption_ConcreteSubtype(JVMCIObject assumption) {
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_ConcreteSubtype_context(assumption);
+  JVMCIObject subtype_handle = jvmci_env()->get_Assumptions_ConcreteSubtype_subtype(assumption);
+  Klass* context = jvmci_env()->asKlass(context_handle);
+  Klass* subtype = jvmci_env()->asKlass(subtype_handle);
 
   assert(context->is_abstract(), "");
   _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
 }
 
-void CodeInstaller::assumption_LeafType(Thread* thread, Handle assumption) {
-  Handle context_handle (thread, Assumptions_LeafType::context(assumption()));
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+void CodeInstaller::assumption_LeafType(JVMCIObject assumption) {
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_LeafType_context(assumption);
+  Klass* context = jvmci_env()->asKlass(context_handle);
 
   _dependencies->assert_leaf_type(context);
 }
 
-void CodeInstaller::assumption_ConcreteMethod(Thread* thread, Handle assumption) {
-  Handle impl_handle (thread, Assumptions_ConcreteMethod::impl(assumption()));
-  Handle context_handle (thread, Assumptions_ConcreteMethod::context(assumption()));
+void CodeInstaller::assumption_ConcreteMethod(JVMCIObject assumption) {
+  JVMCIObject impl_handle = jvmci_env()->get_Assumptions_ConcreteMethod_impl(assumption);
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_ConcreteMethod_context(assumption);
 
-  methodHandle impl = getMethodFromHotSpotMethod(impl_handle());
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+  methodHandle impl = jvmci_env()->asMethod(impl_handle);
+  Klass* context = jvmci_env()->asKlass(context_handle);
 
   _dependencies->assert_unique_concrete_method(context, impl());
 }
 
-void CodeInstaller::assumption_CallSiteTargetValue(Thread* thread, Handle assumption) {
-  Handle callSite(thread, HotSpotObjectConstantImpl::object(Assumptions_CallSiteTargetValue::callSite(assumption())));
-  Handle methodHandle(thread, HotSpotObjectConstantImpl::object(Assumptions_CallSiteTargetValue::methodHandle(assumption())));
-
+void CodeInstaller::assumption_CallSiteTargetValue(JVMCIObject assumption, JVMCI_TRAPS) {
+  JVMCIObject callSiteConstant = jvmci_env()->get_Assumptions_CallSiteTargetValue_callSite(assumption);
+  Handle callSite = jvmci_env()->asConstant(callSiteConstant, JVMCI_CHECK);
+  JVMCIObject methodConstant = jvmci_env()->get_Assumptions_CallSiteTargetValue_methodHandle(assumption);
+  Handle methodHandle = jvmci_env()->asConstant(methodConstant, JVMCI_CHECK);
   _dependencies->assert_call_site_target_value(callSite(), methodHandle());
 }
 
-void CodeInstaller::site_ExceptionHandler(jint pc_offset, Handle exc) {
-  jint handler_offset = site_ExceptionHandler::handlerPos(exc);
+void CodeInstaller::site_ExceptionHandler(jint pc_offset, JVMCIObject exc) {
+  jint handler_offset = jvmci_env()->get_site_ExceptionHandler_handlerPos(exc);
 
   // Subtable header
   _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0));
@@ -1005,19 +974,20 @@
   return true;
 }
 
-GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(Handle debug_info, TRAPS) {
-  objArrayHandle virtualObjects(THREAD, DebugInfo::virtualObjectMapping(debug_info));
+GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(JVMCIObject debug_info, JVMCI_TRAPS) {
+  JVMCIObjectArray virtualObjects = jvmci_env()->get_DebugInfo_virtualObjectMapping(debug_info);
   if (virtualObjects.is_null()) {
     return NULL;
   }
-  GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL);
+  GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(JVMCIENV->get_length(virtualObjects), JVMCIENV->get_length(virtualObjects), NULL);
   // Create the unique ObjectValues
-  for (int i = 0; i < virtualObjects->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle value(THREAD, virtualObjects->obj_at(i));
-    int id = VirtualObject::id(value);
-    Handle type(THREAD, VirtualObject::type(value));
-    oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+  for (int i = 0; i < JVMCIENV->get_length(virtualObjects); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject value = JVMCIENV->get_object_at(virtualObjects, i);
+    int id = jvmci_env()->get_VirtualObject_id(value);
+    JVMCIObject type = jvmci_env()->get_VirtualObject_type(value);
+    Klass* klass = jvmci_env()->asKlass(type);
+    oop javaMirror = klass->java_mirror();
     ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror)));
     if (id < 0 || id >= objects->length()) {
       JVMCI_ERROR_NULL("virtual object id %d out of bounds", id);
@@ -1029,18 +999,18 @@
   }
   // All the values which could be referenced by the VirtualObjects
   // exist, so now describe all the VirtualObjects themselves.
-  for (int i = 0; i < virtualObjects->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle value(THREAD, virtualObjects->obj_at(i));
-    int id = VirtualObject::id(value);
-    record_object_value(objects->at(id)->as_ObjectValue(), value, objects, CHECK_NULL);
+  for (int i = 0; i < JVMCIENV->get_length(virtualObjects); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject value = JVMCIENV->get_object_at(virtualObjects, i);
+    int id = jvmci_env()->get_VirtualObject_id(value);
+    record_object_value(objects->at(id)->as_ObjectValue(), value, objects, JVMCI_CHECK_NULL);
   }
   _debug_recorder->dump_object_pool(objects);
   return objects;
 }
 
-void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS) {
-  Handle position(THREAD, DebugInfo::bytecodePosition(debug_info));
+void CodeInstaller::record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, bool return_oop, JVMCI_TRAPS) {
+  JVMCIObject position = jvmci_env()->get_DebugInfo_bytecodePosition(debug_info);
   if (position.is_null()) {
     // Stubs do not record scope info, just oop maps
     return;
@@ -1048,26 +1018,26 @@
 
   GrowableArray<ScopeValue*>* objectMapping;
   if (scope_mode == CodeInstaller::FullFrame) {
-    objectMapping = record_virtual_objects(debug_info, CHECK);
+    objectMapping = record_virtual_objects(debug_info, JVMCI_CHECK);
   } else {
     objectMapping = NULL;
   }
-  record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, CHECK);
+  record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, JVMCI_CHECK);
 }
 
 int CodeInstaller::map_jvmci_bci(int bci) {
   if (bci < 0) {
-    if (bci == BytecodeFrame::BEFORE_BCI()) {
+    if (bci == jvmci_env()->get_BytecodeFrame_BEFORE_BCI()) {
       return BeforeBci;
-    } else if (bci == BytecodeFrame::AFTER_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_AFTER_BCI()) {
       return AfterBci;
-    } else if (bci == BytecodeFrame::UNWIND_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_UNWIND_BCI()) {
       return UnwindBci;
-    } else if (bci == BytecodeFrame::AFTER_EXCEPTION_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_AFTER_EXCEPTION_BCI()) {
       return AfterExceptionBci;
-    } else if (bci == BytecodeFrame::UNKNOWN_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_UNKNOWN_BCI()) {
       return UnknownBci;
-    } else if (bci == BytecodeFrame::INVALID_FRAMESTATE_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_INVALID_FRAMESTATE_BCI()) {
       return InvalidFrameStateBci;
     }
     ShouldNotReachHere();
@@ -1075,34 +1045,37 @@
   return bci;
 }
 
-void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS) {
-  Handle frame;
+void CodeInstaller::record_scope(jint pc_offset, JVMCIObject position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, JVMCI_TRAPS) {
+  JVMCIObject frame;
   if (scope_mode == CodeInstaller::FullFrame) {
-    if (!position->is_a(BytecodeFrame::klass())) {
+    if (!jvmci_env()->isa_BytecodeFrame(position)) {
       JVMCI_ERROR("Full frame expected for debug info at %i", pc_offset);
     }
     frame = position;
   }
-  Handle caller_frame (THREAD, BytecodePosition::caller(position));
-  if (caller_frame.not_null()) {
-    record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, CHECK);
+  JVMCIObject caller_frame = jvmci_env()->get_BytecodePosition_caller(position);
+  if (caller_frame.is_non_null()) {
+    record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, JVMCI_CHECK);
   }
 
-  Handle hotspot_method (THREAD, BytecodePosition::method(position));
-  Method* method = getMethodFromHotSpotMethod(hotspot_method());
-  jint bci = map_jvmci_bci(BytecodePosition::bci(position));
+  JVMCIObject hotspot_method = jvmci_env()->get_BytecodePosition_method(position);
+  Method* method = jvmci_env()->asMethod(hotspot_method);
+  jint bci = map_jvmci_bci(jvmci_env()->get_BytecodePosition_bci(position));
+  if (bci == jvmci_env()->get_BytecodeFrame_BEFORE_BCI()) {
+    bci = SynchronizationEntryBCI;
+  }
 
   TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string());
 
   bool reexecute = false;
-  if (frame.not_null()) {
-    if (bci < 0) {
+  if (frame.is_non_null()) {
+    if (bci < 0){
        reexecute = false;
     } else {
       Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
       reexecute = bytecode_should_reexecute(code);
-      if (frame.not_null()) {
-        reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE);
+      if (frame.is_non_null()) {
+        reexecute = (jvmci_env()->get_BytecodeFrame_duringCall(frame) == JNI_FALSE);
       }
     }
   }
@@ -1112,55 +1085,55 @@
   DebugToken* monitors_token = NULL;
   bool throw_exception = false;
 
-  if (frame.not_null()) {
-    jint local_count = BytecodeFrame::numLocals(frame);
-    jint expression_count = BytecodeFrame::numStack(frame);
-    jint monitor_count = BytecodeFrame::numLocks(frame);
-    objArrayHandle values(THREAD, BytecodeFrame::values(frame));
-    objArrayHandle slotKinds(THREAD, BytecodeFrame::slotKinds(frame));
+  if (frame.is_non_null()) {
+    jint local_count = jvmci_env()->get_BytecodeFrame_numLocals(frame);
+    jint expression_count = jvmci_env()->get_BytecodeFrame_numStack(frame);
+    jint monitor_count = jvmci_env()->get_BytecodeFrame_numLocks(frame);
+    JVMCIObjectArray values = jvmci_env()->get_BytecodeFrame_values(frame);
+    JVMCIObjectArray slotKinds = jvmci_env()->get_BytecodeFrame_slotKinds(frame);
 
     if (values.is_null() || slotKinds.is_null()) {
-      THROW(vmSymbols::java_lang_NullPointerException());
+      JVMCI_THROW(NullPointerException);
     }
-    if (local_count + expression_count + monitor_count != values->length()) {
-      JVMCI_ERROR("unexpected values length %d in scope (%d locals, %d expressions, %d monitors)", values->length(), local_count, expression_count, monitor_count);
+    if (local_count + expression_count + monitor_count != JVMCIENV->get_length(values)) {
+      JVMCI_ERROR("unexpected values length %d in scope (%d locals, %d expressions, %d monitors)", JVMCIENV->get_length(values), local_count, expression_count, monitor_count);
     }
-    if (local_count + expression_count != slotKinds->length()) {
-      JVMCI_ERROR("unexpected slotKinds length %d in scope (%d locals, %d expressions)", slotKinds->length(), local_count, expression_count);
+    if (local_count + expression_count != JVMCIENV->get_length(slotKinds)) {
+      JVMCI_ERROR("unexpected slotKinds length %d in scope (%d locals, %d expressions)", JVMCIENV->get_length(slotKinds), local_count, expression_count);
     }
 
     GrowableArray<ScopeValue*>* locals = local_count > 0 ? new GrowableArray<ScopeValue*> (local_count) : NULL;
     GrowableArray<ScopeValue*>* expressions = expression_count > 0 ? new GrowableArray<ScopeValue*> (expression_count) : NULL;
     GrowableArray<MonitorValue*>* monitors = monitor_count > 0 ? new GrowableArray<MonitorValue*> (monitor_count) : NULL;
 
-    TRACE_jvmci_2("Scope at bci %d with %d values", bci, values->length());
+    TRACE_jvmci_2("Scope at bci %d with %d values", bci, JVMCIENV->get_length(values));
     TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
 
-    for (jint i = 0; i < values->length(); i++) {
-      HandleMark hm(THREAD);
+    for (jint i = 0; i < JVMCIENV->get_length(values); i++) {
+      // HandleMark hm(THREAD);
       ScopeValue* second = NULL;
-      Handle value(THREAD, values->obj_at(i));
+      JVMCIObject value = JVMCIENV->get_object_at(values, i);
       if (i < local_count) {
-        BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK);
-        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, JVMCI_CHECK);
         if (second != NULL) {
           locals->append(second);
         }
         locals->append(first);
       } else if (i < local_count + expression_count) {
-        BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK);
-        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, JVMCI_CHECK);
         if (second != NULL) {
           expressions->append(second);
         }
         expressions->append(first);
       } else {
-        MonitorValue *monitor = get_monitor_value(value, objects, CHECK);
+        MonitorValue *monitor = get_monitor_value(value, objects, JVMCI_CHECK);
         monitors->append(monitor);
       }
       if (second != NULL) {
         i++;
-        if (i >= values->length() || values->obj_at(i) != Value::ILLEGAL()) {
+        if (i >= JVMCIENV->get_length(values) || !JVMCIENV->equals(JVMCIENV->get_object_at(values, i), jvmci_env()->get_Value_ILLEGAL())) {
           JVMCI_ERROR("double-slot value not followed by Value.ILLEGAL");
         }
       }
@@ -1170,29 +1143,29 @@
     expressions_token = _debug_recorder->create_scope_values(expressions);
     monitors_token = _debug_recorder->create_monitor_values(monitors);
 
-    throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE;
+    throw_exception = jvmci_env()->get_BytecodeFrame_rethrowException(frame) == JNI_TRUE;
   }
 
   _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, return_oop,
                                   locals_token, expressions_token, monitors_token);
 }
 
-void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle debug_info (THREAD, site_Infopoint::debugInfo(site));
+void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
   if (debug_info.is_null()) {
     JVMCI_ERROR("debug info expected at safepoint at %i", pc_offset);
   }
 
   // address instruction = _instructions->start() + pc_offset;
   // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
-  OopMap *map = create_oop_map(debug_info, CHECK);
+  OopMap *map = create_oop_map(debug_info, JVMCI_CHECK);
   _debug_recorder->add_safepoint(pc_offset, map);
-  record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, CHECK);
+  record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, JVMCI_CHECK);
   _debug_recorder->end_safepoint(pc_offset);
 }
 
-void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle debug_info (THREAD, site_Infopoint::debugInfo(site));
+void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
   if (debug_info.is_null()) {
     JVMCI_ERROR("debug info expected at infopoint at %i", pc_offset);
   }
@@ -1202,53 +1175,51 @@
   // but DebugInformationRecorder doesn't have sufficient public API.
 
   _debug_recorder->add_non_safepoint(pc_offset);
-  record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, CHECK);
+  record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, JVMCI_CHECK);
   _debug_recorder->end_non_safepoint(pc_offset);
 }
 
-void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle target(THREAD, site_Call::target(site));
-  InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject target = jvmci_env()->get_site_Call_target(site);
+  JVMCIObject hotspot_method; // JavaMethod
+  JVMCIObject foreign_call;
 
-  Handle hotspot_method; // JavaMethod
-  Handle foreign_call;
-
-  if (target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+  if (jvmci_env()->isa_HotSpotForeignCallTarget(target)) {
     foreign_call = target;
   } else {
     hotspot_method = target;
   }
 
-  Handle debug_info (THREAD, site_Call::debugInfo(site));
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
 
-  assert(hotspot_method.not_null() ^ foreign_call.not_null(), "Call site needs exactly one type");
+  assert(hotspot_method.is_non_null() ^ foreign_call.is_non_null(), "Call site needs exactly one type");
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
-  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method, CHECK);
+  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method, JVMCI_CHECK);
 
-  if (debug_info.not_null()) {
-    OopMap *map = create_oop_map(debug_info, CHECK);
+  if (debug_info.is_non_null()) {
+    OopMap *map = create_oop_map(debug_info, JVMCI_CHECK);
     _debug_recorder->add_safepoint(next_pc_offset, map);
 
-    bool return_oop = hotspot_method.not_null() && getMethodFromHotSpotMethod(hotspot_method())->is_returning_oop();
+    bool return_oop = hotspot_method.is_non_null() && jvmci_env()->asMethod(hotspot_method)->is_returning_oop();
 
-    record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, return_oop, CHECK);
+    record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, return_oop, JVMCI_CHECK);
   }
 
-  if (foreign_call.not_null()) {
-    jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call);
+  if (foreign_call.is_non_null()) {
+    jlong foreign_call_destination = jvmci_env()->get_HotSpotForeignCallTarget_address(foreign_call);
     if (_immutable_pic_compilation) {
       // Use fake short distance during PIC compilation.
       foreign_call_destination = (jlong)(_instructions->start() + pc_offset);
     }
-    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, CHECK);
+    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, JVMCI_CHECK);
   } else { // method != NULL
     if (debug_info.is_null()) {
       JVMCI_ERROR("debug info expected at call at %i", pc_offset);
     }
 
     TRACE_jvmci_3("method call");
-    CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, CHECK);
+    CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, JVMCI_CHECK);
     if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
       // Need a static call stub for transitions from compiled to interpreted.
       CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
@@ -1261,57 +1232,67 @@
 
   _next_call_type = INVOKE_INVALID;
 
-  if (debug_info.not_null()) {
+  if (debug_info.is_non_null()) {
     _debug_recorder->end_safepoint(next_pc_offset);
   }
 }
 
-void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle reference(THREAD, site_DataPatch::reference(site));
+void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject reference = jvmci_env()->get_site_DataPatch_reference(site);
   if (reference.is_null()) {
-    THROW(vmSymbols::java_lang_NullPointerException());
-  } else if (reference->is_a(site_ConstantReference::klass())) {
-    Handle constant(THREAD, site_ConstantReference::constant(reference));
+    JVMCI_THROW(NullPointerException);
+  } else if (jvmci_env()->isa_site_ConstantReference(reference)) {
+    JVMCIObject constant = jvmci_env()->get_site_ConstantReference_constant(reference);
     if (constant.is_null()) {
-      THROW(vmSymbols::java_lang_NullPointerException());
-    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+      JVMCI_THROW(NullPointerException);
+    } else if (jvmci_env()->isa_DirectHotSpotObjectConstantImpl(constant)) {
+      if (!JVMCIENV->is_hotspot()) {
+        JVMCIObject string = JVMCIENV->call_HotSpotJVMCIRuntime_callToString(constant, JVMCI_CHECK);
+        const char* to_string = JVMCIENV->as_utf8_string(string);
+        JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Direct object constant reached the backend: %s", to_string));
+      }
       if (!_immutable_pic_compilation) {
         // Do not patch during PIC compilation.
-        pd_patch_OopConstant(pc_offset, constant, CHECK);
+        pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
       }
-    } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+    } else if (jvmci_env()->isa_IndirectHotSpotObjectConstantImpl(constant)) {
       if (!_immutable_pic_compilation) {
-        pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+        // Do not patch during PIC compilation.
+        pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
+      }
+    } else if (jvmci_env()->isa_HotSpotMetaspaceConstantImpl(constant)) {
+      if (!_immutable_pic_compilation) {
+        pd_patch_MetaspaceConstant(pc_offset, constant, JVMCI_CHECK);
       }
 #if INCLUDE_AOT
-    } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
+    } else if (jvmci_env()->isa_HotSpotSentinelConstant(constant)) {
       if (!_immutable_pic_compilation) {
-        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", constant->klass()->signature_name());
+        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", jvmci_env()->klass_name(constant));
       }
 #endif
     } else {
-      JVMCI_ERROR("unknown constant type in data patch: %s", constant->klass()->signature_name());
+      JVMCI_ERROR("unknown constant type in data patch: %s", jvmci_env()->klass_name(constant));
     }
-  } else if (reference->is_a(site_DataSectionReference::klass())) {
-    int data_offset = site_DataSectionReference::offset(reference);
+  } else if (jvmci_env()->isa_site_DataSectionReference(reference)) {
+    int data_offset = jvmci_env()->get_site_DataSectionReference_offset(reference);
     if (0 <= data_offset && data_offset < _constants_size) {
-      pd_patch_DataSectionReference(pc_offset, data_offset, CHECK);
+      pd_patch_DataSectionReference(pc_offset, data_offset, JVMCI_CHECK);
     } else {
       JVMCI_ERROR("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size);
     }
   } else {
-    JVMCI_ERROR("unknown data patch type: %s", reference->klass()->signature_name());
+    JVMCI_ERROR("unknown data patch type: %s", jvmci_env()->klass_name(reference));
   }
 }
 
-void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle id_obj (THREAD, site_Mark::id(site));
+void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject id_obj = jvmci_env()->get_site_Mark_id(site);
 
-  if (id_obj.not_null()) {
-    if (!java_lang_boxing_object::is_instance(id_obj(), T_INT)) {
-      JVMCI_ERROR("expected Integer id, got %s", id_obj->klass()->signature_name());
+  if (id_obj.is_non_null()) {
+    if (!jvmci_env()->is_boxing_object(T_INT, id_obj)) {
+      JVMCI_ERROR("expected Integer id, got %s", jvmci_env()->klass_name(id_obj));
     }
-    jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+    jint id = jvmci_env()->get_boxed_value(T_INT, id_obj).i;
 
     address pc = _instructions->start() + pc_offset;
 
@@ -1343,7 +1324,7 @@
       case POLL_FAR:
       case POLL_RETURN_NEAR:
       case POLL_RETURN_FAR:
-        pd_relocate_poll(pc, id, CHECK);
+        pd_relocate_poll(pc, id, JVMCI_CHECK);
         break;
       case CARD_TABLE_SHIFT:
       case CARD_TABLE_ADDRESS:
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Fri May 03 14:59:32 2019 -0400
@@ -24,9 +24,11 @@
 #ifndef SHARE_JVMCI_JVMCICODEINSTALLER_HPP
 #define SHARE_JVMCI_JVMCICODEINSTALLER_HPP
 
-#include "jvmci/jvmciCompiler.hpp"
+#include "code/debugInfoRec.hpp"
+#include "code/exceptionHandlerTable.hpp"
+#include "code/nativeInst.hpp"
+#include "jvmci/jvmci.hpp"
 #include "jvmci/jvmciEnv.hpp"
-#include "code/nativeInst.hpp"
 
 #if INCLUDE_AOT
 class RelocBuffer : public StackObj {
@@ -44,9 +46,11 @@
   char *_buffer;
 };
 
+class CodeInstaller;
+
 class AOTOopRecorder : public OopRecorder {
 public:
-  AOTOopRecorder(Arena* arena = NULL, bool deduplicate = false);
+  AOTOopRecorder(CodeInstaller* code_inst, Arena* arena = NULL, bool deduplicate = false);
 
   virtual int find_index(Metadata* h);
   virtual int find_index(jobject h);
@@ -57,7 +61,10 @@
   void record_meta_ref(jobject ref, int index);
 
   GrowableArray<jobject>* _meta_refs;
+
+  CodeInstaller* _code_inst;
 };
+#endif // INCLUDE_AOT
 
 class CodeMetadata {
 public:
@@ -71,9 +78,10 @@
   u_char* get_scopes_desc() const { return _scopes_desc; }
   int get_scopes_size() const { return _nr_scopes_desc; }
 
+#if INCLUDE_AOT
   RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; }
-
   AOTOopRecorder* get_oop_recorder() { return _oop_recorder; }
+#endif
 
   ExceptionHandlerTable* get_exception_table() { return _exception_table; }
 
@@ -87,9 +95,11 @@
     _nr_scopes_desc = size;
   }
 
+#if INCLUDE_AOT
   void set_oop_recorder(AOTOopRecorder* recorder) {
     _oop_recorder = recorder;
   }
+#endif
 
   void set_exception_table(ExceptionHandlerTable* table) {
     _exception_table = table;
@@ -103,11 +113,12 @@
   u_char* _scopes_desc;
   int _nr_scopes_desc;
 
+#if INCLUDE_AOT
   RelocBuffer _reloc_buffer;
   AOTOopRecorder* _oop_recorder;
+#endif
   ExceptionHandlerTable* _exception_table;
 };
-#endif // INCLUDE_AOT
 
 /*
  * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
@@ -143,24 +154,26 @@
   };
 
   Arena         _arena;
+  JVMCIEnv*     _jvmci_env;
 
-  jobject       _data_section_handle;
-  jobject       _data_section_patches_handle;
-  jobject       _sites_handle;
+  JVMCIPrimitiveArray    _data_section_handle;
+  JVMCIObjectArray       _data_section_patches_handle;
+  JVMCIObjectArray       _sites_handle;
+#ifndef PRODUCT
+  JVMCIObjectArray       _comments_handle;
+#endif
+  JVMCIPrimitiveArray    _code_handle;
+  JVMCIObject            _word_kind_handle;
+
   CodeOffsets   _offsets;
 
-  jobject       _code_handle;
   jint          _code_size;
   jint          _total_frame_size;
   jint          _orig_pc_offset;
   jint          _parameter_count;
   jint          _constants_size;
-#ifndef PRODUCT
-  jobject       _comments_handle;
-#endif
 
   bool          _has_wide_vector;
-  jobject       _word_kind_handle;
 
   MarkId        _next_call_type;
   address       _invoke_mark_pc;
@@ -182,72 +195,84 @@
   static ConstantIntValue*    _int_2_scope_value;
   static LocationValue*       _illegal_value;
 
-  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS);
-  void pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS);
-  void pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS);
-  void pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS);
-  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS);
-  void pd_relocate_JavaMethod(CodeBuffer &cbuf, Handle method, jint pc_offset, TRAPS);
-  void pd_relocate_poll(address pc, jint mark, TRAPS);
+  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS);
+  void pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS);
+  void pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS);
+  void pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS);
+  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS);
+  void pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject method, jint pc_offset, JVMCI_TRAPS);
+  void pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS);
 
-  objArrayOop sites();
-  arrayOop code();
-  arrayOop data_section();
-  objArrayOop data_section_patches();
+  JVMCIObjectArray sites()                { return _sites_handle; }
+  JVMCIPrimitiveArray code()              { return _code_handle; }
+  JVMCIPrimitiveArray  data_section()     { return _data_section_handle; }
+  JVMCIObjectArray data_section_patches() { return _data_section_patches_handle; }
 #ifndef PRODUCT
-  objArrayOop comments();
+  JVMCIObjectArray comments()             { return _comments_handle; }
 #endif
-
-  oop word_kind();
+  JVMCIObject word_kind()                 { return _word_kind_handle; }
 
 public:
 
-  CodeInstaller(bool immutable_pic_compilation) : _arena(mtCompiler), _immutable_pic_compilation(immutable_pic_compilation) {}
+  CodeInstaller(JVMCIEnv* jvmci_env, bool immutable_pic_compilation) : _arena(mtJVMCI), _jvmci_env(jvmci_env), _immutable_pic_compilation(immutable_pic_compilation) {}
 
 #if INCLUDE_AOT
-  JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS);
+  JVMCI::CodeInstallResult gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS);
 #endif
-  JVMCIEnv::CodeInstallResult install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS);
+  JVMCI::CodeInstallResult install(JVMCICompiler* compiler,
+                                   JVMCIObject target,
+                                   JVMCIObject compiled_code,
+                                   CodeBlob*& cb,
+                                   JVMCIObject installed_code,
+                                   FailedSpeculation** failed_speculations,
+                                   char* speculations,
+                                   int speculations_len,
+                                   JVMCI_TRAPS);
+
+  JVMCIEnv* jvmci_env() { return _jvmci_env; }
+  JVMCIRuntime* runtime() { return _jvmci_env->runtime(); }
 
   static address runtime_call_target_address(oop runtime_call);
-  static VMReg get_hotspot_reg(jint jvmciRegisterNumber, TRAPS);
+  static VMReg get_hotspot_reg(jint jvmciRegisterNumber, JVMCI_TRAPS);
   static bool is_general_purpose_reg(VMReg hotspotRegister);
 
   const OopMapSet* oopMapSet() const { return _debug_recorder->_oopmaps; }
 
 protected:
-  Location::Type get_oop_type(Thread* thread, Handle value);
-  ScopeValue* get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS);
-  MonitorValue* get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+  Location::Type get_oop_type(JVMCIObject value);
+  ScopeValue* get_scope_value(JVMCIObject value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, JVMCI_TRAPS);
+  MonitorValue* get_monitor_value(JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS);
 
-  void* record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+  void* record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS);
 #ifdef _LP64
-  narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+  narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS);
 #endif
 
   // extract the fields of the HotSpotCompiledCode
-  void initialize_fields(oop target, oop target_method, TRAPS);
-  void initialize_dependencies(oop target_method, OopRecorder* oop_recorder, TRAPS);
+  void initialize_fields(JVMCIObject target, JVMCIObject compiled_code, JVMCI_TRAPS);
+  void initialize_dependencies(JVMCIObject compiled_code, OopRecorder* oop_recorder, JVMCI_TRAPS);
 
-  int estimate_stubs_size(TRAPS);
+  int estimate_stubs_size(JVMCI_TRAPS);
 
   // perform data and call relocation on the CodeBuffer
-  JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS);
+  JVMCI::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, JVMCI_TRAPS);
 
-  void assumption_NoFinalizableSubclass(Thread* thread, Handle assumption);
-  void assumption_ConcreteSubtype(Thread* thread, Handle assumption);
-  void assumption_LeafType(Thread* thread, Handle assumption);
-  void assumption_ConcreteMethod(Thread* thread, Handle assumption);
-  void assumption_CallSiteTargetValue(Thread* thread, Handle assumption);
+  void assumption_NoFinalizableSubclass(JVMCIObject assumption);
+  void assumption_ConcreteSubtype(JVMCIObject assumption);
+  void assumption_LeafType(JVMCIObject assumption);
+  void assumption_ConcreteMethod(JVMCIObject assumption);
+  void assumption_CallSiteTargetValue(JVMCIObject assumption, JVMCI_TRAPS);
 
-  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_ExceptionHandler(jint pc_offset, Handle site);
+  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Infopoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Mark(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_ExceptionHandler(jint pc_offset, JVMCIObject site);
 
-  OopMap* create_oop_map(Handle debug_info, TRAPS);
+  OopMap* create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS);
+
+  VMReg getVMRegFromLocation(JVMCIObject location, int total_frame_size, JVMCI_TRAPS);
 
   /**
    * Specifies the level of detail to record for a scope.
@@ -260,23 +285,17 @@
   };
 
   int map_jvmci_bci(int bci);
-  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS);
-  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS) {
-    record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, THREAD);
+
+  void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, bool return_oop, JVMCI_TRAPS);
+  void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, JVMCI_TRAPS) {
+    record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, JVMCIENV);
   }
-  void record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS);
-  void record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+  void record_scope(jint pc_offset, JVMCIObject position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, JVMCI_TRAPS);
+  void record_object_value(ObjectValue* sv, JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS);
 
-  GrowableArray<ScopeValue*>* record_virtual_objects(Handle debug_info, TRAPS);
+  GrowableArray<ScopeValue*>* record_virtual_objects(JVMCIObject debug_info, JVMCI_TRAPS);
 
   int estimateStubSpace(int static_call_stubs);
 };
 
-/**
- * Gets the Method metaspace object from a HotSpotResolvedJavaMethodImpl Java object.
- */
-Method* getMethodFromHotSpotMethod(oop hotspot_method);
-
-
-
 #endif // SHARE_JVMCI_JVMCICODEINSTALLER_HPP
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri May 03 14:59:32 2019 -0400
@@ -22,18 +22,10 @@
  */
 
 #include "precompiled.hpp"
-#include "jvm.h"
-#include "memory/oopFactory.hpp"
-#include "memory/resourceArea.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/javaCalls.hpp"
-#include "runtime/handles.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciCompiler.hpp"
+#include "compiler/compileBroker.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "runtime/compilationPolicy.hpp"
-#include "runtime/globals_extension.hpp"
 #include "runtime/handles.inline.hpp"
 
 JVMCICompiler* JVMCICompiler::_instance = NULL;
@@ -103,121 +95,39 @@
     tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled);
   }
   _bootstrapping = false;
-  JVMCIRuntime::bootstrap_finished(CHECK);
+  JVMCI::compiler_runtime()->bootstrap_finished(CHECK);
 }
 
-#define CHECK_EXIT THREAD); \
-if (HAS_PENDING_EXCEPTION) { \
-  char buf[256]; \
-  jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
-  JVMCICompiler::exit_on_pending_exception(PENDING_EXCEPTION, buf); \
-  return; \
-} \
-(void)(0
-
-void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JVMCIEnv* env) {
-  JVMCI_EXCEPTION_CONTEXT
-
-  bool is_osr = entry_bci != InvocationEntryBci;
-  if (_bootstrapping && is_osr) {
-      // no OSR compilations during bootstrap - the compiler is just too slow at this point,
-      // and we know that there are no endless loops
-      env->set_failure(true, "No OSR during boostrap");
-      return;
+bool JVMCICompiler::force_comp_at_level_simple(Method *method) {
+  if (UseJVMCINativeLibrary) {
+    // This mechanism exists to force compilation of a JVMCI compiler by C1
+    // to reduces the compilation time spent on the JVMCI compiler itself. In
+    // +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled.
+    return false;
   }
 
-  JVMCIRuntime::initialize_well_known_classes(CHECK_EXIT);
-
-  HandleMark hm;
-  Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_EXIT);
-
-  JavaValue method_result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_long((jlong) (address) method());
-  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(),
-                         vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
-
-  JavaValue result(T_OBJECT);
-  if (!HAS_PENDING_EXCEPTION) {
-    JavaCallArguments args;
-    args.push_oop(receiver);
-    args.push_oop(Handle(THREAD, (oop)method_result.get_jobject()));
-    args.push_int(entry_bci);
-    args.push_long((jlong) (address) env);
-    args.push_int(env->task()->compile_id());
-    JavaCalls::call_special(&result, receiver->klass(),
-                            vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
+  if (_bootstrapping) {
+    // When bootstrapping, the JVMCI compiler can compile its own methods.
+    return false;
   }
 
-  // An uncaught exception was thrown during compilation.  Generally these
-  // should be handled by the Java code in some useful way but if they leak
-  // through to here report them instead of dying or silently ignoring them.
-  if (HAS_PENDING_EXCEPTION) {
-    Handle exception(THREAD, PENDING_EXCEPTION);
-    CLEAR_PENDING_EXCEPTION;
-
-    java_lang_Throwable::java_printStackTrace(exception, THREAD);
-    if (HAS_PENDING_EXCEPTION) {
-      CLEAR_PENDING_EXCEPTION;
-    }
-
-    env->set_failure(false, "unexpected exception thrown");
-  } else {
-    oop result_object = (oop) result.get_jobject();
-    if (result_object != NULL) {
-      oop failure_message = HotSpotCompilationRequestResult::failureMessage(result_object);
-      if (failure_message != NULL) {
-        // Copy failure reason into resource memory first ...
-        const char* failure_reason = java_lang_String::as_utf8_string(failure_message);
-        // ... and then into the C heap.
-        failure_reason = os::strdup(failure_reason, mtCompiler);
-        bool retryable = HotSpotCompilationRequestResult::retry(result_object) != 0;
-        env->set_failure(retryable, failure_reason, true);
-      } else {
-        if (env->task()->code() == NULL) {
-          env->set_failure(true, "no nmethod produced");
-        } else {
-          env->task()->set_num_inlined_bytecodes(HotSpotCompilationRequestResult::inlinedBytecodes(result_object));
-          Atomic::inc(&_methods_compiled);
+  JVMCIRuntime* runtime = JVMCI::compiler_runtime();
+  if (runtime != NULL && runtime->is_HotSpotJVMCIRuntime_initialized()) {
+    JavaThread* thread = JavaThread::current();
+    HandleMark hm(thread);
+    THREAD_JVMCIENV(thread);
+    JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(JVMCIENV);
+    objArrayHandle excludeModules(thread, HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(JVMCIENV, HotSpotJVMCI::resolve(receiver)));
+    if (excludeModules.not_null()) {
+      ModuleEntry* moduleEntry = method->method_holder()->module();
+      for (int i = 0; i < excludeModules->length(); i++) {
+        if (oopDesc::equals(excludeModules->obj_at(i), moduleEntry->module())) {
+          return true;
         }
       }
-    } else {
-      assert(false, "JVMCICompiler.compileMethod should always return non-null");
     }
   }
-  if (_bootstrapping) {
-    _bootstrap_compilation_request_handled = true;
-  }
-}
-
-CompLevel JVMCIRuntime::adjust_comp_level(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread) {
-  if (!thread->adjusting_comp_level()) {
-    thread->set_adjusting_comp_level(true);
-    level = adjust_comp_level_inner(method, is_osr, level, thread);
-    thread->set_adjusting_comp_level(false);
-  }
-  return level;
-}
-
-void JVMCICompiler::exit_on_pending_exception(oop exception, const char* message) {
-  JavaThread* THREAD = JavaThread::current();
-  CLEAR_PENDING_EXCEPTION;
-
-  static volatile int report_error = 0;
-  if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) {
-    // Only report an error once
-    tty->print_raw_cr(message);
-    Handle ex(THREAD, exception);
-    java_lang_Throwable::java_printStackTrace(ex, THREAD);
-  } else {
-    // Allow error reporting thread to print the stack trace.  Windows
-    // doesn't allow uninterruptible wait for JavaThreads
-    const bool interruptible = true;
-    os::sleep(THREAD, 200, interruptible);
-  }
-
-  before_exit(THREAD);
-  vm_exit(-1);
+  return false;
 }
 
 // Compilation entry point for methods
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,8 +25,6 @@
 #define SHARE_JVMCI_JVMCICOMPILER_HPP
 
 #include "compiler/abstractCompiler.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "utilities/exceptions.hpp"
 
 class JVMCICompiler : public AbstractCompiler {
 private:
@@ -65,7 +63,7 @@
     return _instance;
   }
 
-  virtual const char* name() { return "JVMCI"; }
+  virtual const char* name() { return UseJVMCINativeLibrary ? "JVMCI-native" : "JVMCI"; }
 
   virtual bool supports_native()                 { return true; }
   virtual bool supports_osr   ()                 { return true; }
@@ -85,13 +83,18 @@
    */
   void bootstrap(TRAPS);
 
+  // Should force compilation of method at CompLevel_simple?
+  bool force_comp_at_level_simple(Method* method);
+
   bool is_bootstrapping() const { return _bootstrapping; }
 
+  void set_bootstrap_compilation_request_handled() {
+    _instance->_bootstrap_compilation_request_handled = true;
+  }
+
   // Compilation entry point for methods
   virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
-  void compile_method(const methodHandle& target, int entry_bci, JVMCIEnv* env);
-
   // Print compilation timers and statistics
   virtual void print_timers();
 
@@ -101,6 +104,10 @@
    */
   int methods_compiled() { return _methods_compiled; }
 
+  void inc_methods_compiled() {
+    Atomic::inc(&_methods_compiled);
+  }
+
   // Print compilation timers and statistics
   static void print_compilation_timers();
 
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri May 03 14:59:32 2019 -0400
@@ -22,25 +22,25 @@
  */
 
 #include "precompiled.hpp"
-#include "ci/ciUtilities.inline.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
 #include "code/scopeDesc.hpp"
-#include "interpreter/linkResolver.hpp"
-#include "memory/oopFactory.hpp"
-#include "oops/cpCache.inline.hpp"
-#include "oops/generateOopMap.hpp"
-#include "oops/method.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
-#include "oops/typeArrayOop.inline.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/disassembler.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "interpreter/bytecodeStream.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
 #include "jvmci/jvmciRuntime.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/constantPool.inline.hpp"
+#include "oops/method.inline.hpp"
+#include "oops/typeArrayOop.inline.hpp"
+#include "prims/nativeLookup.hpp"
+#include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
-#include "runtime/flags/jvmFlag.hpp"
 #include "runtime/frame.inline.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/timerTrace.hpp"
@@ -87,38 +87,22 @@
   }
 }
 
-// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
-#define C2V_VMENTRY(result_type, name, signature) \
-  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
-  TRACE_jvmci_1("CompilerToVM::" #name); \
-  TRACE_CALL(result_type, jvmci_ ## name signature) \
-  JVMCI_VM_ENTRY_MARK; \
-
-#define C2V_END }
-
-oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) {
-  if (method() != NULL) {
-    JavaValue result(T_OBJECT);
-    JavaCallArguments args;
-    args.push_long((jlong) (address) method());
-    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_NULL);
+class JVMCITraceMark : public StackObj {
+  const char* _msg;
+ public:
+  JVMCITraceMark(const char* msg) {
+    _msg = msg;
+    if (JVMCITraceLevel >= 1) {
+      tty->print_cr(PTR_FORMAT " JVMCITrace-1: Enter %s", p2i(JavaThread::current()), _msg);
+    }
+  }
+  ~JVMCITraceMark() {
+    if (JVMCITraceLevel >= 1) {
+      tty->print_cr(PTR_FORMAT " JVMCITrace-1: Exit %s", p2i(JavaThread::current()), _msg);
+    }
+  }
+};
 
-    return (oop)result.get_jobject();
-  }
-  return NULL;
-}
-
-oop CompilerToVM::get_jvmci_type(JVMCIKlassHandle& klass, TRAPS) {
-  if (!klass.is_null()) {
-    JavaValue result(T_OBJECT);
-    JavaCallArguments args;
-    args.push_oop(Handle(THREAD, klass->java_mirror()));
-    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedObjectTypeImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::klass_fromMetaspace_signature(), &args, CHECK_NULL);
-
-    return (oop)result.get_jobject();
-  }
-  return NULL;
-}
 
 Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
   assert(_index < _args->length(), "out of bounds");
@@ -127,22 +111,32 @@
   return Handle(Thread::current(), arg);
 }
 
-jobjectArray readConfiguration0(JNIEnv *env, TRAPS);
+// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
+#define C2V_VMENTRY(result_type, name, signature)        \
+  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  JVMCITraceMark jtm("CompilerToVM::" #name);            \
+  TRACE_CALL(result_type, jvmci_ ## name signature)      \
+  JVMCI_VM_ENTRY_MARK;                                   \
+  ResourceMark rm;                                       \
+  JNI_JVMCIENV(env);
 
-C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
-   jobjectArray config = readConfiguration0(env, CHECK_NULL);
-   return config;
-C2V_END
+#define C2V_END }
+
+jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS);
 
-C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject c2vm, jobject name_handle))
-#define RETURN_BOXED_LONG(value) oop box; jvalue p; p.j = (jlong) (value); box = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
-#define RETURN_BOXED_DOUBLE(value) oop box; jvalue p; p.d = (jdouble) (value); box = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
-  Handle name(THREAD, JNIHandles::resolve(name_handle));
+C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv* env))
+  jobjectArray config = readConfiguration0(env, JVMCI_CHECK_NULL);
+  return config;
+}
+
+C2V_VMENTRY(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle))
+#define RETURN_BOXED_LONG(value) jvalue p; p.j = (jlong) (value); JVMCIObject box = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); return box.as_jobject();
+#define RETURN_BOXED_DOUBLE(value) jvalue p; p.d = (jdouble) (value); JVMCIObject box = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL); return box.as_jobject();
+  JVMCIObject name = JVMCIENV->wrap(name_handle);
   if (name.is_null()) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  ResourceMark rm;
-  const char* cstring = java_lang_String::as_utf8_string(name());
+  const char* cstring = JVMCIENV->as_utf8_string(name);
   JVMFlag* flag = JVMFlag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
   if (flag == NULL) {
     return c2vm;
@@ -150,11 +144,11 @@
   if (flag->is_bool()) {
     jvalue prim;
     prim.z = flag->get_bool();
-    oop box = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-    return JNIHandles::make_local(THREAD, box);
+    JVMCIObject box = JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(box);
   } else if (flag->is_ccstr()) {
-    Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
-    return JNIHandles::make_local(THREAD, value());
+    JVMCIObject value = JVMCIENV->create_string(flag->get_ccstr(), JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(value);
   } else if (flag->is_intx()) {
     RETURN_BOXED_LONG(flag->get_intx());
   } else if (flag->is_int()) {
@@ -176,12 +170,25 @@
 #undef RETURN_BOXED_DOUBLE
 C2V_END
 
-C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  ResourceMark rm;
+C2V_VMENTRY(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  if (oop_address == 0) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Handle must be non-zero");
+  }
+  oop obj = *((oopDesc**) oop_address);
+  if (obj != NULL) {
+    oopDesc::verify(obj);
+  }
+  return JNIHandles::make_local(obj);
+C2V_END
+
+C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
 
   int code_size = method->code_size();
-  typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
+  jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
 
   guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
   // iterate over all bytecodes and replace non-Java bytecodes
@@ -193,9 +200,9 @@
     int len = s.instruction_size();
 
     // Restore original byte code.
-    reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
+    reconstituted_code[bci] =  (jbyte) (s.is_wide()? Bytecodes::_wide : code);
     if (len > 1) {
-      memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
+      memcpy(reconstituted_code + (bci + 1), s.bcp()+1, len-1);
     }
 
     if (len > 1) {
@@ -211,14 +218,14 @@
         case Bytecodes::_invokestatic:
         case Bytecodes::_invokeinterface:
         case Bytecodes::_invokehandle: {
-          int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
-          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          int cp_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
+          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
           break;
         }
 
         case Bytecodes::_invokedynamic: {
-          int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
-          Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
+          int cp_index = Bytes::get_native_u4((address) reconstituted_code + (bci + 1));
+          Bytes::put_Java_u4((address) reconstituted_code + (bci + 1), (u4) cp_index);
           break;
         }
 
@@ -229,18 +236,18 @@
       // Not all ldc byte code are rewritten.
       switch (raw_code) {
         case Bytecodes::_fast_aldc: {
-          int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
+          int cpc_index = reconstituted_code[bci + 1] & 0xff;
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
+          reconstituted_code[bci + 1] = (jbyte) cp_index;
           break;
         }
 
         case Bytecodes::_fast_aldc_w: {
-          int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+          int cpc_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
           break;
         }
 
@@ -250,25 +257,29 @@
     }
   }
 
-  return (jbyteArray) JNIHandles::make_local(THREAD, reconstituted_code);
+  JVMCIPrimitiveArray result = JVMCIENV->new_byteArray(code_size, JVMCI_CHECK_NULL);
+  JVMCIENV->copy_bytes_from(reconstituted_code, result, 0, code_size);
+  return JVMCIENV->get_jbyteArray(result);
 C2V_END
 
-C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->exception_table_length();
 C2V_END
 
-C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   if (method->exception_table_length() == 0) {
     return 0L;
   }
   return (jlong) (address) method->exception_table_start();
 C2V_END
 
-C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv *, jobject, jobject executable_handle))
+C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+
   oop executable = JNIHandles::resolve(executable_handle);
   oop mirror = NULL;
   int slot = 0;
@@ -283,89 +294,101 @@
   }
   Klass* holder = java_lang_Class::as_Klass(mirror);
   methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot);
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv *, jobject, jobject base, jlong offset))
+C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
   methodHandle method;
-  oop base_object = JNIHandles::resolve(base);
-  if (base_object == NULL) {
+  JVMCIObject base_object = JVMCIENV->wrap(base);
+  if (base_object.is_null()) {
     method = *((Method**)(offset));
-  } else if (base_object->is_a(SystemDictionary::ResolvedMethodName_klass())) {
-    method = (Method*) (intptr_t) base_object->long_field(offset);
-  } else if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-    method = *((Method**)(HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object) + offset));
-  } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", base_object->klass()->external_name()));
+  } else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+    Handle obj = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+    if (obj->is_a(SystemDictionary::ResolvedMethodName_klass())) {
+      method = (Method*) (intptr_t) obj->long_field(offset);
+    } else {
+      JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", obj->klass()->external_name()));
+    }
+  } else if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
+    method = JVMCIENV->asMethod(base_object);
+  }
+  if (method.is_null()) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", JVMCIENV->klass_name(base_object)));
   }
   assert (method.is_null() || method->is_method(), "invalid read");
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle))
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle))
   constantPoolHandle cp;
-  oop object = JNIHandles::resolve(object_handle);
-  if (object == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  JVMCIObject object = JVMCIENV->wrap(object_handle);
+  if (object.is_null()) {
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-    cp = CompilerToVM::asMethod(object)->constMethod()->constants();
-  } else if (object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-    cp = InstanceKlass::cast(CompilerToVM::asKlass(object))->constants();
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(object)) {
+    cp = JVMCIENV->asMethod(object)->constMethod()->constants();
+  } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(object)) {
+    cp = InstanceKlass::cast(JVMCIENV->asKlass(object))->constants();
   } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", object->klass()->external_name()));
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                err_msg("Unexpected type: %s", JVMCIENV->klass_name(object)));
   }
   assert(!cp.is_null(), "npe");
-  JavaValue method_result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_long((jlong) (address) cp());
-  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+
+  JVMCIObject result = JVMCIENV->get_jvmci_constant_pool(cp, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
+C2V_VMENTRY(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
   JVMCIKlassHandle klass(THREAD);
-  oop base_object = JNIHandles::resolve(base);
+  JVMCIObject base_object = JVMCIENV->wrap(base);
   jlong base_address = 0;
-  if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) {
-    klass = base_object->klass();
+  if (base_object.is_non_null() && offset == oopDesc::klass_offset_in_bytes()) {
+    // klass = JVMCIENV->unhandle(base_object)->klass();
+    if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+      Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+      klass = base_oop->klass();
+    } else {
+      assert(false, "What types are we actually expecting here?");
+    }
   } else if (!compressed) {
-    if (base_object != NULL) {
-      if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-        base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
-      } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
-        base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
-      } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-        base_address = (jlong) CompilerToVM::asKlass(base_object);
-      } else if (base_object->is_a(SystemDictionary::Class_klass())) {
-        base_address = (jlong) (address) base_object;
-      } else {
-        THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+    if (base_object.is_non_null()) {
+      if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asMethod(base_object);
+      } else if (JVMCIENV->isa_HotSpotConstantPool(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asConstantPool(base_object);
+      } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asKlass(base_object);
+      } else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+        Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+        if (base_oop->is_a(SystemDictionary::Class_klass())) {
+          base_address = (jlong) (address) base_oop();
+        }
+      }
+      if (base_address == 0) {
+        JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", JVMCIENV->klass_name(base_object), offset, compressed ? "true" : "false"));
       }
     }
     klass = *((Klass**) (intptr_t) (base_address + offset));
   } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
                 err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s",
-                        base_object != NULL ? base_object->klass()->external_name() : "null",
+                        base_object.is_non_null() ? JVMCIENV->klass_name(base_object) : "null",
                         offset, compressed ? "true" : "false"));
   }
   assert (klass == NULL || klass->is_klass(), "invalid read");
-  oop result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  Klass* holder = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  Klass* holder = JVMCIENV->asKlass(jvmci_type);
   if (holder->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name()));
+    JVMCI_THROW_MSG_NULL(InternalError, err_msg("Interface %s should be handled in Java code", holder->external_name()));
   }
 
   methodHandle ucm;
@@ -373,12 +396,12 @@
     MutexLocker locker(Compile_lock);
     ucm = Dependencies::find_unique_concrete_method(holder, method());
   }
-  oop result = CompilerToVM::get_jvmci_method(ucm, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(ucm, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_interface()) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
         err_msg("Expected interface type, got %s", klass->external_name()));
@@ -390,48 +413,55 @@
     MutexLocker locker(Compile_lock);
     handle = iklass->implementor();
   }
-  oop implementor = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, implementor);
+  JVMCIObject implementor = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(implementor);
 C2V_END
 
-C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->is_ignored_by_security_stack_walk();
 C2V_END
 
-C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   constantPoolHandle cp = method->constMethod()->constants();
   assert(!cp.is_null(), "npe");
   // don't inline method when constant pool contains a CONSTANT_Dynamic
   return !method->is_not_compilable(CompLevel_full_optimization) && !cp->has_dynamic_constant();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline();
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return CompilerOracle::should_inline(method) || method->force_inline();
 C2V_END
 
-C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve))
-  ResourceMark rm;
-  Handle name(THREAD, JNIHandles::resolve(jname));
-  Symbol* class_name = java_lang_String::as_symbol(name(), CHECK_0);
-  if (java_lang_String::length(name()) <= 1) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
+C2V_VMENTRY(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve))
+  JVMCIObject name = JVMCIENV->wrap(jname);
+  const char* str = JVMCIENV->as_utf8_string(name);
+  TempNewSymbol class_name = SymbolTable::new_symbol(str, CHECK_NULL);
+
+  if (class_name->utf8_length() <= 1) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
   }
 
   JVMCIKlassHandle resolved_klass(THREAD);
-  if (JNIHandles::resolve(accessing_class) == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  Klass* accessing_klass = NULL;
+  Handle class_loader;
+  Handle protection_domain;
+  if (accessing_class != NULL) {
+    accessing_klass = JVMCIENV->asKlass(accessing_class);
+    class_loader = Handle(THREAD, accessing_klass->class_loader());
+    protection_domain = Handle(THREAD, accessing_klass->protection_domain());
+  } else {
+    // Use the System class loader
+    class_loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    JVMCIENV->runtime()->initialize(JVMCIENV);
   }
-  Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
-  Handle class_loader(THREAD, accessing_klass->class_loader());
-  Handle protection_domain(THREAD, accessing_klass->protection_domain());
 
   if (resolve) {
     resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
@@ -464,135 +494,166 @@
       } else {
         resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(t))->array_klass(fd.dimension(), CHECK_0);
       }
+    } else {
+      resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_0);
     }
   }
-  oop result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  if (mirror == NULL) {
+    return NULL;
+  }
+  JVMCIKlassHandle klass(THREAD);
+  klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
+  if (klass == NULL) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Primitive classes are unsupported");
+  }
+  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_constant_at(index, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->name_and_type_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
-  Handle sym = java_lang_String::create_from_symbol(cp->name_ref_at(which), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
+  JVMCIObject sym = JVMCIENV->create_string(cp->name_ref_at(which), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
-  Handle sym = java_lang_String::create_from_symbol(cp->signature_ref_at(which), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
+  JVMCIObject sym = JVMCIENV->create_string(cp->signature_ref_at(which), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->klass_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* klass = cp->klass_at(index, CHECK_NULL);
   JVMCIKlassHandle resolved_klass(THREAD, klass);
   if (resolved_klass->is_instance_klass()) {
-    InstanceKlass::cast(resolved_klass())->link_class_or_fail(THREAD);
+    bool linked = InstanceKlass::cast(resolved_klass())->link_class_or_fail(CHECK_NULL);
+    if (!linked) {
+      return NULL;
+    }
   }
-  oop jvmci_type = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, jvmci_type);
+  JVMCIObject klassObject = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(klassObject);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* loading_klass = cp->pool_holder();
   bool is_accessible = false;
-  JVMCIKlassHandle klass(THREAD, JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass));
+  JVMCIKlassHandle klass(THREAD, JVMCIRuntime::get_klass_by_index(cp, index, is_accessible, loading_klass));
   Symbol* symbol = NULL;
-  if (klass == NULL) {
-    symbol = cp->klass_name_at(index);
+  if (klass.is_null()) {
+    constantTag tag = cp->tag_at(index);
+    if (tag.is_klass()) {
+      // The klass has been inserted into the constant pool
+      // very recently.
+      klass = cp->resolved_klass_at(index);
+    } else if (tag.is_symbol()) {
+      symbol = cp->symbol_at(index);
+    } else {
+      assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
+      symbol = cp->klass_name_at(index);
+    }
   }
-  oop result_oop;
+  JVMCIObject result;
   if (!klass.is_null()) {
-    result_oop = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+    result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
   } else {
-    Handle result = java_lang_String::create_from_symbol(symbol, CHECK_NULL);
-    result_oop = result();
+    result = JVMCIENV->create_string(symbol, JVMCI_CHECK_NULL);
   }
-  return JNIHandles::make_local(THREAD, result_oop);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
-  return JNIHandles::make_local(THREAD, appendix_oop);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop));
 C2V_END
 
-C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   InstanceKlass* pool_holder = cp->pool_holder();
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
-  methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder);
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  methodHandle method = JVMCIRuntime::get_method_by_index(cp, index, bc, pool_holder);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->remap_instruction_operand_from_cache(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
-  ResourceMark rm;
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   fieldDescriptor fd;
-  LinkInfo link_info(cp, index, (jvmci_method != NULL) ? CompilerToVM::asMethod(jvmci_method) : NULL, CHECK_0);
+  LinkInfo link_info(cp, index, (jvmci_method != NULL) ? JVMCIENV->asMethod(jvmci_method) : NULL, CHECK_0);
   LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
-  typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
-  if (info == NULL || info->length() != 3) {
+  JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
+  if (info.is_null() || JVMCIENV->get_length(info) != 3) {
     JVMCI_ERROR_NULL("info must not be null and have a length of 3");
   }
-  info->int_at_put(0, fd.access_flags().as_int());
-  info->int_at_put(1, fd.offset());
-  info->int_at_put(2, fd.index());
+  JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int());
+  JVMCIENV->put_int_at(info, 1, fd.offset());
+  JVMCIENV->put_int_at(info, 2, fd.index());
   JVMCIKlassHandle handle(THREAD, fd.field_holder());
-  oop field_holder = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, field_holder);
+  JVMCIObject field_holder = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(field_holder);
 C2V_END
 
-C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
-  ResourceMark rm;
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (klass->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", klass->external_name()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Interface %s should be handled in Java code", klass->external_name()));
   }
   if (!method->method_holder()->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+  }
+  if (!klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
   }
   if (!InstanceKlass::cast(klass)->is_linked()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be linked", klass->external_name()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be linked", klass->external_name()));
   }
   return LinkResolver::vtable_index_of_interface_method(klass, method);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
-  Klass* recv_klass = CompilerToVM::asKlass(receiver_jvmci_type);
-  Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type);
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
+  Klass* recv_klass = JVMCIENV->asKlass(receiver_jvmci_type);
+  Klass* caller_klass = JVMCIENV->asKlass(caller_jvmci_type);
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
 
   Klass* resolved     = method->method_holder();
   Symbol* h_name      = method->name();
@@ -632,27 +693,27 @@
     return NULL;
   }
 
-  oop result = CompilerToVM::get_jvmci_method(m, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(m, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   assert(klass != NULL, "method must not be called for primitive types");
   return Dependencies::find_finalizable_subclass(klass) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
     return NULL;
   }
   InstanceKlass* iklass = InstanceKlass::cast(klass);
-  oop result = CompilerToVM::get_jvmci_method(iklass->class_initializer(), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(iklass->class_initializer(), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv*, jobject, jlong addr))
+C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr))
   address target_addr = (address) addr;
   if (target_addr != 0x0) {
     int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
@@ -662,166 +723,164 @@
   return -1;
 C2V_END
 
-C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv *, jobject,  jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv* env, jobject,  jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   method->set_not_c1_compilable();
   method->set_not_c2_compilable();
   method->set_dont_inline(true);
 C2V_END
 
-C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject installed_code, jobject speculation_log))
-  ResourceMark rm;
+C2V_VMENTRY(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code,
+            jobject installed_code, jlong failed_speculations_address, jbyteArray speculations_obj))
   HandleMark hm;
   JNIHandleMark jni_hm;
 
-  Handle target_handle(THREAD, JNIHandles::resolve(target));
-  Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code));
+  JVMCIObject target_handle = JVMCIENV->wrap(target);
+  JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
   CodeBlob* cb = NULL;
-  Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
-  Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log));
+  JVMCIObject installed_code_handle = JVMCIENV->wrap(installed_code);
+  JVMCIPrimitiveArray speculations_handle = JVMCIENV->wrap(speculations_obj);
+
+  int speculations_len = JVMCIENV->get_length(speculations_handle);
+  char* speculations = NEW_RESOURCE_ARRAY(char, speculations_len);
+  JVMCIENV->copy_bytes_to(speculations_handle, (jbyte*) speculations, 0, speculations_len);
 
   JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
 
   TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
-  bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0;
-  CodeInstaller installer(is_immutable_PIC);
-  JVMCIEnv::CodeInstallResult result = installer.install(compiler, target_handle, compiled_code_handle, cb, installed_code_handle, speculation_log_handle, CHECK_0);
+  bool is_immutable_PIC = JVMCIENV->get_HotSpotCompiledCode_isImmutablePIC(compiled_code_handle) > 0;
+
+  CodeInstaller installer(JVMCIENV, is_immutable_PIC);
+  JVMCI::CodeInstallResult result = installer.install(compiler,
+      target_handle,
+      compiled_code_handle,
+      cb,
+      installed_code_handle,
+      (FailedSpeculation**)(address) failed_speculations_address,
+      speculations,
+      speculations_len,
+      JVMCI_CHECK_0);
 
   if (PrintCodeCacheOnCompilation) {
     stringStream s;
-    // Dump code cache  into a buffer before locking the tty,
+    // Dump code cache into a buffer before locking the tty,
     {
-      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       CodeCache::print_summary(&s, false);
     }
     ttyLocker ttyl;
     tty->print_raw_cr(s.as_string());
   }
 
-  if (result != JVMCIEnv::ok) {
+  if (result != JVMCI::ok) {
     assert(cb == NULL, "should be");
   } else {
-    if (installed_code_handle.not_null()) {
-      assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
-      nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
-      {
-        // Ensure that all updates to the InstalledCode fields are consistent.
-        MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-        InstalledCode::set_address(installed_code_handle, (jlong) cb);
-        InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
-        if (cb->is_nmethod()) {
-          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point());
-        } else {
-          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin());
-        }
-        if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
-          HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
-          HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
-          HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
-        }
+    if (installed_code_handle.is_non_null()) {
+      if (cb->is_nmethod()) {
+        assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
+        // Clear the link to an old nmethod first
+        JVMCIObject nmethod_mirror = installed_code_handle;
+        JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK_0);
+      } else {
+        assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
       }
+      // Initialize the link to the new code blob
+      JVMCIENV->initialize_installed_code(installed_code_handle, cb, JVMCI_CHECK_0);
     }
   }
   return result;
 C2V_END
 
-C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject metadata))
+C2V_VMENTRY(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata))
 #if INCLUDE_AOT
-  ResourceMark rm;
   HandleMark hm;
+  assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
 
-  Handle target_handle(THREAD, JNIHandles::resolve(target));
-  Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code));
-  Handle metadata_handle(THREAD, JNIHandles::resolve(metadata));
+  JVMCIObject target_handle = JVMCIENV->wrap(target);
+  JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
+  JVMCIObject metadata_handle = JVMCIENV->wrap(metadata);
 
   CodeMetadata code_metadata;
-  CodeBlob *cb = NULL;
-  CodeInstaller installer(true /* immutable PIC compilation */);
 
-  JVMCIEnv::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, CHECK_0);
-  if (result != JVMCIEnv::ok) {
+  CodeInstaller installer(JVMCIENV, true /* immutable PIC compilation */);
+  JVMCI::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, JVMCI_CHECK_0);
+  if (result != JVMCI::ok) {
     return result;
   }
 
   if (code_metadata.get_nr_pc_desc() > 0) {
-    typeArrayHandle pcArrayOop = oopFactory::new_byteArray_handle(sizeof(PcDesc) * code_metadata.get_nr_pc_desc(), CHECK_(JVMCIEnv::cache_full));
-    memcpy(pcArrayOop->byte_at_addr(0), code_metadata.get_pc_desc(), sizeof(PcDesc) * code_metadata.get_nr_pc_desc());
-    HotSpotMetaData::set_pcDescBytes(metadata_handle, pcArrayOop());
+    int size = sizeof(PcDesc) * code_metadata.get_nr_pc_desc();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_pc_desc(), array, 0, size);
+    HotSpotJVMCI::HotSpotMetaData::set_pcDescBytes(JVMCIENV, metadata_handle, array);
   }
 
   if (code_metadata.get_scopes_size() > 0) {
-    typeArrayHandle scopesArrayOop = oopFactory::new_byteArray_handle(code_metadata.get_scopes_size(), CHECK_(JVMCIEnv::cache_full));
-    memcpy(scopesArrayOop->byte_at_addr(0), code_metadata.get_scopes_desc(), code_metadata.get_scopes_size());
-    HotSpotMetaData::set_scopesDescBytes(metadata_handle, scopesArrayOop());
+    int size = code_metadata.get_scopes_size();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_scopes_desc(), array, 0, size);
+    HotSpotJVMCI::HotSpotMetaData::set_scopesDescBytes(JVMCIENV, metadata_handle, array);
   }
 
   RelocBuffer* reloc_buffer = code_metadata.get_reloc_buffer();
-  typeArrayHandle relocArrayOop = oopFactory::new_byteArray_handle((int) reloc_buffer->size(), CHECK_(JVMCIEnv::cache_full));
-  if (reloc_buffer->size() > 0) {
-    memcpy(relocArrayOop->byte_at_addr(0), reloc_buffer->begin(), reloc_buffer->size());
-  }
-  HotSpotMetaData::set_relocBytes(metadata_handle, relocArrayOop());
+  int size = (int) reloc_buffer->size();
+  JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+  JVMCIENV->copy_bytes_from((jbyte*) reloc_buffer->begin(), array, 0, size);
+  HotSpotJVMCI::HotSpotMetaData::set_relocBytes(JVMCIENV, metadata_handle, array);
 
   const OopMapSet* oopMapSet = installer.oopMapSet();
   {
     ResourceMark mark;
     ImmutableOopMapBuilder builder(oopMapSet);
-    int oopmap_size = builder.heap_size();
-    typeArrayHandle oopMapArrayHandle = oopFactory::new_byteArray_handle(oopmap_size, CHECK_(JVMCIEnv::cache_full));
-    builder.generate_into((address) oopMapArrayHandle->byte_at_addr(0));
-    HotSpotMetaData::set_oopMaps(metadata_handle, oopMapArrayHandle());
+    int size = builder.heap_size();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    builder.generate_into((address) HotSpotJVMCI::resolve(array)->byte_at_addr(0));
+    HotSpotJVMCI::HotSpotMetaData::set_oopMaps(JVMCIENV, metadata_handle, array);
   }
 
   AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
 
   int nr_meta_refs = recorder->nr_meta_refs();
-  objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_refs, CHECK_(JVMCIEnv::cache_full));
-  objArrayHandle metadataArrayHandle(THREAD, metadataArray);
+  JVMCIObjectArray metadataArray = JVMCIENV->new_Object_array(nr_meta_refs, JVMCI_CHECK_(JVMCI::cache_full));
   for (int i = 0; i < nr_meta_refs; ++i) {
     jobject element = recorder->meta_element(i);
     if (element == NULL) {
-      return JVMCIEnv::cache_full;
+      return JVMCI::cache_full;
     }
-    metadataArrayHandle->obj_at_put(i, JNIHandles::resolve(element));
+    JVMCIENV->put_object_at(metadataArray, i, JVMCIENV->wrap(element));
   }
-  HotSpotMetaData::set_metadata(metadata_handle, metadataArrayHandle());
+  HotSpotJVMCI::HotSpotMetaData::set_metadata(JVMCIENV, metadata_handle, metadataArray);
 
   ExceptionHandlerTable* handler = code_metadata.get_exception_table();
   int table_size = handler->size_in_bytes();
-  typeArrayHandle exceptionArrayOop = oopFactory::new_byteArray_handle(table_size, CHECK_(JVMCIEnv::cache_full));
-
+  JVMCIPrimitiveArray exceptionArray = JVMCIENV->new_byteArray(table_size, JVMCI_CHECK_(JVMCI::cache_full));
   if (table_size > 0) {
-    handler->copy_bytes_to((address) exceptionArrayOop->byte_at_addr(0));
+    handler->copy_bytes_to((address) HotSpotJVMCI::resolve(exceptionArray)->byte_at_addr(0));
   }
-  HotSpotMetaData::set_exceptionBytes(metadata_handle, exceptionArrayOop());
+  HotSpotJVMCI::HotSpotMetaData::set_exceptionBytes(JVMCIENV, metadata_handle, exceptionArray);
 
   return result;
 #else
-  THROW_MSG_0(vmSymbols::java_lang_InternalError(), "unimplemented");
+  JVMCI_THROW_MSG_0(InternalError, "unimplemented");
 #endif
 C2V_END
 
-C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
+C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
   JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
   CompilerStatistics* stats = compiler->stats();
   stats->_standard.reset();
   stats->_osr.reset();
 C2V_END
 
-C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode))
   HandleMark hm;
 
   if (installedCode == NULL) {
-    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null");
+    JVMCI_THROW_MSG_NULL(NullPointerException, "installedCode is null");
   }
 
-  jlong codeBlob = InstalledCode::address(installedCode);
-  if (codeBlob == 0L) {
-    return NULL;
-  }
-
-  CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+  JVMCIObject installedCodeObject = JVMCIENV->wrap(installedCode);
+  CodeBlob* cb = JVMCIENV->asCodeBlob(installedCodeObject);
   if (cb == NULL) {
     return NULL;
   }
@@ -846,28 +905,32 @@
     return NULL;
   }
 
-  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result());
+  JVMCIObject result = JVMCIENV->create_string(st.as_string(), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv*, jobject, jobject jvmci_method, int bci))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci))
   HandleMark hm;
 
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, element);
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  JVMCIObject element = JVMCIENV->new_StackTraceElement(method, bci, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeInstalledCode, (JNIEnv*, jobject, jobject args, jobject hotspotInstalledCode))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod))
+  if (env != JavaThread::current()->jni_environment()) {
+    // The incoming arguments array would have to contain JavaConstants instead of regular objects
+    // and the return value would have to be wrapped as a JavaConstant.
+    JVMCI_THROW_MSG_NULL(InternalError, "Wrapping of arguments is currently unsupported");
+  }
+
   HandleMark hm;
 
-  jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
-  if (nmethodValue == 0L) {
-    THROW_NULL(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
+  nmethod* nm = JVMCIENV->asNmethod(nmethod_mirror);
+  if (nm == NULL) {
+    JVMCI_THROW_NULL(InvalidInstalledCodeException);
   }
-  nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
@@ -880,7 +943,7 @@
   if (jap.get_ret_type() == T_VOID) {
     return NULL;
   } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
-    return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
+    return JNIHandles::make_local((oop) result.get_jobject());
   } else {
     jvalue *value = (jvalue *) result.get_value_addr();
     // Narrow the value down if required (Important on big endian machines)
@@ -900,13 +963,13 @@
       default:
         break;
     }
-    oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL);
-    return JNIHandles::make_local(THREAD, o);
+    JVMCIObject o = JVMCIENV->create_box(jap.get_ret_type(), value, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(o);
   }
 C2V_END
 
-C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv *, jobject, jobject jvmci_method))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_linenumber_table()) {
     return NULL;
   }
@@ -917,38 +980,36 @@
   }
 
   CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
-  typeArrayOop result = oopFactory::new_longArray(2 * num_entries, CHECK_NULL);
+  JVMCIPrimitiveArray result = JVMCIENV->new_longArray(2 * num_entries, JVMCI_CHECK_NULL);
 
   int i = 0;
   jlong value;
   while (stream.read_pair()) {
     value = ((long) stream.bci());
-    result->long_at_put(i, value);
+    JVMCIENV->put_long_at(result, i, value);
     value = ((long) stream.line());
-    result->long_at_put(i + 1, value);
+    JVMCIENV->put_long_at(result, i + 1, value);
     i += 2;
   }
 
-  return (jlongArray) JNIHandles::make_local(THREAD, result);
+  return (jlongArray) JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_localvariable_table()) {
     return 0;
   }
   return (jlong) (address) method->localvariable_table_start();
 C2V_END
 
-C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->localvariable_table_length();
 C2V_END
 
-C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jobject jvmci_method))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   MethodCounters* mcs = method->method_counters();
   if (mcs != NULL) {
     mcs->clear_counters();
@@ -971,52 +1032,56 @@
 C2V_END
 
 
-C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code))
-  Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
-  nmethod::invalidate_installed_code(installed_code_handle, CHECK);
+C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod))
+  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
+  JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK);
 C2V_END
 
-C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv*, jobject))
-  typeArrayOop arrayOop = oopFactory::new_longArray(JVMCICounterSize, CHECK_NULL);
-  JavaThread::collect_counters(arrayOop);
-  return (jlongArray) JNIHandles::make_local(THREAD, arrayOop);
+C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr))
+  oop ret = RawAccess<>::oop_load((oop*)(address)addr);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(ret));
+ C2V_END
+
+C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv* env, jobject))
+  JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL);
+  JavaThread::collect_counters(JVMCIENV, array);
+  return (jlongArray) JVMCIENV->get_jobject(array);
 C2V_END
 
-C2V_VMENTRY(int, allocateCompileId, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci))
+C2V_VMENTRY(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci))
   HandleMark hm;
-  ResourceMark rm;
-  if (JNIHandles::resolve(jvmci_method) == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  if (jvmci_method == NULL) {
+    JVMCI_THROW_0(NullPointerException);
   }
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (entry_bci >= method->code_size() || entry_bci < -1) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Unexpected bci %d", entry_bci));
+    JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Unexpected bci %d", entry_bci));
   }
   return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
 C2V_END
 
 
-C2V_VMENTRY(jboolean, isMature, (JNIEnv*, jobject, jlong metaspace_method_data))
-  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+C2V_VMENTRY(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data))
+  MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   return mdo != NULL && mdo->is_mature();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci, int comp_level))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getSymbol, (JNIEnv*, jobject, jlong symbol))
-  Handle sym = java_lang_String::create_from_symbol((Symbol*)(address)symbol, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol))
+  JVMCIObject sym = JVMCIENV->create_string((Symbol*)(address)symbol, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-bool matches(jobjectArray methods, Method* method) {
+bool matches(jobjectArray methods, Method* method, JVMCIEnv* JVMCIENV) {
   objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
 
   for (int i = 0; i < methods_oop->length(); i++) {
     oop resolved = methods_oop->obj_at(i);
-    if (resolved->is_a(HotSpotResolvedJavaMethodImpl::klass()) && CompilerToVM::asMethod(resolved) == method) {
+    if ((resolved->klass() == HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass()) && HotSpotJVMCI::asMethod(JVMCIENV, resolved) == method) {
       return true;
     }
   }
@@ -1037,18 +1102,21 @@
   JavaCalls::call(result, method, args, CHECK);
 }
 
-C2V_VMENTRY(jobject, iterateFrames, (JNIEnv*, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
 
   if (!thread->has_last_Java_frame()) {
     return NULL;
   }
   Handle visitor(THREAD, JNIHandles::resolve_non_null(visitor_handle));
-  Handle frame_reference = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
-  HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
+  }
+
+  HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+  Handle frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
 
   StackFrameStream fst(thread);
-
   jobjectArray methods = initial_methods;
 
   int frame_number = 0;
@@ -1062,7 +1130,7 @@
       if (vf->is_compiled_frame()) {
         // compiled method frame
         compiledVFrame* cvf = compiledVFrame::cast(vf);
-        if (methods == NULL || matches(methods, cvf->method())) {
+        if (methods == NULL || matches(methods, cvf->method(), JVMCIENV)) {
           if (initialSkip > 0) {
             initialSkip--;
           } else {
@@ -1096,29 +1164,29 @@
                   array->bool_at_put(i, true);
                 }
               }
-              HotSpotStackFrameReference::set_localIsVirtual(frame_reference, array());
+              HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), array());
             } else {
-              HotSpotStackFrameReference::set_localIsVirtual(frame_reference, NULL);
+              HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), NULL);
             }
 
             locals = cvf->locals();
-            HotSpotStackFrameReference::set_bci(frame_reference, cvf->bci());
-            oop method = CompilerToVM::get_jvmci_method(cvf->method(), CHECK_NULL);
-            HotSpotStackFrameReference::set_method(frame_reference, method);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_bci(JVMCIENV, frame_reference(), cvf->bci());
+            JVMCIObject method = JVMCIENV->get_jvmci_method(cvf->method(), JVMCI_CHECK_NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_method(JVMCIENV, frame_reference(), JNIHandles::resolve(method.as_jobject()));
           }
         }
       } else if (vf->is_interpreted_frame()) {
         // interpreted method frame
         interpretedVFrame* ivf = interpretedVFrame::cast(vf);
-        if (methods == NULL || matches(methods, ivf->method())) {
+        if (methods == NULL || matches(methods, ivf->method(), JVMCIENV)) {
           if (initialSkip > 0) {
             initialSkip--;
           } else {
             locals = ivf->locals();
-            HotSpotStackFrameReference::set_bci(frame_reference, ivf->bci());
-            oop method = CompilerToVM::get_jvmci_method(ivf->method(), CHECK_NULL);
-            HotSpotStackFrameReference::set_method(frame_reference, method);
-            HotSpotStackFrameReference::set_localIsVirtual(frame_reference, NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_bci(JVMCIENV, frame_reference(), ivf->bci());
+            JVMCIObject method = JVMCIENV->get_jvmci_method(ivf->method(), JVMCI_CHECK_NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_method(JVMCIENV, frame_reference(), JNIHandles::resolve(method.as_jobject()));
+            HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), NULL);
           }
         }
       }
@@ -1126,9 +1194,9 @@
       // locals != NULL means that we found a matching frame and result is already partially initialized
       if (locals != NULL) {
         methods = match_methods;
-        HotSpotStackFrameReference::set_compilerToVM(frame_reference, JNIHandles::resolve(compilerToVM));
-        HotSpotStackFrameReference::set_stackPointer(frame_reference, (jlong) fst.current()->sp());
-        HotSpotStackFrameReference::set_frameNumber(frame_reference, frame_number);
+        HotSpotJVMCI::HotSpotStackFrameReference::set_compilerToVM(JVMCIENV, frame_reference(), JNIHandles::resolve(compilerToVM));
+        HotSpotJVMCI::HotSpotStackFrameReference::set_stackPointer(JVMCIENV, frame_reference(), (jlong) fst.current()->sp());
+        HotSpotJVMCI::HotSpotStackFrameReference::set_frameNumber(JVMCIENV, frame_reference(), frame_number);
 
         // initialize the locals array
         objArrayOop array_oop = oopFactory::new_objectArray(locals->size(), CHECK_NULL);
@@ -1139,20 +1207,20 @@
             array->obj_at_put(i, locals->at(i)->get_obj()());
           }
         }
-        HotSpotStackFrameReference::set_locals(frame_reference, array());
-        HotSpotStackFrameReference::set_objectsMaterialized(frame_reference, JNI_FALSE);
+        HotSpotJVMCI::HotSpotStackFrameReference::set_locals(JVMCIENV, frame_reference(), array());
+        HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, frame_reference(), JNI_FALSE);
 
         JavaValue result(T_OBJECT);
         JavaCallArguments args(visitor);
         args.push_oop(frame_reference);
-        call_interface(&result, SystemDictionary::InspectedFrameVisitor_klass(), vmSymbols::visitFrame_name(), vmSymbols::visitFrame_signature(), &args, CHECK_NULL);
+        call_interface(&result, HotSpotJVMCI::InspectedFrameVisitor::klass(), vmSymbols::visitFrame_name(), vmSymbols::visitFrame_signature(), &args, CHECK_NULL);
         if (result.get_jobject() != NULL) {
           return JNIHandles::make_local(thread, (oop) result.get_jobject());
         }
         assert(initialSkip == 0, "There should be no match before initialSkip == 0");
-        if (HotSpotStackFrameReference::objectsMaterialized(frame_reference) == JNI_TRUE) {
+        if (HotSpotJVMCI::HotSpotStackFrameReference::objectsMaterialized(JVMCIENV, frame_reference()) == JNI_TRUE) {
           // the frame has been deoptimized, we need to re-synchronize the frame and vframe
-          intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(frame_reference);
+          intptr_t* stack_pointer = (intptr_t*) HotSpotJVMCI::HotSpotStackFrameReference::stackPointer(JVMCIENV, frame_reference());
           fst = StackFrameStream(thread);
           while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
             fst.next();
@@ -1172,8 +1240,8 @@
             assert(vf->is_compiled_frame(), "Wrong frame type");
           }
         }
-        frame_reference = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
-        HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+        frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
+        HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
       }
 
       if (vf->is_top()) {
@@ -1195,16 +1263,16 @@
   return NULL;
 C2V_END
 
-C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   CallInfo callInfo;
   LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokedynamic, CHECK);
   ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
   cp_cache_entry->set_dynamic_call(cp, callInfo);
 C2V_END
 
-C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* holder = cp->klass_ref_at(index, CHECK);
   Symbol* name = cp->name_ref_at(index);
   if (MethodHandles::is_signature_polymorphic_name(holder, name)) {
@@ -1215,8 +1283,8 @@
   }
 C2V_END
 
-C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
   if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
     // MethodHandle.invoke* --> LambdaForm?
@@ -1256,16 +1324,16 @@
 C2V_END
 
 
-C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject))
-  objArrayHandle holders = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), 2, CHECK_NULL);
-  Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL);
-  Handle vh = java_lang_String::create_from_str("Ljava/lang/invoke/VarHandle;", CHECK_NULL);
-  holders->obj_at_put(0, mh());
-  holders->obj_at_put(1, vh());
-  return JNIHandles::make_local(THREAD, holders());
+C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject))
+  JVMCIObjectArray holders = JVMCIENV->new_String_array(2, JVMCI_CHECK_NULL);
+  JVMCIObject mh = JVMCIENV->create_string("Ljava/lang/invoke/MethodHandle;", JVMCI_CHECK_NULL);
+  JVMCIObject vh = JVMCIENV->create_string("Ljava/lang/invoke/VarHandle;", JVMCI_CHECK_NULL);
+  JVMCIENV->put_object_at(holders, 0, mh);
+  JVMCIENV->put_object_at(holders, 1, vh);
+  return JVMCIENV->get_jobject(holders);
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
+C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject))
   //see compute_recording_non_safepoints in debugInfroRec.cpp
   if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
     return true;
@@ -1274,28 +1342,31 @@
 C2V_END
 
 // public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
-C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate))
-  ResourceMark rm;
-
-  if (hs_frame == NULL) {
-    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
+C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_frame, bool invalidate))
+  JVMCIObject hs_frame = JVMCIENV->wrap(_hs_frame);
+  if (hs_frame.is_null()) {
+    JVMCI_THROW_MSG(NullPointerException, "stack frame is null");
   }
 
-  HotSpotStackFrameReference::klass()->initialize(CHECK);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
+  }
+
+  JVMCIENV->HotSpotStackFrameReference_initialize(JVMCI_CHECK);
 
   // look for the given stack frame
   StackFrameStream fst(thread);
-  intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+  intptr_t* stack_pointer = (intptr_t*) JVMCIENV->get_HotSpotStackFrameReference_stackPointer(hs_frame);
   while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
     fst.next();
   }
   if (fst.current()->sp() != stack_pointer) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+    JVMCI_THROW_MSG(IllegalStateException, "stack frame not found");
   }
 
   if (invalidate) {
     if (!fst.current()->is_compiled_frame()) {
-      THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+      JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
     }
     assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
     ((nmethod*) fst.current()->cb())->make_not_entrant();
@@ -1307,12 +1378,12 @@
     fstAfterDeopt.next();
   }
   if (fstAfterDeopt.current()->sp() != stack_pointer) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found after deopt")
+    JVMCI_THROW_MSG(IllegalStateException, "stack frame not found after deopt");
   }
 
   vframe* vf = vframe::new_vframe(fstAfterDeopt.current(), fstAfterDeopt.register_map(), thread);
   if (!vf->is_compiled_frame()) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+    JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
   }
 
   GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
@@ -1325,9 +1396,9 @@
     vf = vf->sender();
   }
 
-  int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+  int last_frame_number = JVMCIENV->get_HotSpotStackFrameReference_frameNumber(hs_frame);
   if (last_frame_number >= virtualFrames->length()) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+    JVMCI_THROW_MSG(IllegalStateException, "invalid frame number");
   }
 
   // Reallocate the non-escaping objects and restore their fields.
@@ -1381,49 +1452,50 @@
   }
 
   // all locals are materialized by now
-  HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
-
+  JVMCIENV->set_HotSpotStackFrameReference_localIsVirtual(hs_frame, NULL);
   // update the locals array
-  objArrayHandle array(THREAD, HotSpotStackFrameReference::locals(hs_frame));
+  JVMCIObjectArray array = JVMCIENV->get_HotSpotStackFrameReference_locals(hs_frame);
   StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
   for (int i = 0; i < locals->size(); i++) {
     StackValue* var = locals->at(i);
     if (var->type() == T_OBJECT) {
-      array->obj_at_put(i, locals->at(i)->get_obj()());
+      JVMCIENV->put_object_at(array, i, HotSpotJVMCI::wrap(locals->at(i)->get_obj()()));
     }
   }
-  HotSpotStackFrameReference::set_objectsMaterialized(hs_frame, JNI_TRUE);
+  HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE);
 C2V_END
 
-C2V_VMENTRY(void, writeDebugOutput, (JNIEnv*, jobject, jbyteArray bytes, jint offset, jint length))
+C2V_VMENTRY(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
   if (bytes == NULL) {
-    THROW(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW(NullPointerException);
   }
-  typeArrayOop array = (typeArrayOop) JNIHandles::resolve(bytes);
+  JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes);
 
   // Check if offset and length are non negative.
   if (offset < 0 || length < 0) {
-    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+    JVMCI_THROW(ArrayIndexOutOfBoundsException);
   }
   // Check if the range is valid.
-  if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array->length())) {
-    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+  int array_length = JVMCIENV->get_length(array);
+  if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) {
+    JVMCI_THROW(ArrayIndexOutOfBoundsException);
   }
+  jbyte buffer[O_BUFLEN];
   while (length > 0) {
-    jbyte* start = array->byte_at_addr(offset);
-    tty->write((char*) start, MIN2(length, (jint)O_BUFLEN));
+    int copy_len = MIN2(length, (jint)O_BUFLEN);
+    JVMCIENV->copy_bytes_to(array, buffer, offset, copy_len);
+    tty->write((char*) buffer, copy_len);
     length -= O_BUFLEN;
     offset += O_BUFLEN;
   }
 C2V_END
 
-C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
+C2V_VMENTRY(void, flushDebugOutput, (JNIEnv* env, jobject))
   tty->flush();
 C2V_END
 
-C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv*, jobject, jlong metaspace_method_data, jint position))
-  ResourceMark rm;
-  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position))
+  MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   ProfileData* profile_data = mdo->data_at(position);
   if (mdo->is_valid(profile_data)) {
     return profile_data->size_in_bytes();
@@ -1437,48 +1509,115 @@
       return profile_data->size_in_bytes();
     }
   }
-  THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
+  JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Invalid profile data position %d", position));
 C2V_END
 
-C2V_VMENTRY(jlong, getFingerprint, (JNIEnv*, jobject, jlong metaspace_klass))
+C2V_VMENTRY(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass))
 #if INCLUDE_AOT
-  Klass *k = CompilerToVM::asKlass(metaspace_klass);
+  Klass *k = (Klass*) (address) metaspace_klass;
   if (k->is_instance_klass()) {
     return InstanceKlass::cast(k)->get_stored_fingerprint();
   } else {
     return 0;
   }
 #else
-  THROW_MSG_0(vmSymbols::java_lang_InternalError(), "unimplemented");
+  JVMCI_THROW_MSG_0(InternalError, "unimplemented");
 #endif
 C2V_END
 
-C2V_VMENTRY(jobject, getHostClass, (JNIEnv*, jobject, jobject jvmci_type))
-  InstanceKlass* k = InstanceKlass::cast(CompilerToVM::asKlass(jvmci_type));
+C2V_VMENTRY(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type))
+  InstanceKlass* k = InstanceKlass::cast(JVMCIENV->asKlass(jvmci_type));
   InstanceKlass* host = k->unsafe_anonymous_host();
   JVMCIKlassHandle handle(THREAD, host);
-  oop result = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  if (klass == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  if (!klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
+  }
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+
+  // Regular instance klass, fill in all local interfaces
+  int size = iklass->local_interfaces()->length();
+  JVMCIObjectArray interfaces = JVMCIENV->new_HotSpotResolvedObjectTypeImpl_array(size, JVMCI_CHECK_NULL);
+  for (int index = 0; index < size; index++) {
+    JVMCIKlassHandle klass(THREAD);
+    Klass* k = iklass->local_interfaces()->at(index);
+    klass = k;
+    JVMCIObject type = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(interfaces, index, type);
+  }
+  return JVMCIENV->get_jobject(interfaces);
 C2V_END
 
-C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle))
-  if (bytecode_frame_handle == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+C2V_VMENTRY(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  oop mirror = klass->java_mirror();
+  if (java_lang_Class::is_primitive(mirror) ||
+      !java_lang_Class::as_Klass(mirror)->is_array_klass()) {
+    return NULL;
   }
 
-  oop top_bytecode_frame = JNIHandles::resolve_non_null(bytecode_frame_handle);
-  oop bytecode_frame = top_bytecode_frame;
+  oop component_mirror = java_lang_Class::component_mirror(mirror);
+  if (component_mirror == NULL) {
+    return NULL;
+  }
+  Klass* component_klass = java_lang_Class::as_Klass(component_mirror);
+  if (component_klass != NULL) {
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = component_klass;
+    JVMCIObject result = JVMCIENV->get_jvmci_type(klass_handle, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(result);
+  }
+  BasicType type = java_lang_Class::primitive_type(component_mirror);
+  JVMCIObject result = JVMCIENV->get_jvmci_primitive_type(type);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(void, ensureInitialized, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  if (klass != NULL && klass->should_be_initialized()) {
+    InstanceKlass* k = InstanceKlass::cast(klass);
+    k->initialize(CHECK);
+  }
+C2V_END
+
+C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle))
+  if (bytecode_frame_handle == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  JVMCIObject top_bytecode_frame = JVMCIENV->wrap(bytecode_frame_handle);
+  JVMCIObject bytecode_frame = top_bytecode_frame;
   int size = 0;
   int callee_parameters = 0;
   int callee_locals = 0;
-  Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
-  int extra_args = method->max_stack() - BytecodeFrame::numStack(bytecode_frame);
+  Method* method = JVMCIENV->asMethod(JVMCIENV->get_BytecodePosition_method(bytecode_frame));
+  int extra_args = method->max_stack() - JVMCIENV->get_BytecodeFrame_numStack(bytecode_frame);
 
-  while (bytecode_frame != NULL) {
-    int locks = BytecodeFrame::numLocks(bytecode_frame);
-    int temps = BytecodeFrame::numStack(bytecode_frame);
-    bool is_top_frame = (bytecode_frame == top_bytecode_frame);
-    Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+  while (bytecode_frame.is_non_null()) {
+    int locks = JVMCIENV->get_BytecodeFrame_numLocks(bytecode_frame);
+    int temps = JVMCIENV->get_BytecodeFrame_numStack(bytecode_frame);
+    bool is_top_frame = (JVMCIENV->equals(bytecode_frame, top_bytecode_frame));
+    Method* method = JVMCIENV->asMethod(JVMCIENV->get_BytecodePosition_method(bytecode_frame));
 
     int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(),
                                                                  temps + callee_parameters,
@@ -1492,48 +1631,652 @@
     callee_parameters = method->size_of_parameters();
     callee_locals = method->max_locals();
     extra_args = 0;
-    bytecode_frame = BytecodePosition::caller(bytecode_frame);
+    bytecode_frame = JVMCIENV->get_BytecodePosition_caller(bytecode_frame);
   }
   return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord;
 C2V_END
 
-C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_handle))
-  Handle lambda_form(THREAD, JNIHandles::resolve_non_null(lambda_form_handle));
+C2V_VMENTRY(void, compileToBytecode, (JNIEnv* env, jobject, jobject lambda_form_handle))
+  Handle lambda_form = JVMCIENV->asConstant(JVMCIENV->wrap(lambda_form_handle), JVMCI_CHECK);
   if (lambda_form->is_a(SystemDictionary::LambdaForm_klass())) {
     TempNewSymbol compileToBytecode = SymbolTable::new_symbol("compileToBytecode", CHECK);
     JavaValue result(T_VOID);
     JavaCalls::call_special(&result, lambda_form, SystemDictionary::LambdaForm_klass(), compileToBytecode, vmSymbols::void_method_signature(), CHECK);
   } else {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", lambda_form->klass()->external_name()));
+    JVMCI_THROW_MSG(IllegalArgumentException,
+                    err_msg("Unexpected type: %s", lambda_form->klass()->external_name()))
   }
 C2V_END
 
+C2V_VMENTRY(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object))
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  return obj->identity_hash();
+C2V_END
+
+C2V_VMENTRY(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object))
+  Handle str = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  if (!java_lang_String::is_instance(str())) {
+    return false;
+  }
+  int len;
+  jchar* name = java_lang_String::as_unicode_string(str(), len, CHECK_0);
+  return (StringTable::lookup(name, len) != NULL);
+C2V_END
+
+
+C2V_VMENTRY(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle box = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  BasicType type = java_lang_boxing_object::basic_type(box());
+  jvalue result;
+  if (java_lang_boxing_object::get_value(box(), &result) == T_ILLEGAL) {
+    return NULL;
+  }
+  JVMCIObject boxResult = JVMCIENV->create_box(type, &result, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(boxResult);
+C2V_END
+
+C2V_VMENTRY(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject box = JVMCIENV->wrap(object);
+  BasicType type = JVMCIENV->get_box_type(box);
+  if (type == T_ILLEGAL) {
+    return NULL;
+  }
+  jvalue value = JVMCIENV->get_boxed_value(type, box);
+  JavaValue box_result(T_OBJECT);
+  JavaCallArguments jargs;
+  Klass* box_klass = NULL;
+  Symbol* box_signature = NULL;
+#define BOX_CASE(bt, v, argtype, name)           \
+  case bt: \
+    jargs.push_##argtype(value.v); \
+    box_klass = SystemDictionary::name##_klass(); \
+    box_signature = vmSymbols::name##_valueOf_signature(); \
+    break
+
+  switch (type) {
+    BOX_CASE(T_BOOLEAN, z, int, Boolean);
+    BOX_CASE(T_BYTE, b, int, Byte);
+    BOX_CASE(T_CHAR, c, int, Character);
+    BOX_CASE(T_SHORT, s, int, Short);
+    BOX_CASE(T_INT, i, int, Integer);
+    BOX_CASE(T_LONG, j, long, Long);
+    BOX_CASE(T_FLOAT, f, float, Float);
+    BOX_CASE(T_DOUBLE, d, double, Double);
+    default:
+      ShouldNotReachHere();
+  }
+#undef BOX_CASE
+
+  JavaCalls::call_static(&box_result,
+                         box_klass,
+                         vmSymbols::valueOf_name(),
+                         box_signature, &jargs, CHECK_NULL);
+  oop hotspot_box = (oop) box_result.get_jobject();
+  JVMCIObject result = JVMCIENV->get_object_constant(hotspot_box, false);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(holder);
+  if (!klass->is_instance_klass()) {
+    JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobjectArray(methods);
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  // Ensure class is linked
+  iklass->link_class(CHECK_NULL);
+
+  GrowableArray<Method*> constructors_array;
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* m = iklass->methods()->at(i);
+    if (m->is_initializer() && !m->is_static()) {
+      constructors_array.append(m);
+    }
+  }
+  JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(constructors_array.length(), JVMCI_CHECK_NULL);
+  for (int i = 0; i < constructors_array.length(); i++) {
+    JVMCIObject method = JVMCIENV->get_jvmci_method(constructors_array.at(i), JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(methods, i, method);
+  }
+  return JVMCIENV->get_jobjectArray(methods);
+C2V_END
+
+C2V_VMENTRY(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(holder);
+  if (!klass->is_instance_klass()) {
+    JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobjectArray(methods);
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  // Ensure class is linked
+  iklass->link_class(CHECK_NULL);
+
+  GrowableArray<Method*> methods_array;
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* m = iklass->methods()->at(i);
+    if (!m->is_initializer() && !m->is_overpass()) {
+      methods_array.append(m);
+    }
+  }
+  JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(methods_array.length(), JVMCI_CHECK_NULL);
+  for (int i = 0; i < methods_array.length(); i++) {
+    JVMCIObject method = JVMCIENV->get_jvmci_method(methods_array.at(i), JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(methods, i, method);
+  }
+  return JVMCIENV->get_jobjectArray(methods);
+C2V_END
+
+C2V_VMENTRY(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile))
+  if (object == NULL || field == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject field_object = JVMCIENV->wrap(field);
+  JVMCIObject java_type = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_type(field_object);
+  int modifiers = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_modifiers(field_object);
+  Klass* holder = JVMCIENV->asKlass(JVMCIENV->get_HotSpotResolvedJavaFieldImpl_holder(field_object));
+  if (!holder->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Holder %s must be instance klass", holder->external_name()));
+  }
+  InstanceKlass* ik = InstanceKlass::cast(holder);
+  BasicType constant_type;
+  if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(java_type)) {
+    constant_type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(java_type), JVMCI_CHECK_NULL);
+  } else {
+    constant_type = T_OBJECT;
+  }
+  int displacement = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_offset(field_object);
+  fieldDescriptor fd;
+  if (!ik->find_local_field_from_offset(displacement, (modifiers & JVM_ACC_STATIC) != 0, &fd)) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Can't find field with displacement %d", displacement));
+  }
+  JVMCIObject base = JVMCIENV->wrap(object);
+  Handle obj;
+  if (JVMCIENV->isa_HotSpotObjectConstantImpl(base)) {
+    obj = JVMCIENV->asConstant(base, JVMCI_CHECK_NULL);
+  } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base)) {
+    Klass* klass = JVMCIENV->asKlass(base);
+    obj = Handle(THREAD, klass->java_mirror());
+  } else {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                         err_msg("Unexpected type: %s", JVMCIENV->klass_name(base)));
+  }
+  jlong value = 0;
+  JVMCIObject kind;
+  switch (constant_type) {
+    case T_OBJECT: {
+      oop object = is_volatile ? obj->obj_field_acquire(displacement) : obj->obj_field(displacement);
+      JVMCIObject result = JVMCIENV->get_object_constant(object);
+      if (result.is_null()) {
+        return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
+      }
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_FLOAT: {
+      float f = is_volatile ? obj->float_field_acquire(displacement) : obj->float_field(displacement);
+      JVMCIObject result = JVMCIENV->call_JavaConstant_forFloat(f, JVMCI_CHECK_NULL);
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_DOUBLE: {
+      double f = is_volatile ? obj->double_field_acquire(displacement) : obj->double_field(displacement);
+      JVMCIObject result = JVMCIENV->call_JavaConstant_forDouble(f, JVMCI_CHECK_NULL);
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_BOOLEAN: value = is_volatile ? obj->bool_field_acquire(displacement) : obj->bool_field(displacement); break;
+    case T_BYTE: value = is_volatile ? obj->byte_field_acquire(displacement) : obj->byte_field(displacement); break;
+    case T_SHORT: value = is_volatile ? obj->short_field_acquire(displacement) : obj->short_field(displacement); break;
+    case T_CHAR: value = is_volatile ? obj->char_field_acquire(displacement) : obj->char_field(displacement); break;
+    case T_INT: value = is_volatile ? obj->int_field_acquire(displacement) : obj->int_field(displacement); break;
+    case T_LONG: value = is_volatile ? obj->long_field_acquire(displacement) : obj->long_field(displacement); break;
+    default:
+      ShouldNotReachHere();
+  }
+  JVMCIObject result = JVMCIENV->call_PrimitiveConstant_forTypeChar(type2char(constant_type), value, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object))
+  if (object == NULL || holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  Klass* klass = JVMCIENV->asKlass(JVMCIENV->wrap(holder));
+  return obj->is_a(klass);
+C2V_END
+
+C2V_VMENTRY(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder))
+  if (holder == NULL || otherHolder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(JVMCIENV->wrap(holder));
+  Klass* otherKlass = JVMCIENV->asKlass(JVMCIENV->wrap(otherHolder));
+  return otherKlass->is_subtype_of(klass);
+C2V_END
+
+C2V_VMENTRY(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  InstanceKlass* ik = InstanceKlass::cast(JVMCIENV->asKlass(JVMCIENV->wrap(holder)));
+  if (ik->class_loader_data()->is_builtin_class_loader_data()) {
+    return true;
+  }
+  return false;
+C2V_END
+
+C2V_VMENTRY(jobject, asJavaType, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  if (java_lang_Class::is_instance(obj())) {
+    if (java_lang_Class::is_primitive(obj())) {
+      JVMCIObject type = JVMCIENV->get_jvmci_primitive_type(java_lang_Class::primitive_type(obj()));
+      return JVMCIENV->get_jobject(type);
+    }
+    Klass* klass = java_lang_Class::as_Klass(obj());
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = klass;
+    JVMCIObject type = JVMCIENV->get_jvmci_type(klass_handle, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(type);
+  }
+  return NULL;
+C2V_END
+
+
+C2V_VMENTRY(jobject, asString, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  const char* str = java_lang_String::as_utf8_string(obj());
+  JVMCIObject result = JVMCIENV->create_string(str, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+
+C2V_VMENTRY(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle))
+  if (x == NULL || y == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  return JVMCIENV->resolve_handle(xHandle) == JVMCIENV->resolve_handle(yHandle);
+C2V_END
+
+C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject base_object = JVMCIENV->wrap(object);
+  Handle mirror;
+  if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
+    mirror = Handle(THREAD, JVMCIENV->asKlass(base_object)->java_mirror());
+  } else if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(base_object)) {
+    mirror = JVMCIENV->asConstant(JVMCIENV->get_HotSpotResolvedPrimitiveType_mirror(base_object), JVMCI_CHECK_NULL);
+  } else {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                         err_msg("Unexpected type: %s", JVMCIENV->klass_name(base_object)));
+ }
+  JVMCIObject result = JVMCIENV->get_object_constant(mirror());
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+
+C2V_VMENTRY(jint, getArrayLength, (JNIEnv* env, jobject, jobject x))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  if (xobj->klass()->is_array_klass()) {
+    return arrayOop(xobj())->length();
+  }
+  return -1;
+ C2V_END
+
+
+C2V_VMENTRY(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_NULL);
+  if (xobj->klass()->is_array_klass()) {
+    arrayOop array = arrayOop(xobj());
+    BasicType element_type = ArrayKlass::cast(array->klass())->element_type();
+    if (index < 0 || index >= array->length()) {
+      return NULL;
+    }
+    JVMCIObject result;
+
+    if (element_type == T_OBJECT) {
+      result = JVMCIENV->get_object_constant(objArrayOop(xobj())->obj_at(index));
+      if (result.is_null()) {
+        result = JVMCIENV->get_JavaConstant_NULL_POINTER();
+      }
+    } else {
+      jvalue value;
+      switch (element_type) {
+        case T_DOUBLE:        value.d = typeArrayOop(xobj())->double_at(index);        break;
+        case T_FLOAT:         value.f = typeArrayOop(xobj())->float_at(index);         break;
+        case T_LONG:          value.j = typeArrayOop(xobj())->long_at(index);          break;
+        case T_INT:           value.i = typeArrayOop(xobj())->int_at(index);            break;
+        case T_SHORT:         value.s = typeArrayOop(xobj())->short_at(index);          break;
+        case T_CHAR:          value.c = typeArrayOop(xobj())->char_at(index);           break;
+        case T_BYTE:          value.b = typeArrayOop(xobj())->byte_at(index);           break;
+        case T_BOOLEAN:       value.z = typeArrayOop(xobj())->byte_at(index) & 1;       break;
+        default:              ShouldNotReachHere();
+      }
+      result = JVMCIENV->create_box(element_type, &value, JVMCI_CHECK_NULL);
+    }
+    assert(!result.is_null(), "must have a value");
+    return JVMCIENV->get_jobject(result);
+  }
+  return NULL;;
+C2V_END
+
+
+C2V_VMENTRY(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind))
+  if (kind == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->wrap(kind), JVMCI_CHECK_0);
+  return arrayOopDesc::header_size(type) * HeapWordSize;
+C2V_END
+
+C2V_VMENTRY(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind))
+  if (kind == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->wrap(kind), JVMCI_CHECK_0);
+  return type2aelembytes(type);
+C2V_END
+
+C2V_VMENTRY(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->byte_field(displacement);
+}
+
+C2V_VMENTRY(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->short_field(displacement);
+}
+
+C2V_VMENTRY(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->int_field(displacement);
+}
+
+C2V_VMENTRY(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->long_field(displacement);
+}
+
+C2V_VMENTRY(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  oop res = xobj->obj_field(displacement);
+  JVMCIObject result = JVMCIENV->get_object_constant(res);
+  return JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h))
+  jobject handle = (jobject)(address)h;
+  if (handle != NULL) {
+    assert(JVMCI::is_global_handle(handle), "Invalid delete of global JNI handle");
+    *((oop*)handle) = NULL; // Mark the handle as deleted, allocate will reuse it
+  }
+}
+
+C2V_VMENTRY(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror))
+  if (!UseJVMCINativeLibrary) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)");
+  }
+  if (!JVMCIENV->is_hotspot()) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "Cannot call registerNativeMethods from JVMCI shared library");
+  }
+  void* shared_library = JVMCIEnv::get_shared_library_handle();
+  if (shared_library == NULL) {
+    // Ensure the JVMCI shared library runtime is initialized.
+    JVMCIEnv __peer_jvmci_env__(false, __FILE__, __LINE__);
+    JVMCIEnv* peerEnv = &__peer_jvmci_env__;
+    HandleMark hm;
+    JVMCIRuntime* runtime = JVMCI::compiler_runtime();
+    JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv);
+    if (peerEnv->has_pending_exception()) {
+      peerEnv->describe_pending_exception(true);
+      JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime");
+    }
+    shared_library = JVMCIEnv::get_shared_library_handle();
+  }
+
+  if (shared_library == NULL) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is unavailable");
+  }
+
+  if (mirror == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
+  if (klass == NULL || !klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(IllegalArgumentException, "clazz is for primitive type");
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* method = iklass->methods()->at(i);
+    if (method->is_native()) {
+
+      // Compute argument size
+      int args_size = 1                             // JNIEnv
+                    + (method->is_static() ? 1 : 0) // class for static methods
+                    + method->size_of_parameters(); // actual parameters
+
+      // 1) Try JNI short style
+      stringStream st;
+      char* pure_name = NativeLookup::pure_jni_name(method);
+      os::print_jni_name_prefix_on(&st, args_size);
+      st.print_raw(pure_name);
+      os::print_jni_name_suffix_on(&st, args_size);
+      char* jni_name = st.as_string();
+
+      address entry = (address) os::dll_lookup(shared_library, jni_name);
+      if (entry == NULL) {
+        // 2) Try JNI long style
+        st.reset();
+        char* long_name = NativeLookup::long_jni_name(method);
+        os::print_jni_name_prefix_on(&st, args_size);
+        st.print_raw(pure_name);
+        st.print_raw(long_name);
+        os::print_jni_name_suffix_on(&st, args_size);
+        jni_name = st.as_string();
+        entry = (address) os::dll_lookup(shared_library, jni_name);
+      }
+      if (entry == NULL) {
+        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, method->name_and_sig_as_C_string());
+      }
+      if (method->has_native_function() && entry != method->native_function()) {
+        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("Cannot overwrite existing native implementation for %s",
+            method->name_and_sig_as_C_string()));
+      }
+      method->set_native_function(entry, Method::native_bind_event_is_interesting);
+      if (PrintJNIResolving) {
+        tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]",
+          method->method_holder()->external_name(),
+          method->name()->as_C_string());
+      }
+    }
+  }
+
+  JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm();
+  JVMCIPrimitiveArray result = JVMCIENV->new_longArray(4, JVMCI_CHECK_NULL);
+  JVMCIENV->put_long_at(result, 0, (jlong) (address) javaVM);
+  JVMCIENV->put_long_at(result, 1, (jlong) (address) javaVM->functions->reserved0);
+  JVMCIENV->put_long_at(result, 2, (jlong) (address) javaVM->functions->reserved1);
+  JVMCIENV->put_long_at(result, 3, (jlong) (address) javaVM->functions->reserved2);
+  return (jlongArray) JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
+  if (obj_handle == NULL) {
+    return 0L;
+  }
+  JVMCIEnv __peer_jvmci_env__(!JVMCIENV->is_hotspot(), __FILE__, __LINE__);
+  JVMCIEnv* peerEnv = &__peer_jvmci_env__;
+  JVMCIEnv* thisEnv = JVMCIENV;
+
+  JVMCIObject obj = thisEnv->wrap(obj_handle);
+  JVMCIObject result;
+  if (thisEnv->isa_HotSpotResolvedJavaMethodImpl(obj)) {
+    Method* method = thisEnv->asMethod(obj);
+    result = peerEnv->get_jvmci_method(method, JVMCI_CHECK_0);
+  } else if (thisEnv->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    Klass* klass = thisEnv->asKlass(obj);
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = klass;
+    result = peerEnv->get_jvmci_type(klass_handle, JVMCI_CHECK_0);
+  } else if (thisEnv->isa_HotSpotResolvedPrimitiveType(obj)) {
+    BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(obj), JVMCI_CHECK_0);
+    result = peerEnv->get_jvmci_primitive_type(type);
+  } else if (thisEnv->isa_IndirectHotSpotObjectConstantImpl(obj) ||
+             thisEnv->isa_DirectHotSpotObjectConstantImpl(obj)) {
+    Handle constant = thisEnv->asConstant(obj, JVMCI_CHECK_0);
+    result = peerEnv->get_object_constant(constant());
+  } else if (thisEnv->isa_HotSpotNmethod(obj)) {
+    nmethod* nm = thisEnv->asNmethod(obj);
+    if (nm != NULL) {
+      JVMCINMethodData* data = nm->jvmci_nmethod_data();
+      if (data != NULL) {
+        if (peerEnv->is_hotspot()) {
+          // Only the mirror in the HotSpot heap is accessible
+          // through JVMCINMethodData
+          oop nmethod_mirror = data->get_nmethod_mirror(nm);
+          if (nmethod_mirror != NULL) {
+            result = HotSpotJVMCI::wrap(nmethod_mirror);
+          }
+        }
+      }
+    }
+    if (result.is_null()) {
+      JVMCIObject methodObject = thisEnv->get_HotSpotNmethod_method(obj);
+      methodHandle mh = thisEnv->asMethod(methodObject);
+      jboolean isDefault = thisEnv->get_HotSpotNmethod_isDefault(obj);
+      jlong compileIdSnapshot = thisEnv->get_HotSpotNmethod_compileIdSnapshot(obj);
+      JVMCIObject name_string = thisEnv->get_InstalledCode_name(obj);
+      const char* cstring = name_string.is_null() ? NULL : thisEnv->as_utf8_string(name_string);
+      // Create a new HotSpotNmethod instance in the peer runtime
+      result = peerEnv->new_HotSpotNmethod(mh(), cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0);
+      if (nm == NULL) {
+        // nmethod must have been unloaded
+      } else {
+        // Link the new HotSpotNmethod to the nmethod
+        peerEnv->initialize_installed_code(result, nm, JVMCI_CHECK_0);
+        // Only HotSpotNmethod instances in the HotSpot heap are tracked directly by the runtime.
+        if (peerEnv->is_hotspot()) {
+          JVMCINMethodData* data = nm->jvmci_nmethod_data();
+          if (data == NULL) {
+            JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot set HotSpotNmethod mirror for default nmethod");
+          }
+          if (data->get_nmethod_mirror(nm) != NULL) {
+            JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot overwrite existing HotSpotNmethod mirror for nmethod");
+          }
+          oop nmethod_mirror = HotSpotJVMCI::resolve(result);
+          data->set_nmethod_mirror(nm, nmethod_mirror);
+        }
+      }
+    }
+  } else {
+    JVMCI_THROW_MSG_0(IllegalArgumentException,
+                err_msg("Cannot translate object of type: %s", thisEnv->klass_name(obj)));
+  }
+  return (jlong) peerEnv->make_global(result).as_jobject();
+}
+
+C2V_VMENTRY(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle))
+  if (obj_handle == 0L) {
+    return NULL;
+  }
+  jobject global_handle = (jobject) obj_handle;
+  JVMCIObject global_handle_obj = JVMCIENV->wrap((jobject) obj_handle);
+  jobject result = JVMCIENV->make_local(global_handle_obj).as_jobject();
+
+  JVMCIENV->destroy_global(global_handle_obj);
+  return result;
+}
+
+C2V_VMENTRY(void, updateHotSpotNmethod, (JNIEnv* env, jobject, jobject code_handle))
+  JVMCIObject code = JVMCIENV->wrap(code_handle);
+  // Execute this operation for the side effect of updating the InstalledCode state
+  JVMCIENV->asNmethod(code);
+}
+
+C2V_VMENTRY(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle))
+  JVMCIObject code = JVMCIENV->wrap(code_handle);
+  CodeBlob* cb = JVMCIENV->asCodeBlob(code);
+  if (cb == NULL) {
+    return NULL;
+  }
+  int code_size = cb->code_size();
+  JVMCIPrimitiveArray result = JVMCIENV->new_byteArray(code_size, JVMCI_CHECK_NULL);
+  JVMCIENV->copy_bytes_from((jbyte*) cb->code_begin(), result, 0, code_size);
+  return JVMCIENV->get_jbyteArray(result);
+}
+
 C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
-  methodHandle m = CompilerToVM::asMethod(jvmci_method);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  methodHandle m = JVMCIENV->asMethod(jvmci_method);
   oop executable;
   if (m->is_initializer()) {
     if (m->is_static_initializer()) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-        "Cannot create java.lang.reflect.Method for class initializer");
+      JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+          "Cannot create java.lang.reflect.Method for class initializer");
     }
     executable = Reflection::new_constructor(m, CHECK_NULL);
   } else {
     executable = Reflection::new_method(m, false, CHECK_NULL);
   }
-  return JNIHandles::make_local(thread, executable);
+  return JNIHandles::make_local(THREAD, executable);
 }
 
 C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
         err_msg("Expected non-primitive type, got %s", klass->external_name()));
   }
   InstanceKlass* iklass = InstanceKlass::cast(klass);
   Array<u2>* fields = iklass->fields();
-  if (index < 0 || index > fields->length()) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+  if (index < 0 ||index > fields->length()) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
         err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
   }
   fieldDescriptor fd(iklass, index);
@@ -1541,27 +2284,90 @@
   return JNIHandles::make_local(env, reflected);
 }
 
+C2V_VMENTRY(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
+  FailedSpeculation* head = *((FailedSpeculation**)(address) failed_speculations_address);
+  int result_length = 0;
+  for (FailedSpeculation* fs = head; fs != NULL; fs = fs->next()) {
+    result_length++;
+  }
+  int current_length = 0;
+  JVMCIObjectArray current_array = NULL;
+  if (current != NULL) {
+    current_array = JVMCIENV->wrap(current);
+    current_length = JVMCIENV->get_length(current_array);
+    if (current_length == result_length) {
+      // No new failures
+      return current;
+    }
+  }
+  JVMCIObjectArray result = JVMCIENV->new_byte_array_array(result_length, JVMCI_CHECK_NULL);
+  int result_index = 0;
+  for (FailedSpeculation* fs = head; result_index < result_length; fs = fs->next()) {
+    assert(fs != NULL, "npe");
+    JVMCIPrimitiveArray entry;
+    if (result_index < current_length) {
+      entry = (JVMCIPrimitiveArray) JVMCIENV->get_object_at(current_array, result_index);
+    } else {
+      entry = JVMCIENV->new_byteArray(fs->data_len(), JVMCI_CHECK_NULL);
+      JVMCIENV->copy_bytes_from((jbyte*) fs->data(), entry, 0, fs->data_len());
+    }
+    JVMCIENV->put_object_at(result, result_index++, entry);
+  }
+  return JVMCIENV->get_jobjectArray(result);
+}
+
+C2V_VMENTRY(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  MethodData* method_data = method->method_data();
+  if (method_data == NULL) {
+    ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
+    method_data = MethodData::allocate(loader_data, method, CHECK_0);
+    method->set_method_data(method_data);
+  }
+  return (jlong) method_data->get_failed_speculations_address();
+}
+
+C2V_VMENTRY(void, releaseFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address))
+  FailedSpeculation::free_failed_speculations((FailedSpeculation**)(address) failed_speculations_address);
+}
+
+C2V_VMENTRY(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj))
+  JVMCIPrimitiveArray speculation_handle = JVMCIENV->wrap(speculation_obj);
+  int speculation_len = JVMCIENV->get_length(speculation_handle);
+  char* speculation = NEW_RESOURCE_ARRAY(char, speculation_len);
+  JVMCIENV->copy_bytes_to(speculation_handle, (jbyte*) speculation, 0, speculation_len);
+  return FailedSpeculation::add_failed_speculation(NULL, (FailedSpeculation**)(address) failed_speculations_address, (address) speculation, speculation_len);
+}
+
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
 
 #define STRING                  "Ljava/lang/String;"
 #define OBJECT                  "Ljava/lang/Object;"
 #define CLASS                   "Ljava/lang/Class;"
+#define OBJECTCONSTANT          "Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;"
+#define HANDLECONSTANT          "Ljdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl;"
 #define EXECUTABLE              "Ljava/lang/reflect/Executable;"
 #define STACK_TRACE_ELEMENT     "Ljava/lang/StackTraceElement;"
 #define INSTALLED_CODE          "Ljdk/vm/ci/code/InstalledCode;"
 #define TARGET_DESCRIPTION      "Ljdk/vm/ci/code/TargetDescription;"
 #define BYTECODE_FRAME          "Ljdk/vm/ci/code/BytecodeFrame;"
+#define JAVACONSTANT            "Ljdk/vm/ci/meta/JavaConstant;"
 #define INSPECTED_FRAME_VISITOR "Ljdk/vm/ci/code/stack/InspectedFrameVisitor;"
 #define RESOLVED_METHOD         "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
 #define HS_RESOLVED_METHOD      "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;"
 #define HS_RESOLVED_KLASS       "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;"
+#define HS_RESOLVED_TYPE        "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaType;"
+#define HS_RESOLVED_FIELD       "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaField;"
+#define HS_INSTALLED_CODE       "Ljdk/vm/ci/hotspot/HotSpotInstalledCode;"
+#define HS_NMETHOD              "Ljdk/vm/ci/hotspot/HotSpotNmethod;"
 #define HS_CONSTANT_POOL        "Ljdk/vm/ci/hotspot/HotSpotConstantPool;"
 #define HS_COMPILED_CODE        "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG               "Ljdk/vm/ci/hotspot/HotSpotVMConfig;"
 #define HS_METADATA             "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
 #define HS_STACK_FRAME_REF      "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
 #define HS_SPECULATION_LOG      "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
+#define METASPACE_OBJECT        "Ljdk/vm/ci/hotspot/MetaspaceObject;"
 #define REFLECTION_EXECUTABLE   "Ljava/lang/reflect/Executable;"
 #define REFLECTION_FIELD        "Ljava/lang/reflect/Field;"
 #define METASPACE_METHOD_DATA   "J"
@@ -1578,17 +2384,18 @@
   {CC "isCompilable",                                 CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(isCompilable)},
   {CC "hasNeverInlineDirective",                      CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(hasNeverInlineDirective)},
   {CC "shouldInlineMethod",                           CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(shouldInlineMethod)},
-  {CC "lookupType",                                   CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS,                                           FN_PTR(lookupType)},
+  {CC "lookupType",                                   CC "(" STRING HS_RESOLVED_KLASS "Z)" HS_RESOLVED_TYPE,                                FN_PTR(lookupType)},
+  {CC "lookupClass",                                  CC "(" CLASS ")" HS_RESOLVED_TYPE,                                                    FN_PTR(lookupClass)},
   {CC "lookupNameInPool",                             CC "(" HS_CONSTANT_POOL "I)" STRING,                                                  FN_PTR(lookupNameInPool)},
   {CC "lookupNameAndTypeRefIndexInPool",              CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(lookupNameAndTypeRefIndexInPool)},
   {CC "lookupSignatureInPool",                        CC "(" HS_CONSTANT_POOL "I)" STRING,                                                  FN_PTR(lookupSignatureInPool)},
   {CC "lookupKlassRefIndexInPool",                    CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(lookupKlassRefIndexInPool)},
   {CC "lookupKlassInPool",                            CC "(" HS_CONSTANT_POOL "I)Ljava/lang/Object;",                                       FN_PTR(lookupKlassInPool)},
-  {CC "lookupAppendixInPool",                         CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(lookupAppendixInPool)},
+  {CC "lookupAppendixInPool",                         CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(lookupAppendixInPool)},
   {CC "lookupMethodInPool",                           CC "(" HS_CONSTANT_POOL "IB)" HS_RESOLVED_METHOD,                                     FN_PTR(lookupMethodInPool)},
   {CC "constantPoolRemapInstructionOperandFromCache", CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(constantPoolRemapInstructionOperandFromCache)},
-  {CC "resolveConstantInPool",                        CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolveConstantInPool)},
-  {CC "resolvePossiblyCachedConstantInPool",          CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolvePossiblyCachedConstantInPool)},
+  {CC "resolveConstantInPool",                        CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(resolveConstantInPool)},
+  {CC "resolvePossiblyCachedConstantInPool",          CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(resolvePossiblyCachedConstantInPool)},
   {CC "resolveTypeInPool",                            CC "(" HS_CONSTANT_POOL "I)" HS_RESOLVED_KLASS,                                       FN_PTR(resolveTypeInPool)},
   {CC "resolveFieldInPool",                           CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[I)" HS_RESOLVED_KLASS,              FN_PTR(resolveFieldInPool)},
   {CC "resolveInvokeDynamicInPool",                   CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeDynamicInPool)},
@@ -1601,20 +2408,21 @@
   {CC "hasFinalizableSubclass",                       CC "(" HS_RESOLVED_KLASS ")Z",                                                        FN_PTR(hasFinalizableSubclass)},
   {CC "getMaxCallTargetOffset",                       CC "(J)J",                                                                            FN_PTR(getMaxCallTargetOffset)},
   {CC "asResolvedJavaMethod",                         CC "(" EXECUTABLE ")" HS_RESOLVED_METHOD,                                             FN_PTR(asResolvedJavaMethod)},
-  {CC "getResolvedJavaMethod",                        CC "(Ljava/lang/Object;J)" HS_RESOLVED_METHOD,                                        FN_PTR(getResolvedJavaMethod)},
-  {CC "getConstantPool",                              CC "(Ljava/lang/Object;)" HS_CONSTANT_POOL,                                           FN_PTR(getConstantPool)},
-  {CC "getResolvedJavaType",                          CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS,                                        FN_PTR(getResolvedJavaType)},
+  {CC "getResolvedJavaMethod",                        CC "(" OBJECTCONSTANT "J)" HS_RESOLVED_METHOD,                                        FN_PTR(getResolvedJavaMethod)},
+  {CC "getConstantPool",                              CC "(" METASPACE_OBJECT ")" HS_CONSTANT_POOL,                                         FN_PTR(getConstantPool)},
+  {CC "getResolvedJavaType0",                         CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS,                                        FN_PTR(getResolvedJavaType0)},
   {CC "readConfiguration",                            CC "()[" OBJECT,                                                                      FN_PTR(readConfiguration)},
-  {CC "installCode",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG ")I",    FN_PTR(installCode)},
+  {CC "installCode",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE "J[B)I",                    FN_PTR(installCode)},
   {CC "getMetadata",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA ")I",                          FN_PTR(getMetadata)},
   {CC "resetCompilationStatistics",                   CC "()V",                                                                             FN_PTR(resetCompilationStatistics)},
   {CC "disassembleCodeBlob",                          CC "(" INSTALLED_CODE ")" STRING,                                                     FN_PTR(disassembleCodeBlob)},
-  {CC "executeInstalledCode",                         CC "([" OBJECT INSTALLED_CODE ")" OBJECT,                                             FN_PTR(executeInstalledCode)},
+  {CC "executeHotSpotNmethod",                        CC "([" OBJECT HS_NMETHOD ")" OBJECT,                                                 FN_PTR(executeHotSpotNmethod)},
   {CC "getLineNumberTable",                           CC "(" HS_RESOLVED_METHOD ")[J",                                                      FN_PTR(getLineNumberTable)},
   {CC "getLocalVariableTableStart",                   CC "(" HS_RESOLVED_METHOD ")J",                                                       FN_PTR(getLocalVariableTableStart)},
   {CC "getLocalVariableTableLength",                  CC "(" HS_RESOLVED_METHOD ")I",                                                       FN_PTR(getLocalVariableTableLength)},
   {CC "reprofile",                                    CC "(" HS_RESOLVED_METHOD ")V",                                                       FN_PTR(reprofile)},
-  {CC "invalidateInstalledCode",                      CC "(" INSTALLED_CODE ")V",                                                           FN_PTR(invalidateInstalledCode)},
+  {CC "invalidateHotSpotNmethod",                     CC "(" HS_NMETHOD ")V",                                                               FN_PTR(invalidateHotSpotNmethod)},
+  {CC "readUncompressedOop",                          CC "(J)" OBJECTCONSTANT,                                                              FN_PTR(readUncompressedOop)},
   {CC "collectCounters",                              CC "()[J",                                                                            FN_PTR(collectCounters)},
   {CC "allocateCompileId",                            CC "(" HS_RESOLVED_METHOD "I)I",                                                      FN_PTR(allocateCompileId)},
   {CC "isMature",                                     CC "(" METASPACE_METHOD_DATA ")Z",                                                    FN_PTR(isMature)},
@@ -1629,10 +2437,48 @@
   {CC "getFingerprint",                               CC "(J)J",                                                                            FN_PTR(getFingerprint)},
   {CC "getHostClass",                                 CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_KLASS,                                       FN_PTR(getHostClass)},
   {CC "interpreterFrameSize",                         CC "(" BYTECODE_FRAME ")I",                                                           FN_PTR(interpreterFrameSize)},
-  {CC "compileToBytecode",                            CC "(" OBJECT ")V",                                                                   FN_PTR(compileToBytecode)},
+  {CC "compileToBytecode",                            CC "(" OBJECTCONSTANT ")V",                                                           FN_PTR(compileToBytecode)},
   {CC "getFlagValue",                                 CC "(" STRING ")" OBJECT,                                                             FN_PTR(getFlagValue)},
+  {CC "getObjectAtAddress",                           CC "(J)" OBJECT,                                                                      FN_PTR(getObjectAtAddress)},
+  {CC "getInterfaces",                                CC "(" HS_RESOLVED_KLASS ")[" HS_RESOLVED_KLASS,                                      FN_PTR(getInterfaces)},
+  {CC "getComponentType",                             CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_TYPE,                                        FN_PTR(getComponentType)},
+  {CC "ensureInitialized",                            CC "(" HS_RESOLVED_KLASS ")V",                                                        FN_PTR(ensureInitialized)},
+  {CC "getIdentityHashCode",                          CC "(" OBJECTCONSTANT ")I",                                                           FN_PTR(getIdentityHashCode)},
+  {CC "isInternedString",                             CC "(" OBJECTCONSTANT ")Z",                                                           FN_PTR(isInternedString)},
+  {CC "unboxPrimitive",                               CC "(" OBJECTCONSTANT ")" OBJECT,                                                     FN_PTR(unboxPrimitive)},
+  {CC "boxPrimitive",                                 CC "(" OBJECT ")" OBJECTCONSTANT,                                                     FN_PTR(boxPrimitive)},
+  {CC "getDeclaredConstructors",                      CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD,                                        FN_PTR(getDeclaredConstructors)},
+  {CC "getDeclaredMethods",                           CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD,                                        FN_PTR(getDeclaredMethods)},
+  {CC "readFieldValue",                               CC "(" HS_RESOLVED_KLASS HS_RESOLVED_FIELD "Z)" JAVACONSTANT,                         FN_PTR(readFieldValue)},
+  {CC "readFieldValue",                               CC "(" OBJECTCONSTANT HS_RESOLVED_FIELD "Z)" JAVACONSTANT,                            FN_PTR(readFieldValue)},
+  {CC "isInstance",                                   CC "(" HS_RESOLVED_KLASS OBJECTCONSTANT ")Z",                                         FN_PTR(isInstance)},
+  {CC "isAssignableFrom",                             CC "(" HS_RESOLVED_KLASS HS_RESOLVED_KLASS ")Z",                                      FN_PTR(isAssignableFrom)},
+  {CC "isTrustedForIntrinsics",                       CC "(" HS_RESOLVED_KLASS ")Z",                                                        FN_PTR(isTrustedForIntrinsics)},
+  {CC "asJavaType",                                   CC "(" OBJECTCONSTANT ")" HS_RESOLVED_TYPE,                                           FN_PTR(asJavaType)},
+  {CC "asString",                                     CC "(" OBJECTCONSTANT ")" STRING,                                                     FN_PTR(asString)},
+  {CC "equals",                                       CC "(" OBJECTCONSTANT "J" OBJECTCONSTANT "J)Z",                                       FN_PTR(equals)},
+  {CC "getJavaMirror",                                CC "(" HS_RESOLVED_TYPE ")" OBJECTCONSTANT,                                           FN_PTR(getJavaMirror)},
+  {CC "getArrayLength",                               CC "(" OBJECTCONSTANT ")I",                                                           FN_PTR(getArrayLength)},
+  {CC "readArrayElement",                             CC "(" OBJECTCONSTANT "I)Ljava/lang/Object;",                                         FN_PTR(readArrayElement)},
+  {CC "arrayBaseOffset",                              CC "(Ljdk/vm/ci/meta/JavaKind;)I",                                                    FN_PTR(arrayBaseOffset)},
+  {CC "arrayIndexScale",                              CC "(Ljdk/vm/ci/meta/JavaKind;)I",                                                    FN_PTR(arrayIndexScale)},
+  {CC "getByte",                                      CC "(" OBJECTCONSTANT "J)B",                                                          FN_PTR(getByte)},
+  {CC "getShort",                                     CC "(" OBJECTCONSTANT "J)S",                                                          FN_PTR(getShort)},
+  {CC "getInt",                                       CC "(" OBJECTCONSTANT "J)I",                                                          FN_PTR(getInt)},
+  {CC "getLong",                                      CC "(" OBJECTCONSTANT "J)J",                                                          FN_PTR(getLong)},
+  {CC "getObject",                                    CC "(" OBJECTCONSTANT "J)" OBJECTCONSTANT,                                            FN_PTR(getObject)},
+  {CC "deleteGlobalHandle",                           CC "(J)V",                                                                            FN_PTR(deleteGlobalHandle)},
+  {CC "registerNativeMethods",                        CC "(" CLASS ")[J",                                                                   FN_PTR(registerNativeMethods)},
+  {CC "translate",                                    CC "(" OBJECT ")J",                                                                   FN_PTR(translate)},
+  {CC "unhand",                                       CC "(J)" OBJECT,                                                                      FN_PTR(unhand)},
+  {CC "updateHotSpotNmethod",                         CC "(" HS_NMETHOD ")V",                                                               FN_PTR(updateHotSpotNmethod)},
+  {CC "getCode",                                      CC "(" HS_INSTALLED_CODE ")[B",                                                       FN_PTR(getCode)},
   {CC "asReflectionExecutable",                       CC "(" HS_RESOLVED_METHOD ")" REFLECTION_EXECUTABLE,                                  FN_PTR(asReflectionExecutable)},
   {CC "asReflectionField",                            CC "(" HS_RESOLVED_KLASS "I)" REFLECTION_FIELD,                                       FN_PTR(asReflectionField)},
+  {CC "getFailedSpeculations",                        CC "(J[[B)[[B",                                                                       FN_PTR(getFailedSpeculations)},
+  {CC "getFailedSpeculationsAddress",                 CC "(" HS_RESOLVED_METHOD ")J",                                                       FN_PTR(getFailedSpeculationsAddress)},
+  {CC "releaseFailedSpeculations",                    CC "(J)V",                                                                            FN_PTR(releaseFailedSpeculations)},
+  {CC "addFailedSpeculation",                         CC "(J[B)Z",                                                                          FN_PTR(addFailedSpeculation)},
 };
 
 int CompilerToVM::methods_count() {
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Fri May 03 14:59:32 2019 -0400
@@ -24,40 +24,12 @@
 #ifndef SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
 #define SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
 
-#include "jni.h"
+#include "gc/shared/cardTable.hpp"
+#include "jvmci/jvmciExceptions.hpp"
 #include "runtime/javaCalls.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-
-// Helper class to ensure that references to Klass* are kept alive for G1
-class JVMCIKlassHandle : public StackObj {
- private:
-  Klass*     _klass;
-  Handle     _holder;
-  Thread*    _thread;
-
-  Klass*        klass() const                     { return _klass; }
-  Klass*        non_null_klass() const            { assert(_klass != NULL, "resolving NULL _klass"); return _klass; }
+#include "runtime/signature.hpp"
 
- public:
-  /* Constructors */
-  JVMCIKlassHandle (Thread* thread) : _klass(NULL), _thread(thread) {}
-  JVMCIKlassHandle (Thread* thread, Klass* klass);
-
-  JVMCIKlassHandle (const JVMCIKlassHandle &h): _klass(h._klass), _holder(h._holder), _thread(h._thread) {}
-  JVMCIKlassHandle& operator=(const JVMCIKlassHandle &s);
-  JVMCIKlassHandle& operator=(Klass* klass);
-
-  /* Operators for ease of use */
-  Klass*        operator () () const            { return klass(); }
-  Klass*        operator -> () const            { return non_null_klass(); }
-
-  bool    operator == (Klass* o) const          { return klass() == o; }
-  bool    operator == (const JVMCIKlassHandle& h) const  { return klass() == h.klass(); }
-
-  /* Null checks */
-  bool    is_null() const                      { return _klass == NULL; }
-  bool    not_null() const                     { return _klass != NULL; }
-};
+class JVMCIObjectArray;
 
 class CompilerToVM {
  public:
@@ -118,7 +90,7 @@
     static address symbol_clinit;
 
    public:
-    static void initialize(TRAPS);
+     static void initialize(JVMCI_TRAPS);
 
     static int max_oop_map_stack_offset() {
       assert(_max_oop_map_stack_offset > 0, "must be initialized");
@@ -141,59 +113,14 @@
   }
 
   static JNINativeMethod methods[];
+  static JNINativeMethod jni_methods[];
 
-  static objArrayHandle initialize_intrinsics(TRAPS);
+  static JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
  public:
   static int methods_count();
 
-  static inline Method* asMethod(jobject jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline Method* asMethod(Handle jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline Method* asMethod(oop jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline ConstantPool* asConstantPool(jobject jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
-
-  static inline ConstantPool* asConstantPool(Handle jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
-
-  static inline ConstantPool* asConstantPool(oop jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
+};
 
-  static inline Klass* asKlass(jobject jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(Handle jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(oop jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(jlong metaspaceKlass) {
-    return (Klass*) (address) metaspaceKlass;
-  }
-
-  static inline MethodData* asMethodData(jlong metaspaceMethodData) {
-    return (MethodData*) (address) metaspaceMethodData;
-  }
-
-  static oop get_jvmci_method(const methodHandle& method, TRAPS);
-
-  static oop get_jvmci_type(JVMCIKlassHandle& klass, TRAPS);
-};
 
 class JavaArgumentUnboxer : public SignatureIterator {
  protected:
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Fri May 03 14:59:32 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
@@ -25,13 +25,10 @@
 #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"
+#include "gc/shared/collectedHeap.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/vmStructs_jvmci.hpp"
-#include "runtime/flags/jvmFlag.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/resourceHash.hpp"
 
@@ -88,7 +85,7 @@
 address CompilerToVM::Data::symbol_init;
 address CompilerToVM::Data::symbol_clinit;
 
-void CompilerToVM::Data::initialize(TRAPS) {
+void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
   Klass_vtable_start_offset = in_bytes(Klass::vtable_start_offset());
   Klass_vtable_length_offset = in_bytes(Klass::vtable_length_offset());
 
@@ -157,29 +154,23 @@
 #undef SET_TRIGFUNC
 }
 
-objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) {
-  objArrayHandle vmIntrinsics = oopFactory::new_objArray_handle(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle()));
+JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
+  JVMCIObjectArray vmIntrinsics = JVMCIENV->new_VMIntrinsicMethod_array(vmIntrinsics::ID_LIMIT - 1, JVMCI_CHECK_NULL);
   int index = 0;
-  // The intrinsics for a class are usually adjacent to each other.
-  // When they are, the string for the class name can be reused.
   vmSymbols::SID kls_sid = vmSymbols::NO_SID;
-  Handle kls_str;
+  JVMCIObject kls_str;
 #define VM_SYMBOL_TO_STRING(s) \
-  java_lang_String::create_from_symbol(vmSymbols::symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(s)), CHECK_(objArrayHandle()))
+  JVMCIENV->create_string(vmSymbols::symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(s)), JVMCI_CHECK_NULL)
 #define VM_INTRINSIC_INFO(id, kls, name, sig, ignore_fcode) {             \
-    instanceHandle vmIntrinsicMethod = InstanceKlass::cast(VMIntrinsicMethod::klass())->allocate_instance_handle(CHECK_(objArrayHandle())); \
     vmSymbols::SID sid = vmSymbols::VM_SYMBOL_ENUM_NAME(kls);             \
     if (kls_sid != sid) {                                                 \
       kls_str = VM_SYMBOL_TO_STRING(kls);                                 \
       kls_sid = sid;                                                      \
     }                                                                     \
-    Handle name_str = VM_SYMBOL_TO_STRING(name);                          \
-    Handle sig_str = VM_SYMBOL_TO_STRING(sig);                            \
-    VMIntrinsicMethod::set_declaringClass(vmIntrinsicMethod, kls_str());  \
-    VMIntrinsicMethod::set_name(vmIntrinsicMethod, name_str());           \
-    VMIntrinsicMethod::set_descriptor(vmIntrinsicMethod, sig_str());      \
-    VMIntrinsicMethod::set_id(vmIntrinsicMethod, vmIntrinsics::id);       \
-      vmIntrinsics->obj_at_put(index++, vmIntrinsicMethod());             \
+    JVMCIObject name_str = VM_SYMBOL_TO_STRING(name);                    \
+    JVMCIObject sig_str = VM_SYMBOL_TO_STRING(sig);                      \
+    JVMCIObject vmIntrinsicMethod = JVMCIENV->new_VMIntrinsicMethod(kls_str, name_str, sig_str, (jint) vmIntrinsics::id, JVMCI_CHECK_NULL); \
+    JVMCIENV->put_object_at(vmIntrinsics, index++, vmIntrinsicMethod);   \
   }
 
   VM_INTRINSICS_DO(VM_INTRINSIC_INFO, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
@@ -190,9 +181,6 @@
   return vmIntrinsics;
 }
 
-/**
- * The set of VM flags known to be used.
- */
 #define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
   do_intx_flag(AllocateInstancePrefetchLines)                              \
   do_intx_flag(AllocatePrefetchDistance)                                   \
@@ -258,30 +246,28 @@
   do_bool_flag(UseTLAB)                                                    \
   do_bool_flag(VerifyOops)                                                 \
 
-#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
-#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+#define BOXED_BOOLEAN(name, value) name = ((jboolean)(value) ? boxedTrue : boxedFalse)
+#define BOXED_DOUBLE(name, value) do { jvalue p; p.d = (jdouble) (value); name = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL);} while(0)
 #define BOXED_LONG(name, value) \
-  oop name; \
   do { \
     jvalue p; p.j = (jlong) (value); \
-    Handle* e = longs.get(p.j); \
+    JVMCIObject* e = longs.get(p.j); \
     if (e == NULL) { \
-      oop o = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
-      Handle h(THREAD, o); \
+      JVMCIObject h = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); \
       longs.put(p.j, h); \
-      name = h(); \
+      name = h; \
     } else { \
-      name = (*e)(); \
+      name = (*e); \
     } \
   } while (0)
 
 #define CSTRING_TO_JSTRING(name, value) \
-  Handle name; \
+  JVMCIObject name; \
   do { \
     if (value != NULL) { \
-      Handle* e = strings.get(value); \
+      JVMCIObject* e = strings.get(value); \
       if (e == NULL) { \
-        Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
+        JVMCIObject h = JVMCIENV->create_string(value, JVMCI_CHECK_NULL); \
         strings.put(value, h); \
         name = h; \
       } else { \
@@ -290,51 +276,42 @@
     } \
   } while (0)
 
-jobjectArray readConfiguration0(JNIEnv *env, TRAPS) {
-  ResourceMark rm;
-  HandleMark hm;
-
-  // Used to canonicalize Long and String values.
-  ResourceHashtable<jlong, Handle> longs;
-  ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
+jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) {
+  Thread* THREAD = Thread::current();
+  ResourceHashtable<jlong, JVMCIObject> longs;
+  ResourceHashtable<const char*, JVMCIObject, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
 
   jvalue prim;
-  prim.z = true;  oop boxedTrueOop =  java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-  Handle boxedTrue(THREAD, boxedTrueOop);
-  prim.z = false; oop boxedFalseOop = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-  Handle boxedFalse(THREAD, boxedFalseOop);
+  prim.z = true;  JVMCIObject boxedTrue =  JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
+  prim.z = false; JVMCIObject boxedFalse = JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
 
-  CompilerToVM::Data::initialize(CHECK_NULL);
+  CompilerToVM::Data::initialize(JVMCI_CHECK_NULL);
 
-  VMField::klass()->initialize(CHECK_NULL);
-  VMFlag::klass()->initialize(CHECK_NULL);
-  VMIntrinsicMethod::klass()->initialize(CHECK_NULL);
+  JVMCIENV->VMField_initialize(JVMCI_CHECK_NULL);
+  JVMCIENV->VMFlag_initialize(JVMCI_CHECK_NULL);
+  JVMCIENV->VMIntrinsicMethod_initialize(JVMCI_CHECK_NULL);
 
   int len = JVMCIVMStructs::localHotSpotVMStructs_count();
-  objArrayHandle vmFields = oopFactory::new_objArray_handle(VMField::klass(), len, CHECK_NULL);
+  JVMCIObjectArray vmFields = JVMCIENV->new_VMField_array(len, JVMCI_CHECK_NULL);
   for (int i = 0; i < len ; i++) {
     VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i];
-    instanceHandle vmFieldObj = InstanceKlass::cast(VMField::klass())->allocate_instance_handle(CHECK_NULL);
     size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
     char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
     sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
     CSTRING_TO_JSTRING(name, name_buf);
     CSTRING_TO_JSTRING(type, vmField.typeString);
-    VMField::set_name(vmFieldObj, name());
-    VMField::set_type(vmFieldObj, type());
-    VMField::set_offset(vmFieldObj, vmField.offset);
-    VMField::set_address(vmFieldObj, (jlong) vmField.address);
+    JVMCIObject box;
     if (vmField.isStatic && vmField.typeString != NULL) {
       if (strcmp(vmField.typeString, "bool") == 0) {
         BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "int") == 0 ||
                  strcmp(vmField.typeString, "jint") == 0) {
         BOXED_LONG(box, *(jint*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "uint64_t") == 0) {
         BOXED_LONG(box, *(uint64_t*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "address") == 0 ||
                  strcmp(vmField.typeString, "intptr_t") == 0 ||
                  strcmp(vmField.typeString, "uintptr_t") == 0 ||
@@ -343,43 +320,47 @@
                  // All foo* types are addresses.
                  vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
         BOXED_LONG(box, *((address*) vmField.address));
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else {
         JVMCI_ERROR_NULL("VM field %s has unsupported type %s", name_buf, vmField.typeString);
       }
     }
-    vmFields->obj_at_put(i, vmFieldObj());
+    JVMCIObject vmFieldObj = JVMCIENV->new_VMField(name, type, vmField.offset, (jlong) vmField.address, box, JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(vmFields, i, vmFieldObj);
   }
 
   int ints_len = JVMCIVMStructs::localHotSpotVMIntConstants_count();
   int longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count();
   len = ints_len + longs_len;
-  objArrayHandle vmConstants = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  JVMCIObjectArray vmConstants = JVMCIENV->new_Object_array(len * 2, JVMCI_CHECK_NULL);
   int insert = 0;
   for (int i = 0; i < ints_len ; i++) {
     VMIntConstantEntry c = JVMCIVMStructs::localHotSpotVMIntConstants[i];
     CSTRING_TO_JSTRING(name, c.name);
+    JVMCIObject value;
     BOXED_LONG(value, c.value);
-    vmConstants->obj_at_put(insert++, name());
-    vmConstants->obj_at_put(insert++, value);
+    JVMCIENV->put_object_at(vmConstants, insert++, name);
+    JVMCIENV->put_object_at(vmConstants, insert++, value);
   }
   for (int i = 0; i < longs_len ; i++) {
     VMLongConstantEntry c = JVMCIVMStructs::localHotSpotVMLongConstants[i];
     CSTRING_TO_JSTRING(name, c.name);
+    JVMCIObject value;
     BOXED_LONG(value, c.value);
-    vmConstants->obj_at_put(insert++, name());
-    vmConstants->obj_at_put(insert++, value);
+    JVMCIENV->put_object_at(vmConstants, insert++, name);
+    JVMCIENV->put_object_at(vmConstants, insert++, value);
   }
   assert(insert == len * 2, "must be");
 
   len = JVMCIVMStructs::localHotSpotVMAddresses_count();
-  objArrayHandle vmAddresses = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  JVMCIObjectArray vmAddresses = JVMCIENV->new_Object_array(len * 2, JVMCI_CHECK_NULL);
   for (int i = 0; i < len ; i++) {
     VMAddressEntry a = JVMCIVMStructs::localHotSpotVMAddresses[i];
     CSTRING_TO_JSTRING(name, a.name);
+    JVMCIObject value;
     BOXED_LONG(value, a.value);
-    vmAddresses->obj_at_put(i * 2, name());
-    vmAddresses->obj_at_put(i * 2 + 1, value);
+    JVMCIENV->put_object_at(vmAddresses, i * 2, name);
+    JVMCIENV->put_object_at(vmAddresses, i * 2 + 1, value);
   }
 
 #define COUNT_FLAG(ignore) +1
@@ -393,40 +374,32 @@
 #define CHECK_FLAG(type, name)
 #endif
 
-#define ADD_FLAG(type, name, convert) { \
-  CHECK_FLAG(type, name) \
-  instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
-  CSTRING_TO_JSTRING(fname, #name); \
-  CSTRING_TO_JSTRING(ftype, #type); \
-  VMFlag::set_name(vmFlagObj, fname()); \
-  VMFlag::set_type(vmFlagObj, ftype()); \
-  convert(value, name); \
-  VMFlag::set_value(vmFlagObj, value); \
-  vmFlags->obj_at_put(i++, vmFlagObj()); \
+#define ADD_FLAG(type, name, convert) {                                                \
+  CHECK_FLAG(type, name)                                                               \
+  CSTRING_TO_JSTRING(fname, #name);                                                    \
+  CSTRING_TO_JSTRING(ftype, #type);                                                    \
+  convert(value, name);                                                                \
+  JVMCIObject vmFlagObj = JVMCIENV->new_VMFlag(fname, ftype, value, JVMCI_CHECK_NULL); \
+  JVMCIENV->put_object_at(vmFlags, i++, vmFlagObj);                                    \
 }
 #define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_BOOLEAN)
 #define ADD_INTX_FLAG(name)  ADD_FLAG(intx, name, BOXED_LONG)
 #define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG)
 
   len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG);
-  objArrayHandle vmFlags = oopFactory::new_objArray_handle(VMFlag::klass(), len, CHECK_NULL);
+  JVMCIObjectArray vmFlags = JVMCIENV->new_VMFlag_array(len, JVMCI_CHECK_NULL);
   int i = 0;
+  JVMCIObject value;
   PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
 
-  objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
-
-  objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL);
-  data->obj_at_put(0, vmFields());
-  data->obj_at_put(1, vmConstants());
-  data->obj_at_put(2, vmAddresses());
-  data->obj_at_put(3, vmFlags());
-  data->obj_at_put(4, vmIntrinsics());
+  JVMCIObjectArray vmIntrinsics = CompilerToVM::initialize_intrinsics(JVMCI_CHECK_NULL);
 
-  return (jobjectArray) JNIHandles::make_local(THREAD, data);
-#undef COUNT_FLAG
-#undef ADD_FLAG
-#undef ADD_BOOL_FLAG
-#undef ADD_INTX_FLAG
-#undef ADD_UINTX_FLAG
-#undef CHECK_FLAG
+  JVMCIObjectArray data = JVMCIENV->new_Object_array(5, JVMCI_CHECK_NULL);
+  JVMCIENV->put_object_at(data, 0, vmFields);
+  JVMCIENV->put_object_at(data, 1, vmConstants);
+  JVMCIENV->put_object_at(data, 2, vmAddresses);
+  JVMCIENV->put_object_at(data, 3, vmFlags);
+  JVMCIENV->put_object_at(data, 4, vmIntrinsics);
+
+  return JVMCIENV->get_jobjectArray(data);
 }
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,44 +23,22 @@
  */
 
 #include "precompiled.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "classfile/javaAssertions.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "classfile/vmSymbols.hpp"
+#include "classfile/stringTable.hpp"
 #include "code/codeCache.hpp"
-#include "code/scopeDesc.hpp"
-#include "compiler/compileBroker.hpp"
-#include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
-#include "interpreter/linkResolver.hpp"
-#include "memory/allocation.inline.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
-#include "memory/universe.hpp"
-#include "oops/constantPool.inline.hpp"
-#include "oops/cpCache.inline.hpp"
-#include "oops/method.inline.hpp"
-#include "oops/methodData.hpp"
-#include "oops/objArrayKlass.hpp"
-#include "oops/oop.inline.hpp"
-#include "prims/jvmtiExport.hpp"
-#include "runtime/fieldDescriptor.inline.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/init.hpp"
-#include "runtime/reflection.hpp"
-#include "runtime/sharedRuntime.hpp"
-#include "runtime/sweeper.hpp"
-#include "utilities/dtrace.hpp"
+#include "oops/typeArrayOop.inline.hpp"
+#include "runtime/jniHandles.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 
-JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter):
+JVMCICompileState::JVMCICompileState(CompileTask* task, int system_dictionary_modification_counter):
   _task(task),
   _system_dictionary_modification_counter(system_dictionary_modification_counter),
   _retryable(true),
   _failure_reason(NULL),
-  _failure_reason_on_C_heap(false)
-{
+  _failure_reason_on_C_heap(false) {
   // Get Jvmti capabilities under lock to get consistent values.
   MutexLocker mu(JvmtiThreadState_lock);
   _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0;
@@ -69,7 +47,7 @@
   _jvmti_can_pop_frame                  = JvmtiExport::can_pop_frame() ? 1 : 0;
 }
 
-bool JVMCIEnv::jvmti_state_changed() const {
+bool JVMCICompileState::jvmti_state_changed() const {
   if (!jvmti_can_access_local_variables() &&
       JvmtiExport::can_access_local_variables()) {
     return true;
@@ -89,532 +67,1587 @@
   return false;
 }
 
-// ------------------------------------------------------------------
-// Note: the logic of this method should mirror the logic of
-// constantPoolOopDesc::verify_constant_pool_resolve.
-bool JVMCIEnv::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) {
-  if (accessing_klass->is_objArray_klass()) {
-    accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass();
-  }
-  if (!accessing_klass->is_instance_klass()) {
-    return true;
-  }
+JavaVM* JVMCIEnv::_shared_library_javavm = NULL;
+void* JVMCIEnv::_shared_library_handle = NULL;
+char* JVMCIEnv::_shared_library_path = NULL;
 
-  if (resolved_klass->is_objArray_klass()) {
-    // Find the element klass, if this is an array.
-    resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
-  }
-  if (resolved_klass->is_instance_klass()) {
-    Reflection::VerifyClassAccessResults result =
-      Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true);
-    return result == Reflection::ACCESS_OK;
-  }
-  return true;
-}
+void JVMCIEnv::copy_saved_properties() {
+  assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
+
+  JavaThread* THREAD = JavaThread::current();
 
-// ------------------------------------------------------------------
-Klass* JVMCIEnv::get_klass_by_name_impl(Klass* accessing_klass,
-                                        const constantPoolHandle& cpool,
-                                        Symbol* sym,
-                                        bool require_local) {
-  JVMCI_EXCEPTION_CONTEXT;
-
-  // Now we need to check the SystemDictionary
-  if (sym->char_at(0) == 'L' &&
-    sym->char_at(sym->utf8_length()-1) == ';') {
-    // This is a name from a signature.  Strip off the trimmings.
-    // Call recursive to keep scope of strippedsym.
-    TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
-                    sym->utf8_length()-2,
-                    CHECK_NULL);
-    return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_services_Services(), Handle(), Handle(), true, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services");
   }
-
-  Handle loader(THREAD, (oop)NULL);
-  Handle domain(THREAD, (oop)NULL);
-  if (accessing_klass != NULL) {
-    loader = Handle(THREAD, accessing_klass->class_loader());
-    domain = Handle(THREAD, accessing_klass->protection_domain());
-  }
-
-  Klass* found_klass = NULL;
-  {
-    ttyUnlocker ttyul;  // release tty lock to avoid ordering problems
-    MutexLocker ml(Compile_lock);
-    if (!require_local) {
-      found_klass = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_NULL);
-    } else {
-      found_klass = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_NULL);
+  InstanceKlass* ik = InstanceKlass::cast(k);
+  if (ik->should_be_initialized()) {
+    ik->initialize(THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services");
     }
   }
 
-  // If we fail to find an array klass, look again for its element type.
-  // The element type may be available either locally or via constraints.
-  // In either case, if we can find the element type in the system dictionary,
-  // we must build an array type around it.  The CI requires array klasses
-  // to be loaded if their element klasses are loaded, except when memory
-  // is exhausted.
-  if (sym->char_at(0) == '[' &&
-      (sym->char_at(1) == '[' || sym->char_at(1) == 'L')) {
-    // We have an unloaded array.
-    // Build it on the fly if the element class exists.
-    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
-                                                 sym->utf8_length()-1,
-                                                 CHECK_NULL);
+  // Get the serialized saved properties from HotSpot
+  TempNewSymbol serializeSavedProperties = SymbolTable::new_symbol("serializeSavedProperties", CHECK_EXIT);
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::serializePropertiesToByteArray_signature(), &args, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    JVMCIRuntime::exit_on_pending_exception(NULL, "Error calling jdk.vm.ci.services.Services.serializeSavedProperties");
+  }
+  oop res = (oop) result.get_jobject();
+  assert(res->is_typeArray(), "must be");
+  assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be");
+  typeArrayOop ba = typeArrayOop(res);
+  int serialized_properties_len = ba->length();
+
+  // Copy serialized saved properties from HotSpot object into native buffer
+  jbyte* serialized_properties = NEW_RESOURCE_ARRAY(jbyte, serialized_properties_len);
+  memcpy(serialized_properties, ba->byte_at_addr(0), serialized_properties_len);
+
+  // Copy native buffer into shared library object
+  JVMCIPrimitiveArray buf = new_byteArray(serialized_properties_len, this);
+  if (has_pending_exception()) {
+    describe_pending_exception(true);
+    fatal("Error in copy_saved_properties");
+  }
+  copy_bytes_from(serialized_properties, buf, 0, serialized_properties_len);
+  if (has_pending_exception()) {
+    describe_pending_exception(true);
+    fatal("Error in copy_saved_properties");
+  }
+
+  // Initialize saved properties in shared library
+  jclass servicesClass = JNIJVMCI::Services::clazz();
+  jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method();
+  JNIAccessMark jni(this);
+  jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject());
+  if (jni()->ExceptionCheck()) {
+    jni()->ExceptionDescribe();
+    fatal("Error calling jdk.vm.ci.services.Services.initializeSavedProperties");
+  }
+}
 
-    // Get element Klass recursively.
-    Klass* elem_klass =
-      get_klass_by_name_impl(accessing_klass,
-                             cpool,
-                             elem_sym,
-                             require_local);
-    if (elem_klass != NULL) {
-      // Now make an array for it
-      return elem_klass->array_klass(THREAD);
+JNIEnv* JVMCIEnv::attach_shared_library() {
+  if (_shared_library_javavm == NULL) {
+    MutexLocker locker(JVMCI_lock);
+    if (_shared_library_javavm == NULL) {
+
+      char path[JVM_MAXPATHLEN];
+      char ebuf[1024];
+      if (JVMCILibPath != NULL) {
+        if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) {
+          vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath);
+        }
+      } else {
+        if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
+          vm_exit_during_initialization("Unable to create path to JVMCI shared library");
+        }
+      }
+
+      void* handle = os::dll_load(path, ebuf, sizeof ebuf);
+      if (handle == NULL) {
+        vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf);
+      }
+      _shared_library_handle = handle;
+      _shared_library_path = strdup(path);
+      jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
+      typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
+
+      JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM"));
+      JNIEnv* env;
+      if (JNI_CreateJavaVM == NULL) {
+        vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path);
+      }
+
+      ResourceMark rm;
+      JavaVMInitArgs vm_args;
+      vm_args.version = JNI_VERSION_1_2;
+      vm_args.ignoreUnrecognized = JNI_TRUE;
+      vm_args.options = NULL;
+      vm_args.nOptions = 0;
+
+      JavaVM* the_javavm = NULL;
+      int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args);
+      if (result == JNI_OK) {
+        guarantee(env != NULL, "missing env");
+        _shared_library_javavm = the_javavm;
+        return env;
+      } else {
+        vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path);
+      }
     }
   }
+  JNIEnv* env;
+  if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) {
+    guarantee(env != NULL, "missing env");
+    return env;
+  }
+  fatal("Error attaching current thread to JVMCI shared library JNI interface");
+  return NULL;
+}
 
-  if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) {
-    // Look inside the constant pool for pre-resolved class entries.
-    for (int i = cpool->length() - 1; i >= 1; i--) {
-      if (cpool->tag_at(i).is_klass()) {
-        Klass*  kls = cpool->resolved_klass_at(i);
-        if (kls->name() == sym) {
-          return kls;
-        }
-      }
+void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) {
+  // By default there is only one runtime which is the compiler runtime.
+  _runtime = JVMCI::compiler_runtime();
+  if (!UseJVMCINativeLibrary) {
+    // In HotSpot mode, JNI isn't used at all.
+    _is_hotspot = true;
+    _env = NULL;
+    return;
+  }
+
+  if (parent_env != NULL) {
+    // If the parent JNI environment is non-null then figure out whether it
+    // is a HotSpot or shared library JNIEnv and set the state appropriately.
+    JavaThread* thread = JavaThread::current();
+    if (thread->jni_environment() == parent_env) {
+      // Select the Java runtime
+      _runtime = JVMCI::java_runtime();
+      _is_hotspot = true;
+      _env = NULL;
+      return;
     }
   }
 
-  return found_klass;
+  // Running in JVMCI shared library mode so get a shared library JNIEnv
+  _is_hotspot = false;
+  _env = attach_shared_library();
+  assert(parent_env == NULL || _env == parent_env, "must be");
+
+  if (parent_env == NULL) {
+    // There is no parent shared library JNI env so push
+    // a JNI local frame to release all local handles in
+    // this JVMCIEnv scope when it's closed.
+    assert(_throw_to_caller == false, "must be");
+    JNIAccessMark jni(this);
+    jint result = _env->PushLocalFrame(32);
+    if (result != JNI_OK) {
+      char message[256];
+      jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
+      JVMCIRuntime::exit_on_pending_exception(this, message);
+    }
+  }
+}
+
+JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line):
+    _throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
+  init_env_mode_runtime(NULL);
+}
+
+JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
+    _throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
+  init_env_mode_runtime(NULL);
+}
+
+JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line):
+    _throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
+  init_env_mode_runtime(parent_env);
+  assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
 }
 
-// ------------------------------------------------------------------
-Klass* JVMCIEnv::get_klass_by_name(Klass* accessing_klass,
-                                  Symbol* klass_name,
-                                  bool require_local) {
-  ResourceMark rm;
-  constantPoolHandle cpool;
-  return get_klass_by_name_impl(accessing_klass,
-                                cpool,
-                                klass_name,
-                                require_local);
+void JVMCIEnv::init(bool is_hotspot, const char* file, int line) {
+  _compile_state = NULL;
+  _throw_to_caller = false;
+  _file = file;
+  _line = line;
+  if (is_hotspot) {
+    _env = NULL;
+    _is_hotspot = true;
+    _runtime = JVMCI::java_runtime();
+  } else {
+    init_env_mode_runtime(NULL);
+  }
 }
 
-// ------------------------------------------------------------------
-// Implementation of get_klass_by_index.
-Klass* JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool,
-                                        int index,
-                                        bool& is_accessible,
-                                        Klass* accessor) {
-  JVMCI_EXCEPTION_CONTEXT;
-  Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index);
-  Symbol* klass_name = NULL;
-  if (klass == NULL) {
-    klass_name = cpool->klass_name_at(index);
+// Prints a pending exception (if any) and its stack trace.
+void JVMCIEnv::describe_pending_exception(bool clear) {
+  if (!is_hotspot()) {
+    JNIAccessMark jni(this);
+    if (jni()->ExceptionCheck()) {
+      jthrowable ex = !clear ? jni()->ExceptionOccurred() : NULL;
+      jni()->ExceptionDescribe();
+      if (ex != NULL) {
+        jni()->Throw(ex);
+      }
+    }
+  } else {
+    Thread* THREAD = Thread::current();
+    if (HAS_PENDING_EXCEPTION) {
+      JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear);
+    }
+  }
+}
+
+void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable) {
+  assert(!is_hotspot(), "must_be");
+  // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets
+  // may not have been called.
+  Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK);
+  JavaCallArguments jargs;
+  jargs.push_oop(throwable);
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result,
+                          runtimeKlass,
+                          vmSymbols::encodeThrowable_name(),
+                          vmSymbols::encodeThrowable_signature(), &jargs, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    JVMCIRuntime::exit_on_pending_exception(this, "HotSpotJVMCIRuntime.encodeThrowable should not throw an exception");
   }
 
-  if (klass == NULL) {
-    // Not found in constant pool.  Use the name to do the lookup.
-    Klass* k = get_klass_by_name_impl(accessor,
-                                      cpool,
-                                      klass_name,
-                                      false);
-    // Calculate accessibility the hard way.
-    if (k == NULL) {
-      is_accessible = false;
-    } else if (k->class_loader() != accessor->class_loader() &&
-               get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) {
-      // Loaded only remotely.  Not linked yet.
-      is_accessible = false;
+  oop encoded_throwable_string = (oop) result.get_jobject();
+
+  ResourceMark rm;
+  const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string);
+
+  JNIAccessMark jni(this);
+  jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars);
+  jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
+                                JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(),
+                                jni_encoded_throwable_string);
+  jni()->Throw(jni_throwable);
+}
+
+JVMCIEnv::~JVMCIEnv() {
+  if (_throw_to_caller) {
+    if (is_hotspot()) {
+      // Nothing to do
     } else {
-      // Linked locally, and we must also check public/private, etc.
-      is_accessible = check_klass_accessibility(accessor, k);
+      if (Thread::current()->is_Java_thread()) {
+        JavaThread* THREAD = JavaThread::current();
+        if (HAS_PENDING_EXCEPTION) {
+          Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
+          CLEAR_PENDING_EXCEPTION;
+          translate_hotspot_exception_to_jni_exception(THREAD, throwable);
+        }
+      }
     }
-    if (!is_accessible) {
-      return NULL;
+  } else {
+    if (!is_hotspot()) {
+      // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
+      JNIAccessMark jni(this);
+      jni()->PopLocalFrame(NULL);
+    }
+
+    if (has_pending_exception()) {
+      char message[256];
+      jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
+      JVMCIRuntime::exit_on_pending_exception(this, message);
     }
-    return k;
+  }
+}
+
+jboolean JVMCIEnv::has_pending_exception() {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    return HAS_PENDING_EXCEPTION;
+  } else {
+    JNIAccessMark jni(this);
+    return jni()->ExceptionCheck();
   }
+}
+
+void JVMCIEnv::clear_pending_exception() {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    CLEAR_PENDING_EXCEPTION;
+  } else {
+    JNIAccessMark jni(this);
+    jni()->ExceptionClear();
+  }
+}
 
-  // It is known to be accessible, since it was found in the constant pool.
-  is_accessible = true;
-  return klass;
+int JVMCIEnv::get_length(JVMCIArray array) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(array)->length();
+  } else {
+    JNIAccessMark jni(this);
+    return jni()->GetArrayLength(get_jarray(array));
+  }
+}
+
+JVMCIObject JVMCIEnv::get_object_at(JVMCIObjectArray array, int index) {
+  if (is_hotspot()) {
+    oop result = HotSpotJVMCI::resolve(array)->obj_at(index);
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->GetObjectArrayElement(get_jobjectArray(array), index);
+    return wrap(result);
+  }
+}
+
+void JVMCIEnv::put_object_at(JVMCIObjectArray array, int index, JVMCIObject value) {
+  if (is_hotspot()) {
+    HotSpotJVMCI::resolve(array)->obj_at_put(index, HotSpotJVMCI::resolve(value));
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetObjectArrayElement(get_jobjectArray(array), index, get_jobject(value));
+  }
 }
 
-// ------------------------------------------------------------------
-// Get a klass from the constant pool.
-Klass* JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool,
-                                    int index,
-                                    bool& is_accessible,
-                                    Klass* accessor) {
-  ResourceMark rm;
-  return get_klass_by_index_impl(cpool, index, is_accessible, accessor);
+jboolean JVMCIEnv::get_bool_at(JVMCIPrimitiveArray array, int index) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(array)->bool_at(index);
+  } else {
+    JNIAccessMark jni(this);
+    jboolean result;
+    jni()->GetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &result);
+    return result;
+  }
+}
+void JVMCIEnv::put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value) {
+  if (is_hotspot()) {
+    HotSpotJVMCI::resolve(array)->bool_at_put(index, value);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &value);
+  }
+}
+
+jbyte JVMCIEnv::get_byte_at(JVMCIPrimitiveArray array, int index) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(array)->byte_at(index);
+  } else {
+    JNIAccessMark jni(this);
+    jbyte result;
+    jni()->GetByteArrayRegion(array.as_jbyteArray(), index, 1, &result);
+    return result;
+  }
+}
+void JVMCIEnv::put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value) {
+  if (is_hotspot()) {
+    HotSpotJVMCI::resolve(array)->byte_at_put(index, value);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetByteArrayRegion(array.as_jbyteArray(), index, 1, &value);
+  }
+}
+
+jint JVMCIEnv::get_int_at(JVMCIPrimitiveArray array, int index) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(array)->int_at(index);
+  } else {
+    JNIAccessMark jni(this);
+    jint result;
+    jni()->GetIntArrayRegion(array.as_jintArray(), index, 1, &result);
+    return result;
+  }
+}
+void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) {
+  if (is_hotspot()) {
+    HotSpotJVMCI::resolve(array)->int_at_put(index, value);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetIntArrayRegion(array.as_jintArray(), index, 1, &value);
+  }
+}
+
+long JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(array)->long_at(index);
+  } else {
+    JNIAccessMark jni(this);
+    jlong result;
+    jni()->GetLongArrayRegion(array.as_jlongArray(), index, 1, &result);
+    return result;
+  }
+}
+void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
+  if (is_hotspot()) {
+    HotSpotJVMCI::resolve(array)->long_at_put(index, value);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetLongArrayRegion(array.as_jlongArray(), index, 1, &value);
+  }
+}
+
+void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes) {
+  if (size_in_bytes == 0) {
+    return;
+  }
+  if (is_hotspot()) {
+    memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest);
+  }
+}
+void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) {
+  if (size_in_bytes == 0) {
+    return;
+  }
+  if (is_hotspot()) {
+    memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src);
+  }
 }
 
-// ------------------------------------------------------------------
-// Implementation of get_field_by_index.
-//
-// Implementation note: the results of field lookups are cached
-// in the accessor klass.
-void JVMCIEnv::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc,
-                                        int index) {
-  JVMCI_EXCEPTION_CONTEXT;
+jboolean JVMCIEnv::is_boxing_object(BasicType type, JVMCIObject object) {
+  if (is_hotspot()) {
+    return java_lang_boxing_object::is_instance(HotSpotJVMCI::resolve(object), type);
+  } else {
+    JNIAccessMark jni(this);
+    return jni()->IsInstanceOf(get_jobject(object), JNIJVMCI::box_class(type));
+  }
+}
+
+// Get the primitive value from a Java boxing object.  It's hard error to
+// pass a non-primitive BasicType.
+jvalue JVMCIEnv::get_boxed_value(BasicType type, JVMCIObject object) {
+  jvalue result;
+  if (is_hotspot()) {
+    if (java_lang_boxing_object::get_value(HotSpotJVMCI::resolve(object), &result) == T_ILLEGAL) {
+      ShouldNotReachHere();
+    }
+  } else {
+    JNIAccessMark jni(this);
+    jfieldID field = JNIJVMCI::box_field(type);
+    switch (type) {
+      case T_BOOLEAN: result.z = jni()->GetBooleanField(get_jobject(object), field); break;
+      case T_BYTE:    result.b = jni()->GetByteField(get_jobject(object), field); break;
+      case T_SHORT:   result.s = jni()->GetShortField(get_jobject(object), field); break;
+      case T_CHAR:    result.c = jni()->GetCharField(get_jobject(object), field); break;
+      case T_INT:     result.i = jni()->GetIntField(get_jobject(object), field); break;
+      case T_LONG:    result.j = jni()->GetLongField(get_jobject(object), field); break;
+      case T_FLOAT:   result.f = jni()->GetFloatField(get_jobject(object), field); break;
+      case T_DOUBLE:  result.d = jni()->GetDoubleField(get_jobject(object), field); break;
+      default:
+        ShouldNotReachHere();
+    }
+  }
+  return result;
+}
+
+// Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
+BasicType JVMCIEnv::get_box_type(JVMCIObject object) {
+  if (is_hotspot()) {
+    return java_lang_boxing_object::basic_type(HotSpotJVMCI::resolve(object));
+  } else {
+    JNIAccessMark jni(this);
+    jclass clazz = jni()->GetObjectClass(get_jobject(object));
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BOOLEAN))) return T_BOOLEAN;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BYTE))) return T_BYTE;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_SHORT))) return T_SHORT;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_CHAR))) return T_CHAR;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_INT))) return T_INT;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_LONG))) return T_LONG;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_FLOAT))) return T_FLOAT;
+    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_DOUBLE))) return T_DOUBLE;
+    return T_ILLEGAL;
+  }
+}
 
-  assert(klass->is_linked(), "must be linked before using its constant-pool");
+// Create a boxing object of the appropriate primitive type.
+JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
+  switch (type) {
+    case T_BOOLEAN:
+    case T_BYTE:
+    case T_CHAR:
+    case T_SHORT:
+    case T_INT:
+    case T_LONG:
+    case T_FLOAT:
+    case T_DOUBLE:
+      break;
+    default:
+      JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
+  }
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
+    return HotSpotJVMCI::wrap(box);
+  } else {
+    JNIAccessMark jni(this);
+    jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
+    assert(box != NULL, "");
+    return wrap(box);
+  }
+}
 
-  constantPoolHandle cpool(thread, klass->constants());
+const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
+  if (is_hotspot()) {
+    return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
+  } else {
+    JNIAccessMark jni(this);
+    int length = jni()->GetStringLength(str.as_jstring());
+    char* result = NEW_RESOURCE_ARRAY(char, length + 1);
+    jni()->GetStringUTFRegion(str.as_jstring(), 0, length, result);
+    return result;
+  }
+}
 
-  // Get the field's name, signature, and type.
-  Symbol* name  = cpool->name_ref_at(index);
+char* JVMCIEnv::as_utf8_string(JVMCIObject str, char* buf, int buflen) {
+  if (is_hotspot()) {
+    return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str), buf, buflen);
+  } else {
+    JNIAccessMark jni(this);
+    int length = jni()->GetStringLength(str.as_jstring());
+    if (length >= buflen) {
+      length = buflen;
+    }
+    jni()->GetStringUTFRegion(str.as_jstring(), 0, length, buf);
+    return buf;
+  }
+}
+
+#define DO_THROW(name)                             \
+void JVMCIEnv::throw_##name(const char* msg) {     \
+  if (is_hotspot()) {                              \
+    JavaThread* THREAD = JavaThread::current();    \
+    THROW_MSG(HotSpotJVMCI::name::symbol(), msg);  \
+  } else {                                         \
+    JNIAccessMark jni(this);                       \
+    jni()->ThrowNew(JNIJVMCI::name::clazz(), msg); \
+  }                                                \
+}
+
+DO_THROW(InternalError)
+DO_THROW(ArrayIndexOutOfBoundsException)
+DO_THROW(IllegalStateException)
+DO_THROW(NullPointerException)
+DO_THROW(IllegalArgumentException)
+DO_THROW(InvalidInstalledCodeException)
+DO_THROW(UnsatisfiedLinkError)
+
+#undef DO_THROW
 
-  int nt_index = cpool->name_and_type_ref_index_at(index);
-  int sig_index = cpool->signature_ref_index_at(nt_index);
-  Symbol* signature = cpool->symbol_at(sig_index);
+void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) {
+  const int max_msg_size = 1024;
+  va_list ap;
+  va_start(ap, format);
+  char msg[max_msg_size];
+  vsnprintf(msg, max_msg_size, format, ap);
+  msg[max_msg_size-1] = '\0';
+  va_end(ap);
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    Handle h_loader = Handle();
+    Handle h_protection_domain = Handle();
+    Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
+  }
+}
+
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
+                                                              jlong compile_state, int id) {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    JavaCallArguments jargs;
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method)));
+    jargs.push_int(entry_bci);
+    jargs.push_long(compile_state);
+    jargs.push_int(id);
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_special(&result,
+                            HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
+                            vmSymbols::compileMethod_name(),
+                            vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(),
+                                                     JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
+                                                     JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(),
+                                                     method.as_jobject(), entry_bci, compile_state, id);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
+
+void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    JavaCallArguments jargs;
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
+    JavaValue result(T_VOID);
+    JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());
+
+  }
+}
 
-  // Get the field's declared holder.
-  int holder_index = cpool->klass_ref_index_at(index);
-  bool holder_is_accessible;
-  Klass* declared_holder = get_klass_by_index(cpool, holder_index,
-                                              holder_is_accessible,
-                                              klass);
+void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
+  HandleMark hm;
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
+    JavaValue result(T_VOID);
+    JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method());
+  }
+  if (has_pending_exception()) {
+    // This should never happen as HotSpotJVMCIRuntime.shutdown() should
+    // handle all exceptions.
+    describe_pending_exception(true);
+  }
+}
 
-  // The declared holder of this field may not have been loaded.
-  // Bail out with partial field information.
-  if (!holder_is_accessible) {
-    return;
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
   }
+}
+
+JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
 
 
-  // Perform the field lookup.
-  Klass*  canonical_holder =
-    InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc);
-  if (canonical_holder == NULL) {
-    return;
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
+                           vmSymbols::callToString_name(),
+                           vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
+                                                     JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(),
+                                                     object.as_jobject());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
   }
-
-  assert(canonical_holder == field_desc.field_holder(), "just checking");
-}
-
-// ------------------------------------------------------------------
-// Get a field by index from a klass's constant pool.
-void JVMCIEnv::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index) {
-  ResourceMark rm;
-  return get_field_by_index_impl(accessor, fd, index);
-}
-
-// ------------------------------------------------------------------
-// Perform an appropriate method lookup based on accessor, holder,
-// name, signature, and bytecode.
-methodHandle JVMCIEnv::lookup_method(InstanceKlass* accessor,
-                               Klass*         holder,
-                               Symbol*        name,
-                               Symbol*        sig,
-                               Bytecodes::Code bc,
-                               constantTag   tag) {
-  // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl().
-  assert(check_klass_accessibility(accessor, holder), "holder not accessible");
-
-  methodHandle dest_method;
-  LinkInfo link_info(holder, name, sig, accessor, LinkInfo::needs_access_check, tag);
-  switch (bc) {
-  case Bytecodes::_invokestatic:
-    dest_method =
-      LinkResolver::resolve_static_call_or_null(link_info);
-    break;
-  case Bytecodes::_invokespecial:
-    dest_method =
-      LinkResolver::resolve_special_call_or_null(link_info);
-    break;
-  case Bytecodes::_invokeinterface:
-    dest_method =
-      LinkResolver::linktime_resolve_interface_method_or_null(link_info);
-    break;
-  case Bytecodes::_invokevirtual:
-    dest_method =
-      LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
-    break;
-  default: ShouldNotReachHere();
-  }
-
-  return dest_method;
 }
 
 
-// ------------------------------------------------------------------
-methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
-                                          int index, Bytecodes::Code bc,
-                                          InstanceKlass* accessor) {
-  if (bc == Bytecodes::_invokedynamic) {
-    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
-    bool is_resolved = !cpce->is_f1_null();
-    if (is_resolved) {
-      // Get the invoker Method* from the constant pool.
-      // (The appendix argument, if any, will be noted in the method's signature.)
-      Method* adapter = cpce->f1_as_method();
-      return methodHandle(adapter);
+JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_int(kind);
+    jargs.push_long(value);
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::PrimitiveConstant::klass(),
+                           vmSymbols::forTypeChar_name(),
+                           vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(),
+                                                     JNIJVMCI::PrimitiveConstant::forTypeChar_method(),
+                                                     kind, value);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_float(value);
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::JavaConstant::klass(),
+                           vmSymbols::forFloat_name(),
+                           vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
+                                                     JNIJVMCI::JavaConstant::forFloat_method(),
+                                                     value);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    jargs.push_double(value);
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::JavaConstant::klass(),
+                           vmSymbols::forDouble_name(),
+                           vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
+                                                     JNIJVMCI::JavaConstant::forDouble_method(),
+                                                     value);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type) {
+  JVMCIObjectArray primitives = get_HotSpotResolvedPrimitiveType_primitives();
+  JVMCIObject result = get_object_at(primitives, type);
+  return result;
+}
+
+JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) {
+  JavaThread* THREAD = JavaThread::current();
+  Symbol* method_name_sym;
+  Symbol* file_name_sym;
+  int line_number;
+  Handle mirror (THREAD, method->method_holder()->java_mirror());
+  java_lang_StackTraceElement::decode(mirror, method, bci, method_name_sym, file_name_sym, line_number);
+
+  InstanceKlass* holder = method->method_holder();
+  const char* declaring_class_str = holder->external_name();
+
+  if (is_hotspot()) {
+    HotSpotJVMCI::StackTraceElement::klass()->initialize(CHECK_(JVMCIObject()));
+    oop objOop = HotSpotJVMCI::StackTraceElement::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    Handle obj = Handle(THREAD, objOop);
+
+    oop declaring_class = StringTable::intern((char*) declaring_class_str, CHECK_(JVMCIObject()));
+    HotSpotJVMCI::StackTraceElement::set_declaringClass(this, obj(), declaring_class);
+
+    oop method_name = StringTable::intern(method_name_sym, CHECK_(JVMCIObject()));
+    HotSpotJVMCI::StackTraceElement::set_methodName(this, obj(), method_name);
+
+    if (file_name_sym != NULL) {
+      oop file_name = StringTable::intern(file_name_sym, CHECK_(JVMCIObject()));
+      HotSpotJVMCI::StackTraceElement::set_fileName(this, obj(), file_name);
+    }
+    HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number);
+    return wrap(obj());
+  } else {
+    JNIAccessMark jni(this);
+    jobject declaring_class = jni()->NewStringUTF(declaring_class_str);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    jobject method_name = jni()->NewStringUTF(method_name_sym->as_C_string());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    jobject file_name = NULL;
+    if (file_name != NULL) {
+      file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
+      if (jni()->ExceptionCheck()) {
+        return JVMCIObject();
+      }
     }
 
-    return NULL;
+    jobject result = jni()->NewObject(JNIJVMCI::StackTraceElement::clazz(),
+                                      JNIJVMCI::StackTraceElement::constructor(),
+                                      declaring_class, method_name, file_name, line_number);
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) {
+  JavaThread* THREAD = JavaThread::current();
+
+  JVMCIObject methodObject = get_jvmci_method(method(), JVMCI_CHECK_(JVMCIObject()));
+
+  if (is_hotspot()) {
+    InstanceKlass* ik = InstanceKlass::cast(HotSpotJVMCI::HotSpotNmethod::klass());
+    if (ik->should_be_initialized()) {
+      ik->initialize(CHECK_(JVMCIObject()));
+    }
+    oop obj = ik->allocate_instance(CHECK_(JVMCIObject()));
+    Handle obj_h(THREAD, obj);
+    Handle nameStr = java_lang_String::create_from_str(name, CHECK_(JVMCIObject()));
+
+    // Call constructor
+    JavaCallArguments jargs;
+    jargs.push_oop(obj_h);
+    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject)));
+    jargs.push_oop(nameStr);
+    jargs.push_int(isDefault);
+    jargs.push_long(compileId);
+    JavaValue result(T_VOID);
+    JavaCalls::call_special(&result, ik,
+                            vmSymbols::object_initializer_name(),
+                            vmSymbols::method_string_bool_long_signature(),
+                            &jargs, CHECK_(JVMCIObject()));
+    return wrap(obj_h());
+  } else {
+    JNIAccessMark jni(this);
+    jobject nameStr = name == NULL ? NULL : jni()->NewStringUTF(name);
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+
+    jobject result = jni()->NewObject(JNIJVMCI::HotSpotNmethod::clazz(),
+                                      JNIJVMCI::HotSpotNmethod::constructor(),
+                                      methodObject.as_jobject(), nameStr, isDefault);
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::make_local(JVMCIObject object) {
+  if (object.is_null()) {
+    return JVMCIObject();
+  }
+  if (is_hotspot()) {
+    return wrap(JNIHandles::make_local(HotSpotJVMCI::resolve(object)));
+  } else {
+    JNIAccessMark jni(this);
+    return wrap(jni()->NewLocalRef(object.as_jobject()));
+  }
+}
+
+JVMCIObject JVMCIEnv::make_global(JVMCIObject object) {
+  if (object.is_null()) {
+    return JVMCIObject();
+  }
+  if (is_hotspot()) {
+    return wrap(JNIHandles::make_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
+  } else {
+    JNIAccessMark jni(this);
+    return wrap(jni()->NewGlobalRef(object.as_jobject()));
+  }
+}
+
+JVMCIObject JVMCIEnv::make_weak(JVMCIObject object) {
+  if (object.is_null()) {
+    return JVMCIObject();
+  }
+  if (is_hotspot()) {
+    return wrap(JNIHandles::make_weak_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
+  } else {
+    JNIAccessMark jni(this);
+    return wrap(jni()->NewWeakGlobalRef(object.as_jobject()));
+  }
+}
+
+void JVMCIEnv::destroy_local(JVMCIObject object) {
+  if (is_hotspot()) {
+    JNIHandles::destroy_local(object.as_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jni()->DeleteLocalRef(object.as_jobject());
+  }
+}
+
+void JVMCIEnv::destroy_global(JVMCIObject object) {
+  if (is_hotspot()) {
+    JNIHandles::destroy_global(object.as_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jni()->DeleteGlobalRef(object.as_jobject());
+  }
+}
+
+void JVMCIEnv::destroy_weak(JVMCIObject object) {
+  if (is_hotspot()) {
+    JNIHandles::destroy_weak_global(object.as_jweak());
+  } else {
+    JNIAccessMark jni(this);
+    jni()->DeleteWeakGlobalRef(object.as_jweak());
+  }
+}
+
+const char* JVMCIEnv::klass_name(JVMCIObject object) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(object)->klass()->signature_name();
+  } else {
+    JVMCIObject name;
+    {
+      JNIAccessMark jni(this);
+      jclass jcl = jni()->GetObjectClass(object.as_jobject());
+      jobject result = jni()->CallObjectMethod(jcl, JNIJVMCI::Class_getName_method());
+      name = JVMCIObject::create(result, is_hotspot());
+    }
+    return as_utf8_string(name);
+  }
+}
+
+JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) {
+  JVMCIObject method_object;
+  if (method() == NULL) {
+    return method_object;
   }
 
-  int holder_index = cpool->klass_ref_index_at(index);
-  bool holder_is_accessible;
-  Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+  Thread* THREAD = Thread::current();
+  jmetadata handle = JVMCI::allocate_handle(method);
+  jboolean exception = false;
+  if (is_hotspot()) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_long((jlong) handle);
+    JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(),
+                           vmSymbols::fromMetaspace_name(),
+                           vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      exception = true;
+    } else {
+      method_object = wrap((oop)result.get_jobject());
+    }
+  } else {
+    JNIAccessMark jni(this);
+    method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
+                                                                  JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
+                                                                  (jlong) handle));
+    exception = jni()->ExceptionCheck();
+  }
 
-  // Get the method's name and signature.
-  Symbol* name_sym = cpool->name_ref_at(index);
-  Symbol* sig_sym  = cpool->signature_ref_at(index);
+  if (exception) {
+    JVMCI::release_handle(handle);
+    return JVMCIObject();
+  }
+
+  assert(asMethod(method_object) == method(), "must be");
+  if (get_HotSpotResolvedJavaMethodImpl_metadataHandle(method_object) != (jlong) handle) {
+    JVMCI::release_handle(handle);
+  }
+  assert(!method_object.is_null(), "must be");
+  return method_object;
+}
+
+JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) {
+  JVMCIObject type;
+  if (klass.is_null()) {
+    return type;
+  }
+#ifdef INCLUDE_ALL_GCS
+    if (UseG1GC) {
+      // The klass might have come from a weak location so enqueue
+      // the Class to make sure it's noticed by G1
+      G1SATBCardTableModRefBS::enqueue(klass()->java_mirror());
+    }
+#endif  // Klass* don't require tracking as Metadata*
 
-  if (cpool->has_preresolution()
-      || ((holder == SystemDictionary::MethodHandle_klass() || holder == SystemDictionary::VarHandle_klass()) &&
-          MethodHandles::is_signature_polymorphic_name(holder, name_sym))) {
-    // Short-circuit lookups for JSR 292-related call sites.
-    // That is, do not rely only on name-based lookups, because they may fail
-    // if the names are not resolvable in the boot class loader (7056328).
-    switch (bc) {
-    case Bytecodes::_invokevirtual:
-    case Bytecodes::_invokeinterface:
-    case Bytecodes::_invokespecial:
-    case Bytecodes::_invokestatic:
-      {
-        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
-        if (m != NULL) {
-          return m;
-        }
-      }
-      break;
-    default:
-      break;
+  jlong pointer = (jlong) klass();
+  JavaThread* THREAD = JavaThread::current();
+  JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject()));
+  jboolean exception = false;
+  if (is_hotspot()) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_long(pointer);
+    args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(signature)));
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::HotSpotResolvedObjectTypeImpl::klass(),
+                           vmSymbols::fromMetaspace_name(),
+                           vmSymbols::klass_fromMetaspace_signature(), &args, THREAD);
+
+    if (HAS_PENDING_EXCEPTION) {
+      exception = true;
+    } else {
+      type = wrap((oop)result.get_jobject());
     }
+  } else {
+    JNIAccessMark jni(this);
+
+    HandleMark hm(THREAD);
+    type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
+                                                        JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(),
+                                                        pointer, signature.as_jstring()));
+    exception = jni()->ExceptionCheck();
+  }
+  if (exception) {
+    return JVMCIObject();
+  }
+
+  assert(type.is_non_null(), "must have result");
+  return type;
+}
+
+JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
+  JVMCIObject cp_object;
+  jmetadata handle = JVMCI::allocate_handle(cp);
+  jboolean exception = false;
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_long((jlong) handle);
+    JavaCalls::call_static(&result,
+                           HotSpotJVMCI::HotSpotConstantPool::klass(),
+                           vmSymbols::fromMetaspace_name(),
+                           vmSymbols::constantPool_fromMetaspace_signature(), &args, THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      exception = true;
+    } else {
+      cp_object = wrap((oop)result.get_jobject());
+    }
+  } else {
+    JNIAccessMark jni(this);
+    cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
+                                                             JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
+                                                             (jlong) handle));
+    exception = jni()->ExceptionCheck();
+  }
+
+  if (exception) {
+    JVMCI::release_handle(handle);
+    return JVMCIObject();
   }
 
-  if (holder_is_accessible) { // Our declared holder is loaded.
-    constantTag tag = cpool->tag_ref_at(index);
-    methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);
-    if (!m.is_null()) {
-      // We found the method.
-      return m;
-    }
+  assert(!cp_object.is_null(), "must be");
+  // Constant pools aren't cached so this is always a newly created object using the handle
+  assert(get_HotSpotConstantPool_metadataHandle(cp_object) == (jlong) handle, "must use same handle");
+  return cp_object;
+}
+
+JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jbooleanArray result = jni()->NewBooleanArray(length);
+    return wrap(result);
+  }
+}
+
+JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jbyteArray result = jni()->NewByteArray(length);
+    return wrap(result);
   }
+}
 
-  // Either the declared holder was not loaded, or the method could
-  // not be found.
+JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlassObj  ())->array_klass(CHECK_(JVMCIObject()));
+    objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject()));
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), NULL);
+    return wrap(result);
+  }
+}
 
-  return NULL;
+JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jintArray result = jni()->NewIntArray(length);
+    return wrap(result);
+  }
+}
+
+JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
+    return wrap(result);
+  } else {
+    JNIAccessMark jni(this);
+    jlongArray result = jni()->NewLongArray(length);
+    return wrap(result);
+  }
 }
 
-// ------------------------------------------------------------------
-InstanceKlass* JVMCIEnv::get_instance_klass_for_declared_method_holder(Klass* method_holder) {
-  // For the case of <array>.clone(), the method holder can be an ArrayKlass*
-  // instead of an InstanceKlass*.  For that case simply pretend that the
-  // declared holder is Object.clone since that's where the call will bottom out.
-  if (method_holder->is_instance_klass()) {
-    return InstanceKlass::cast(method_holder);
-  } else if (method_holder->is_array_klass()) {
-    return SystemDictionary::Object_klass();
+JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject()));
+    oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name));
+    HotSpotJVMCI::VMField::set_type(this, obj, HotSpotJVMCI::resolve(type));
+    HotSpotJVMCI::VMField::set_offset(this, obj, offset);
+    HotSpotJVMCI::VMField::set_address(this, obj, address);
+    HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value));
+    return wrap(obj);
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(),
+                                    JNIJVMCI::VMField::constructor(),
+                                    get_jobject(name), get_jobject(type), offset, address, get_jobject(value));
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject()));
+    oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name));
+    HotSpotJVMCI::VMFlag::set_type(this, obj, HotSpotJVMCI::resolve(type));
+    HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value));
+    return wrap(obj);
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(),
+                                    JNIJVMCI::VMFlag::constructor(),
+                                    get_jobject(name), get_jobject(type), get_jobject(value));
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
+    oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass));
+    HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name));
+    HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor));
+    HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
+    return wrap(obj);
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
+                                    JNIJVMCI::VMIntrinsicMethod::constructor(),
+                                    get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id);
+    return wrap(result);
+  }
+}
+
+JVMCIObject JVMCIEnv::new_HotSpotStackFrameReference(JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_(JVMCIObject()));
+    oop obj = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    return wrap(obj);
   } else {
     ShouldNotReachHere();
+    return JVMCIObject();
   }
-  return NULL;
+}
+JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject()));
+    oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    return wrap(obj);
+  } else {
+    ShouldNotReachHere();
+    return JVMCIObject();
+  }
 }
 
 
-// ------------------------------------------------------------------
-methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool,
-                                     int index, Bytecodes::Code bc,
-                                     InstanceKlass* accessor) {
-  ResourceMark rm;
-  return get_method_by_index_impl(cpool, index, bc, accessor);
+JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
+  JavaThread* THREAD = JavaThread::current();
+  Handle obj = Handle(THREAD, objOop);
+  if (obj.is_null()) {
+    return JVMCIObject();
+  }
+  if (is_hotspot()) {
+    HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->initialize(CHECK_(JVMCIObject()));
+    oop constant = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->allocate_instance(CHECK_(JVMCIObject()));
+    HotSpotJVMCI::DirectHotSpotObjectConstantImpl::set_object(this, constant, obj());
+    HotSpotJVMCI::HotSpotObjectConstantImpl::set_compressed(this, constant, compressed);
+    return wrap(constant);
+  } else {
+    jlong handle = make_handle(obj);
+    JNIAccessMark jni(this);
+    jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(),
+                                      JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(),
+                                      handle, compressed, dont_register);
+    return wrap(result);
+  }
+}
+
+
+Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
+  if (constant.is_null()) {
+    return Handle();
+  }
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
+    oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
+    return Handle(THREAD, obj);
+  } else {
+    assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type");
+    jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
+    oop result = resolve_handle(object_handle);
+    if (result == NULL) {
+      JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
+    }
+    return Handle(THREAD, result);
+  }
+}
+
+JVMCIObject JVMCIEnv::wrap(jobject object) {
+  return JVMCIObject::create(object, is_hotspot());
+}
+
+jlong JVMCIEnv::make_handle(const Handle& obj) {
+  assert(!obj.is_null(), "should only create handle for non-NULL oops");
+  jobject handle = JVMCI::make_global(obj);
+  return (jlong) handle;
+}
+
+oop JVMCIEnv::resolve_handle(jlong objectHandle) {
+  assert(objectHandle != 0, "should be a valid handle");
+  oop obj = *((oopDesc**)objectHandle);
+  if (obj != NULL) {
+    oopDesc::verify(obj);
+  }
+  return obj;
+}
+
+JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
+    return HotSpotJVMCI::wrap(result());
+  } else {
+    jobject result;
+    jboolean exception = false;
+    {
+      JNIAccessMark jni(this);
+      result = jni()->NewStringUTF(str);
+      exception = jni()->ExceptionCheck();
+    }
+    return wrap(result);
+  }
+}
+
+bool JVMCIEnv::equals(JVMCIObject a, JVMCIObject b) {
+  if (is_hotspot()) {
+    return HotSpotJVMCI::resolve(a) == HotSpotJVMCI::resolve(b);
+  } else {
+    JNIAccessMark jni(this);
+    return jni()->IsSameObject(a.as_jobject(), b.as_jobject()) != 0;
+  }
 }
 
-// ------------------------------------------------------------------
-// Check for changes to the system dictionary during compilation
-// class loads, evolution, breakpoints
-JVMCIEnv::CodeInstallResult JVMCIEnv::validate_compile_task_dependencies(Dependencies* dependencies, Handle compiled_code,
-                                                                         JVMCIEnv* env, char** failure_detail) {
-  // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
-  if (env != NULL && env->jvmti_state_changed()) {
-    *failure_detail = (char*) "Jvmti state change during compilation invalidated dependencies";
-    return JVMCIEnv::dependencies_failed;
+BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) {
+  if (kind.is_null()) {
+    JVMCI_THROW_(NullPointerException, T_ILLEGAL);
+  }
+  jchar ch = get_JavaKind_typeChar(kind);
+  switch(ch) {
+    case 'Z': return T_BOOLEAN;
+    case 'B': return T_BYTE;
+    case 'S': return T_SHORT;
+    case 'C': return T_CHAR;
+    case 'I': return T_INT;
+    case 'F': return T_FLOAT;
+    case 'J': return T_LONG;
+    case 'D': return T_DOUBLE;
+    case 'A': return T_OBJECT;
+    case '-': return T_ILLEGAL;
+    default:
+      JVMCI_ERROR_(T_ILLEGAL, "unexpected Kind: %c", ch);
+  }
+}
+
+void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS) {
+  // Ensure that all updates to the InstalledCode fields are consistent.
+  if (get_InstalledCode_address(installed_code) != 0) {
+    JVMCI_THROW_MSG(InternalError, "InstalledCode instance already in use");
+  }
+  if (!isa_HotSpotInstalledCode(installed_code)) {
+    JVMCI_THROW_MSG(InternalError, "InstalledCode instance must be a subclass of HotSpotInstalledCode");
   }
 
-  // Dependencies must be checked when the system dictionary changes
-  // or if we don't know whether it has changed (i.e., env == NULL).
-  bool counter_changed = env == NULL || env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications();
-  CompileTask* task = env == NULL ? NULL : env->task();
-  Dependencies::DepType result = dependencies->validate_dependencies(task, counter_changed, failure_detail);
-  if (result == Dependencies::end_marker) {
-    return JVMCIEnv::ok;
+  // Ignore the version which can stay at 0
+  if (cb->is_nmethod()) {
+    nmethod* nm = cb->as_nmethod_or_null();
+    if (!nm->is_alive()) {
+      JVMCI_THROW_MSG(InternalError, "nmethod has been reclaimed");
+    }
+    if (nm->is_in_use()) {
+      set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point());
+    }
+  } else {
+    set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin());
+  }
+  set_InstalledCode_address(installed_code, (jlong) cb);
+  set_HotSpotInstalledCode_size(installed_code, cb->size());
+  set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin());
+  set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
+}
+
+
+void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS) {
+  if (mirror.is_null()) {
+    JVMCI_THROW(NullPointerException);
   }
 
-  if (!Dependencies::is_klass_type(result) || counter_changed) {
-    return JVMCIEnv::dependencies_failed;
+  jlong nativeMethod = get_InstalledCode_address(mirror);
+  nmethod* nm = JVMCIENV->asNmethod(mirror);
+  if (nm == NULL) {
+    // Nothing to do
+    return;
+  }
+
+  Thread* THREAD = Thread::current();
+  if (!mirror.is_hotspot() && !THREAD->is_Java_thread()) {
+    // Calling back into native might cause the execution to block, so only allow this when calling
+    // from a JavaThread, which is the normal case anyway.
+    JVMCI_THROW_MSG(IllegalArgumentException,
+                    "Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread");
   }
-  // The dependencies were invalid at the time of installation
-  // without any intervening modification of the system
-  // dictionary.  That means they were invalidly constructed.
-  return JVMCIEnv::dependencies_invalid;
+
+  nmethodLocker nml(nm);
+  if (nm->is_alive()) {
+    // Invalidating the HotSpotNmethod means we want the nmethod
+    // to be deoptimized.
+    nm->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+
+  // A HotSpotNmethod instance can only reference a single nmethod
+  // during its lifetime so simply clear it here.
+  set_InstalledCode_address(mirror, 0);
+}
+
+Klass* JVMCIEnv::asKlass(JVMCIObject obj) {
+  return (Klass*) get_HotSpotResolvedObjectTypeImpl_metadataPointer(obj);
+}
+
+Method* JVMCIEnv::asMethod(JVMCIObject obj) {
+  Method** metadataHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_metadataHandle(obj);
+  return *metadataHandle;
 }
 
-// ------------------------------------------------------------------
-JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
-                                const methodHandle& method,
-                                nmethod*& nm,
-                                int entry_bci,
-                                CodeOffsets* offsets,
-                                int orig_pc_offset,
-                                CodeBuffer* code_buffer,
-                                int frame_words,
-                                OopMapSet* oop_map_set,
-                                ExceptionHandlerTable* handler_table,
-                                AbstractCompiler* compiler,
-                                DebugInformationRecorder* debug_info,
-                                Dependencies* dependencies,
-                                JVMCIEnv* env,
-                                int compile_id,
-                                bool has_unsafe_access,
-                                bool has_wide_vector,
-                                Handle installed_code,
-                                Handle compiled_code,
-                                Handle speculation_log) {
-  JVMCI_EXCEPTION_CONTEXT;
-  nm = NULL;
-  int comp_level = CompLevel_full_optimization;
-  char* failure_detail = NULL;
-  JVMCIEnv::CodeInstallResult result;
-  {
-    // To prevent compile queue updates.
-    MutexLocker locker(MethodCompileQueue_lock, THREAD);
+ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
+  ConstantPool** metadataHandle = (ConstantPool**) get_HotSpotConstantPool_metadataHandle(obj);
+  return *metadataHandle;
+}
 
-    // Prevent SystemDictionary::add_to_hierarchy from running
-    // and invalidating our dependencies until we install this method.
-    MutexLocker ml(Compile_lock);
-
-    // Encode the dependencies now, so we can check them right away.
-    dependencies->encode_content_bytes();
-
-    // Record the dependencies for the current compile in the log
-    if (LogCompilation) {
-      for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
-        deps.log_dependency();
-      }
-    }
-
-    // Check for {class loads, evolution, breakpoints} during compilation
-    result = validate_compile_task_dependencies(dependencies, compiled_code, env, &failure_detail);
-    if (result != JVMCIEnv::ok) {
-      // While not a true deoptimization, it is a preemptive decompile.
-      MethodData* mdp = method()->method_data();
-      if (mdp != NULL) {
-        mdp->inc_decompile_count();
-#ifdef ASSERT
-        if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
-          ResourceMark m;
-          tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
-        }
-#endif
-      }
 
-      // All buffers in the CodeBuffer are allocated in the CodeCache.
-      // If the code buffer is created on each compile attempt
-      // as in C2, then it must be freed.
-      //code_buffer->free_blob();
-    } else {
-      ImplicitExceptionTable implicit_tbl;
-      nm =  nmethod::new_nmethod(method,
-                                 compile_id,
-                                 entry_bci,
-                                 offsets,
-                                 orig_pc_offset,
-                                 debug_info, dependencies, code_buffer,
-                                 frame_words, oop_map_set,
-                                 handler_table, &implicit_tbl,
-                                 compiler, comp_level,
-                                 JNIHandles::make_weak_global(installed_code),
-                                 JNIHandles::make_weak_global(speculation_log));
-
-      // Free codeBlobs
-      //code_buffer->free_blob();
-      if (nm == NULL) {
-        // The CodeCache is full.  Print out warning and disable compilation.
-        {
-          MutexUnlocker ml(Compile_lock);
-          MutexUnlocker locker(MethodCompileQueue_lock);
-          CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level));
-        }
-      } else {
-        nm->set_has_unsafe_access(has_unsafe_access);
-        nm->set_has_wide_vectors(has_wide_vector);
-
-        // Record successful registration.
-        // (Put nm into the task handle *before* publishing to the Java heap.)
-        CompileTask* task = env == NULL ? NULL : env->task();
-        if (task != NULL) {
-          task->set_code(nm);
+CodeBlob* JVMCIEnv::asCodeBlob(JVMCIObject obj) {
+  address code = (address) get_InstalledCode_address(obj);
+  if (code == NULL) {
+    return NULL;
+  }
+  if (isa_HotSpotNmethod(obj)) {
+    jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj);
+    if (compile_id_snapshot != 0L) {
+      // A HotSpotNMethod not in an nmethod's oops table so look up
+      // the nmethod and then update the fields based on its state.
+      CodeBlob* cb = CodeCache::find_blob_unsafe(code);
+      if (cb == (CodeBlob*) code) {
+        // Found a live CodeBlob with the same address, make sure it's the same nmethod
+        nmethod* nm = cb->as_nmethod_or_null();
+        if (nm != NULL && nm->compile_id() == compile_id_snapshot) {
+          if (!nm->is_alive()) {
+            // Break the links from the mirror to the nmethod
+            set_InstalledCode_address(obj, 0);
+            set_InstalledCode_entryPoint(obj, 0);
+          } else if (nm->is_not_entrant()) {
+            // Zero the entry point so that the nmethod
+            // cannot be invoked by the mirror but can
+            // still be deoptimized.
+            set_InstalledCode_entryPoint(obj, 0);
+          }
+          return cb;
         }
-
-        if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
-          if (entry_bci == InvocationEntryBci) {
-            if (TieredCompilation) {
-              // If there is an old version we're done with it
-              CompiledMethod* old = method->code();
-              if (TraceMethodReplacement && old != NULL) {
-                ResourceMark rm;
-                char *method_name = method->name_and_sig_as_C_string();
-                tty->print_cr("Replacing method %s", method_name);
-              }
-              if (old != NULL ) {
-                old->make_not_entrant();
-              }
-            }
-            if (TraceNMethodInstalls) {
-              ResourceMark rm;
-              char *method_name = method->name_and_sig_as_C_string();
-              ttyLocker ttyl;
-              tty->print_cr("Installing method (%d) %s [entry point: %p]",
-                            comp_level,
-                            method_name, nm->entry_point());
-            }
-            // Allow the code to be executed
-            method->set_code(method, nm);
-          } else {
-            if (TraceNMethodInstalls ) {
-              ResourceMark rm;
-              char *method_name = method->name_and_sig_as_C_string();
-              ttyLocker ttyl;
-              tty->print_cr("Installing osr method (%d) %s @ %d",
-                            comp_level,
-                            method_name,
-                            entry_bci);
-            }
-            InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
-          }
-        }
-        nm->make_in_use();
       }
-      result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
+      // Clear the InstalledCode fields of this HotSpotNmethod
+      // that no longer refers to an nmethod in the code cache.
+      set_InstalledCode_address(obj, 0);
+      set_InstalledCode_entryPoint(obj, 0);
+      return NULL;
     }
   }
+  return (CodeBlob*) code;
+}
 
-  // String creation must be done outside lock
-  if (failure_detail != NULL) {
-    // A failure to allocate the string is silently ignored.
-    Handle message = java_lang_String::create_from_str(failure_detail, THREAD);
-    HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
+
+// Generate implementations for the initialize, new, isa, get and set methods for all the types and
+// fields declared in the JVMCI_CLASSES_DO macro.
+
+#define START_CLASS(className, fullClassName)                                                                        \
+  void JVMCIEnv::className##_initialize(JVMCI_TRAPS) {                                                               \
+    if (is_hotspot()) {                                                                                              \
+      HotSpotJVMCI::className::initialize(JVMCI_CHECK);                                                              \
+    } else {                                                                                                         \
+      JNIJVMCI::className::initialize(JVMCI_CHECK);                                                                  \
+    }                                                                                                                \
+  }                                                                                                                  \
+  JVMCIObjectArray JVMCIEnv::new_##className##_array(int length, JVMCI_TRAPS) {                                      \
+    if (is_hotspot()) {                                                                                              \
+      Thread* THREAD = Thread::current();                                                                            \
+      objArrayOop array = oopFactory::new_objArray(HotSpotJVMCI::className::klass(), length, CHECK_(JVMCIObject())); \
+      return (JVMCIObjectArray) wrap(array);                                                                         \
+    } else {                                                                                                         \
+      JNIAccessMark jni(this);                                                                                       \
+      jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::className::clazz(), NULL);                       \
+      return wrap(result);                                                                                           \
+    }                                                                                                                \
+  }                                                                                                                  \
+  bool JVMCIEnv::isa_##className(JVMCIObject object) {                                                               \
+    if (is_hotspot()) {                                                                                              \
+      return HotSpotJVMCI::className::is_instance(this, object);                                                     \
+    } else {                                                                                                         \
+      return JNIJVMCI::className::is_instance(this, object);                                                         \
+    }                                                                                                                \
+  }
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor, cast)                 \
+  type JVMCIEnv::get_##className##_##name(JVMCIObject obj) {         \
+    if (is_hotspot()) {                                              \
+      return HotSpotJVMCI::className::get_##name(this, obj);         \
+    } else {                                                         \
+      return JNIJVMCI::className::get_##name(this, obj);             \
+    }                                                                \
+  }                                                                  \
+  void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
+    if (is_hotspot()) {                                              \
+      HotSpotJVMCI::className::set_##name(this, obj, x);             \
+    } else {                                                         \
+      JNIJVMCI::className::set_##name(this, obj, x);                 \
+    }                                                                \
   }
 
-  // JVMTI -- compiled method notification (must be done outside lock)
-  if (nm != NULL) {
-    nm->post_compiled_method_load_event();
+#define EMPTY_CAST
+#define CHAR_FIELD(className, name)                    FIELD(className, name, jchar, Char, EMPTY_CAST)
+#define INT_FIELD(className, name)                     FIELD(className, name, jint, Int, EMPTY_CAST)
+#define BOOLEAN_FIELD(className, name)                 FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
+#define LONG_FIELD(className, name)                    FIELD(className, name, jlong, Long, EMPTY_CAST)
+#define FLOAT_FIELD(className, name)                   FIELD(className, name, jfloat, Float, EMPTY_CAST)
+
+#define OBJECT_FIELD(className, name, signature)              OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST)
+#define OBJECTARRAY_FIELD(className, name, signature)         OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
+#define PRIMARRAY_FIELD(className, name, signature)           OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray))
+
+#define STATIC_OBJECT_FIELD(className, name, signature)       STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject))
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature)  STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
 
-    if (env == NULL) {
-      // This compile didn't come through the CompileBroker so perform the printing here
-      DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
-      nm->maybe_print_nmethod(directive);
-      DirectivesStack::release(directive);
-    }
+#define OOPISH_FIELD(className, name, type, accessor, cast)           \
+  type JVMCIEnv::get_##className##_##name(JVMCIObject obj) {          \
+    if (is_hotspot()) {                                               \
+      return HotSpotJVMCI::className::get_##name(this, obj);          \
+    } else {                                                          \
+      return JNIJVMCI::className::get_##name(this, obj);              \
+    }                                                                 \
+  }                                                                   \
+  void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) {  \
+    if (is_hotspot()) {                                               \
+      HotSpotJVMCI::className::set_##name(this, obj, x);              \
+    } else {                                                          \
+      JNIJVMCI::className::set_##name(this, obj, x);                  \
+    }                                                                 \
   }
 
-  return result;
-}
+#define STATIC_OOPISH_FIELD(className, name, type, accessor, cast)    \
+  type JVMCIEnv::get_##className##_##name() {                         \
+    if (is_hotspot()) {                                               \
+      return HotSpotJVMCI::className::get_##name(this);               \
+    } else {                                                          \
+      return JNIJVMCI::className::get_##name(this);                   \
+    }                                                                 \
+  }                                                                   \
+  void JVMCIEnv::set_##className##_##name(type x) {                   \
+    if (is_hotspot()) {                                               \
+      HotSpotJVMCI::className::set_##name(this, x);                   \
+    } else {                                                          \
+      JNIJVMCI::className::set_##name(this, x);                       \
+    }                                                                 \
+  }
+
+#define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \
+  type JVMCIEnv::get_##className##_##name() {                         \
+    if (is_hotspot()) {                                               \
+      return HotSpotJVMCI::className::get_##name(this);               \
+    } else {                                                          \
+      return JNIJVMCI::className::get_##name(this);                   \
+    }                                                                 \
+  }                                                                   \
+  void JVMCIEnv::set_##className##_##name(type x) {                   \
+    if (is_hotspot()) {                                               \
+      HotSpotJVMCI::className::set_##name(this, x);                   \
+    } else {                                                          \
+      JNIJVMCI::className::set_##name(this, x);                       \
+    }                                                                 \
+  }
+#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+#undef START_CLASS
+#undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
--- a/src/hotspot/share/jvmci/jvmciEnv.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,14 +25,16 @@
 #ifndef SHARE_JVMCI_JVMCIENV_HPP
 #define SHARE_JVMCI_JVMCIENV_HPP
 
-#include "classfile/systemDictionary.hpp"
-#include "code/debugInfoRec.hpp"
-#include "code/dependencies.hpp"
-#include "code/exceptionHandlerTable.hpp"
-#include "compiler/oopMap.hpp"
+#include "classfile/javaClasses.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
 #include "runtime/thread.hpp"
 
 class CompileTask;
+class JVMCIObject;
+class JVMCIObjectArray;
+class JVMCIPrimitiveArray;
+class JVMCICompiler;
+class JVMCIRuntime;
 
 // Bring the JVMCI compiler thread into the VM state.
 #define JVMCI_VM_ENTRY_MARK                       \
@@ -47,64 +49,58 @@
   JavaThread* thread=JavaThread::current(); \
   Thread* THREAD = thread;
 
-//
-// This class is the top level broker for requests from the compiler
-// to the VM.
-class JVMCIEnv : StackObj {
-  CI_PACKAGE_ACCESS_TO
-
-  friend class JVMCIVMStructs;
-  friend class CompileBroker;
-  friend class Dependencies;  // for get_object, during logging
+// Helper to log more context on a JNI exception
+#define JVMCI_EXCEPTION_CHECK(env, ...) \
+  do { \
+    if (env->ExceptionCheck()) { \
+      if (env != JavaThread::current()->jni_environment() && JVMCIEnv::get_shared_library_path() != NULL) { \
+        tty->print_cr("In JVMCI shared library (%s):", JVMCIEnv::get_shared_library_path()); \
+      } \
+      tty->print_cr(__VA_ARGS__); \
+      return; \
+    } \
+  } while(0)
 
-public:
+// Helper class to ensure that references to Klass* are kept alive for G1
+class JVMCIKlassHandle : public StackObj {
+ private:
+  Klass*     _klass;
+  Handle     _holder;
+  Thread*    _thread;
 
-  enum CodeInstallResult {
-     ok,
-     dependencies_failed,
-     dependencies_invalid,
-     cache_full,
-     code_too_large
-  };
+  Klass*        klass() const                     { return _klass; }
+  Klass*        non_null_klass() const            { assert(_klass != NULL, "resolving NULL _klass"); return _klass; }
 
-  // Look up a klass by name from a particular class loader (the accessor's).
-  // If require_local, result must be defined in that class loader, or NULL.
-  // If !require_local, a result from remote class loader may be reported,
-  // if sufficient class loader constraints exist such that initiating
-  // a class loading request from the given loader is bound to return
-  // the class defined in the remote loader (or throw an error).
-  //
-  // Return an unloaded klass if !require_local and no class at all is found.
-  //
-  // The CI treats a klass as loaded if it is consistently defined in
-  // another loader, even if it hasn't yet been loaded in all loaders
-  // that could potentially see it via delegation.
-  static Klass* get_klass_by_name(Klass* accessing_klass, Symbol* klass_name, bool require_local);
+ public:
+  /* Constructors */
+  JVMCIKlassHandle (Thread* thread) : _klass(NULL), _thread(thread) {}
+  JVMCIKlassHandle (Thread* thread, Klass* klass);
+
+  JVMCIKlassHandle (const JVMCIKlassHandle &h): _klass(h._klass), _holder(h._holder), _thread(h._thread) {}
+  JVMCIKlassHandle& operator=(const JVMCIKlassHandle &s);
+  JVMCIKlassHandle& operator=(Klass* klass);
+
+  /* Operators for ease of use */
+  Klass*        operator () () const            { return klass(); }
+  Klass*        operator -> () const            { return non_null_klass(); }
 
-  // Constant pool access.
-  static Klass* get_klass_by_index(const constantPoolHandle& cpool,
-                                   int klass_index,
-                                   bool& is_accessible,
-                                   Klass* loading_klass);
-  static void   get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd,
-                                   int field_index);
-  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
-                                    int method_index, Bytecodes::Code bc,
-                                    InstanceKlass* loading_klass);
+  bool    operator == (Klass* o) const          { return klass() == o; }
+  bool    operator == (const JVMCIKlassHandle& h) const  { return klass() == h.klass(); }
 
-  JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter);
+  /* Null checks */
+  bool    is_null() const                      { return _klass == NULL; }
+  bool    not_null() const                     { return _klass != NULL; }
+};
 
-private:
+// A class that maintains the state needed for compilations requested
+// by the CompileBroker.  It is created in the broker and passed through
+// into the code installation step.
+class JVMCICompileState : public ResourceObj {
+  friend class VMStructs;
+ private:
   CompileTask*     _task;
   int              _system_dictionary_modification_counter;
 
-  // Compilation result values
-  bool             _retryable;
-  const char*      _failure_reason;
-
-  // Specifies if _failure_reason is on the C heap.
-  bool             _failure_reason_on_C_heap;
-
   // Cache JVMTI state. Defined as bytes so that reading them from Java
   // via Unsafe is well defined (the C++ type for bool is implementation
   // defined and may not be the same as a Java boolean).
@@ -113,43 +109,20 @@
   jbyte  _jvmti_can_post_on_exceptions;
   jbyte  _jvmti_can_pop_frame;
 
-  // Implementation methods for loading and constant pool access.
-  static Klass* get_klass_by_name_impl(Klass* accessing_klass,
-                                  const constantPoolHandle& cpool,
-                                  Symbol* klass_name,
-                                  bool require_local);
-  static Klass* get_klass_by_index_impl(const constantPoolHandle& cpool,
-                                     int klass_index,
-                                     bool& is_accessible,
-                                     Klass* loading_klass);
-  static void   get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd,
-                                     int field_index);
-  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
-                                      int method_index, Bytecodes::Code bc,
-                                      InstanceKlass* loading_klass);
+  // Compilation result values.
+  bool             _retryable;
+  const char*      _failure_reason;
 
-  // Helper methods
-  static bool       check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass);
-  static methodHandle  lookup_method(InstanceKlass*  accessor,
-                           Klass*         holder,
-                           Symbol*        name,
-                           Symbol*        sig,
-                           Bytecodes::Code bc,
-                           constantTag     tag);
+  // Specifies if _failure_reason is on the C heap. If so, it is allocated
+  // with the mtJVMCI NMT flag.
+  bool             _failure_reason_on_C_heap;
 
-  private:
-
-  // Is this thread currently in the VM state?
-  static bool is_in_vm();
+ public:
+  JVMCICompileState(CompileTask* task, int system_dictionary_modification_counter);
 
-  // Helper routine for determining the validity of a compilation
-  // with respect to concurrent class loading.
-  static JVMCIEnv::CodeInstallResult validate_compile_task_dependencies(Dependencies* target, Handle compiled_code,
-                                                                        JVMCIEnv* env, char** failure_detail);
-
-public:
   CompileTask* task() { return _task; }
 
+  int system_dictionary_modification_counter() { return _system_dictionary_modification_counter; }
   bool  jvmti_state_changed() const;
   bool  jvmti_can_hotswap_or_post_breakpoint() const { return  _jvmti_can_hotswap_or_post_breakpoint != 0; }
   bool  jvmti_can_access_local_variables() const     { return  _jvmti_can_access_local_variables != 0; }
@@ -165,34 +138,355 @@
     _failure_reason_on_C_heap = reason_on_C_heap;
     _retryable = retryable;
   }
+};
 
-  // Register the result of a compilation.
-  static JVMCIEnv::CodeInstallResult register_method(
-                       const methodHandle&       target,
-                       nmethod*&                 nm,
-                       int                       entry_bci,
-                       CodeOffsets*              offsets,
-                       int                       orig_pc_offset,
-                       CodeBuffer*               code_buffer,
-                       int                       frame_words,
-                       OopMapSet*                oop_map_set,
-                       ExceptionHandlerTable*    handler_table,
-                       AbstractCompiler*         compiler,
-                       DebugInformationRecorder* debug_info,
-                       Dependencies*             dependencies,
-                       JVMCIEnv*                 env,
-                       int                       compile_id,
-                       bool                      has_unsafe_access,
-                       bool                      has_wide_vector,
-                       Handle                    installed_code,
-                       Handle                    compiled_code,
-                       Handle                    speculation_log);
+
+// This class is a top level wrapper around interactions between HotSpot
+// and the JVMCI Java code.  It supports both a HotSpot heap based
+// runtime with HotSpot oop based accessors as well as a shared library
+// based runtime that is accessed through JNI. It abstracts away all
+// interactions with JVMCI objects so that a single version of the
+// HotSpot C++ code can can work with either runtime.
+class JVMCIEnv : public ResourceObj {
+  friend class JNIAccessMark;
+
+  static char*   _shared_library_path;   // argument to os:dll_load
+  static void*   _shared_library_handle; // result of os::dll_load
+  static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
+
+  // Attaches the current thread to the JavaVM in the shared library,
+  // initializing the shared library VM first if necessary.
+  // Returns the JNI interface pointer of the current thread.
+  // The _shared_library_* fields are initialized by the first
+  // call to this method.
+  static JNIEnv* attach_shared_library();
+
+  // Initializes the _env, _mode and _runtime fields.
+  void init_env_mode_runtime(JNIEnv* parent_env);
+
+  void init(bool is_hotspot, const char* file, int line);
+
+  JNIEnv*                _env;     // JNI env for calling into shared library
+  JVMCIRuntime*          _runtime; // Access to a HotSpotJVMCIRuntime
+  bool             _is_hotspot;    // Which heap is the HotSpotJVMCIRuntime in
+  bool        _throw_to_caller;    // Propagate an exception raised in this env to the caller?
+  const char*            _file;    // The file and ...
+  int                    _line;    // ... line where this JNIEnv was created
+
+  // Translates an exception on the HotSpot heap to an exception on
+  // the shared library heap. The translation includes the stack and
+  // causes of `throwable`. The translated exception is pending in the
+  // shared library thread upon returning.
+  void translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable);
+
+public:
+  // Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM).
+  // An exception occurring within the scope is left pending when the
+  // scope closes so that it will be propagated back to Java.
+  // The JVMCIEnv destructor translates the exception object for the
+  // Java runtime if necessary.
+  JVMCIEnv(JNIEnv* env, const char* file, int line);
+
+  // Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
+  // An exception occurring within the scope must not be propagated back to
+  // the CompileBroker.
+  JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line);
+
+  // Opens a JNIEnv scope for a call from within the VM. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(JavaThread* env, const char* file, int line);
+
+  // Opens a JNIEnv scope for accessing `for_object`. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(JVMCIObject for_object, const char* file, int line) {
+    // A JNI call to access an object in the shared library heap
+    // can block or take a long time so do not allow such access
+    // on the VM thread.
+    assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
+        "cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
+    init(for_object.is_hotspot(), file, line);
+  }
+
+  // Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
+  // otherwise for the shared library runtime. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(bool is_hotspot, const char* file, int line) {
+    init(is_hotspot, file, line);
+  }
+
+  ~JVMCIEnv();
+
+  JVMCIRuntime* runtime() {
+    return _runtime;
+  }
+
+  // Initializes Services.savedProperties in the shared library by copying
+  // the values from the same field in the HotSpot heap.
+  void copy_saved_properties();
+
+  jboolean has_pending_exception();
+  void clear_pending_exception();
+
+  // Prints an exception and stack trace of a pending exception.
+  void describe_pending_exception(bool clear);
+
+  int get_length(JVMCIArray array);
+
+  JVMCIObject get_object_at(JVMCIObjectArray array, int index);
+  void put_object_at(JVMCIObjectArray array, int index, JVMCIObject value);
+
+  jboolean get_bool_at(JVMCIPrimitiveArray array, int index);
+  void put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value);
+
+  jbyte get_byte_at(JVMCIPrimitiveArray array, int index);
+  void put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value);
+
+  jint get_int_at(JVMCIPrimitiveArray array, int index);
+  void put_int_at(JVMCIPrimitiveArray array, int index, jint value);
+
+  long get_long_at(JVMCIPrimitiveArray array, int index);
+  void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
+
+  void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes);
+  void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes);
+
+  JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
+
+  jboolean is_boxing_object(BasicType type, JVMCIObject object);
+
+  // Get the primitive value from a Java boxing object.  It's hard error to
+  // pass a non-primitive BasicType.
+  jvalue get_boxed_value(BasicType type, JVMCIObject object);
+
+  // Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
+  BasicType get_box_type(JVMCIObject object);
+
+  // Create a boxing object of the appropriate primitive type.
+  JVMCIObject create_box(BasicType type, jvalue* value, JVMCI_TRAPS);
+
+  const char* as_utf8_string(JVMCIObject str);
+  char* as_utf8_string(JVMCIObject str, char* buf, int buflen);
+
+  JVMCIObject create_string(Symbol* str, JVMCI_TRAPS) {
+    return create_string(str->as_C_string(), JVMCI_CHECK_(JVMCIObject()));
+  }
+
+  JVMCIObject create_string(const char* str, JVMCI_TRAPS);
+
+  bool equals(JVMCIObject a, JVMCIObject b);
+
+  // Convert into a JNI handle for the appropriate runtime
+  jobject get_jobject(JVMCIObject object)                       { assert(object.as_jobject() == NULL || is_hotspot() == object.is_hotspot(), "mismatch"); return object.as_jobject(); }
+  jarray get_jarray(JVMCIArray array)                           { assert(array.as_jobject() == NULL || is_hotspot() == array.is_hotspot(), "mismatch"); return array.as_jobject(); }
+  jobjectArray get_jobjectArray(JVMCIObjectArray objectArray)   { assert(objectArray.as_jobject() == NULL || is_hotspot() == objectArray.is_hotspot(), "mismatch"); return objectArray.as_jobject(); }
+  jbyteArray get_jbyteArray(JVMCIPrimitiveArray primitiveArray) { assert(primitiveArray.as_jobject() == NULL || is_hotspot() == primitiveArray.is_hotspot(), "mismatch"); return primitiveArray.as_jbyteArray(); }
+
+  JVMCIObject         wrap(jobject obj);
+  JVMCIObjectArray    wrap(jobjectArray obj)  { return (JVMCIObjectArray)    wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jintArray obj)     { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jbooleanArray obj) { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jbyteArray obj)    { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jlongArray obj)    { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+
+ private:
+  JVMCIObject wrap(oop obj)                  { assert(is_hotspot(), "must be"); return wrap(JNIHandles::make_local(obj)); }
+  JVMCIObjectArray wrap(objArrayOop obj)     { assert(is_hotspot(), "must be"); return (JVMCIObjectArray) wrap(JNIHandles::make_local(obj)); }
+  JVMCIPrimitiveArray wrap(typeArrayOop obj) { assert(is_hotspot(), "must be"); return (JVMCIPrimitiveArray) wrap(JNIHandles::make_local(obj)); }
+
+ public:
+  // Compiles a method with the JVMIC compiler.
+  // Caller must handle pending exception.
+  JVMCIObject call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime, JVMCIObject method, int entry_bci,
+                                                     jlong compile_state, int id);
+
+  void call_HotSpotJVMCIRuntime_bootstrapFinished(JVMCIObject runtime, JVMCI_TRAPS);
+  void call_HotSpotJVMCIRuntime_shutdown(JVMCIObject runtime);
+  JVMCIObject call_HotSpotJVMCIRuntime_runtime(JVMCI_TRAPS);
+  JVMCIObject call_JVMCI_getRuntime(JVMCI_TRAPS);
+  JVMCIObject call_HotSpotJVMCIRuntime_getCompiler(JVMCIObject runtime, JVMCI_TRAPS);
+
+  JVMCIObject call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCI_TRAPS);
+
+  JVMCIObject call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS);
+  JVMCIObject call_JavaConstant_forFloat(float value, JVMCI_TRAPS);
+  JVMCIObject call_JavaConstant_forDouble(double value, JVMCI_TRAPS);
+
+  BasicType kindToBasicType(JVMCIObject kind, JVMCI_TRAPS);
 
-  // converts the Klass* representing the holder of a method into a
-  // InstanceKlass*.  This is needed since the holder of a method in
-  // the bytecodes could be an array type.  Basically this converts
-  // array types into java/lang/Object and other types stay as they are.
-  static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass);
+#define DO_THROW(name) \
+  void throw_##name(const char* msg = NULL);
+
+  DO_THROW(InternalError)
+  DO_THROW(ArrayIndexOutOfBoundsException)
+  DO_THROW(IllegalStateException)
+  DO_THROW(NullPointerException)
+  DO_THROW(IllegalArgumentException)
+  DO_THROW(InvalidInstalledCodeException)
+  DO_THROW(UnsatisfiedLinkError)
+
+#undef DO_THROW
+
+  void fthrow_error(const char* file, int line, const char* format, ...) ATTRIBUTE_PRINTF(4, 5);
+
+  // Given an instance of HotSpotInstalledCode return the corresponding CodeBlob*
+  CodeBlob* asCodeBlob(JVMCIObject code);
+
+  nmethod* asNmethod(JVMCIObject code) {
+    CodeBlob* cb = asCodeBlob(code);
+    if (cb == NULL) {
+      return NULL;
+    }
+    nmethod* nm = cb->as_nmethod_or_null();
+    guarantee(nm != NULL, "not an nmethod");
+    return nm;
+  }
+
+  MethodData* asMethodData(jlong metaspaceMethodData) {
+    return (MethodData*) (address) metaspaceMethodData;
+  }
+
+  const char* klass_name(JVMCIObject object);
+
+  // Unpack an instance of HotSpotResolvedJavaMethodImpl into the original Method*
+  Method* asMethod(JVMCIObject jvmci_method);
+  Method* asMethod(jobject jvmci_method) { return asMethod(wrap(jvmci_method)); }
+
+  // Unpack an instance of HotSpotResolvedObjectTypeImpl into the original Klass*
+  Klass* asKlass(JVMCIObject jvmci_type);
+  Klass* asKlass(jobject jvmci_type)  { return asKlass(wrap(jvmci_type)); }
+
+  JVMCIObject get_jvmci_method(const methodHandle& method, JVMCI_TRAPS);
+
+  JVMCIObject get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS);
+
+  // Unpack an instance of HotSpotConstantPool into the original ConstantPool*
+  ConstantPool* asConstantPool(JVMCIObject constant_pool);
+  ConstantPool* asConstantPool(jobject constant_pool)  { return asConstantPool(wrap(constant_pool)); }
+
+  JVMCIObject get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS);
+  JVMCIObject get_jvmci_primitive_type(BasicType type);
+
+  Handle asConstant(JVMCIObject object, JVMCI_TRAPS);
+  JVMCIObject get_object_constant(oop objOop, bool compressed = false, bool dont_register = false);
+
+  JVMCIPrimitiveArray new_booleanArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_byteArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_intArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_longArray(int length, JVMCI_TRAPS);
+
+  JVMCIObjectArray new_byte_array_array(int length, JVMCI_TRAPS);
+
+  JVMCIObject new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS);
+  JVMCIObject new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS);
+  JVMCIObject new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS);
+  JVMCIObject new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS);
+  JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS);
+  JVMCIObject new_HotSpotStackFrameReference(JVMCI_TRAPS);
+  JVMCIObject new_JVMCIError(JVMCI_TRAPS);
+
+  jlong make_handle(const Handle& obj);
+  oop resolve_handle(jlong objectHandle);
+
+  // These are analagous to the JNI routines
+  JVMCIObject make_local(JVMCIObject object);
+  JVMCIObject make_global(JVMCIObject object);
+  JVMCIObject make_weak(JVMCIObject object);
+  void destroy_local(JVMCIObject object);
+  void destroy_global(JVMCIObject object);
+  void destroy_weak(JVMCIObject object);
+
+  // Deoptimizes the nmethod (if any) in the HotSpotNmethod.address
+  // field of mirror. The field is subsequently zeroed.
+  void invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS);
+
+  void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS);
+
+ private:
+  JVMCICompileState* _compile_state;
+
+ public:
+  static JavaVM* get_shared_library_javavm() { return _shared_library_javavm; }
+  static void* get_shared_library_handle()   { return _shared_library_handle; }
+  static char* get_shared_library_path()     { return _shared_library_path; }
+
+  // Determines if this is for the JVMCI runtime in the HotSpot
+  // heap (true) or the shared library heap (false).
+  bool is_hotspot() { return _is_hotspot; }
+
+  JVMCICompileState* compile_state() { return _compile_state; }
+  void set_compile_state(JVMCICompileState* compile_state) {
+    assert(_compile_state == NULL, "set only once");
+    _compile_state = compile_state;
+  }
+  // Generate declarations for the initialize, new, isa, get and set methods for all the types and
+  // fields declared in the JVMCI_CLASSES_DO macro.
+
+#define START_CLASS(className, fullClassName)                           \
+  void className##_initialize(JVMCI_TRAPS); \
+  JVMCIObjectArray new_##className##_array(int length, JVMCI_TRAPS); \
+  bool isa_##className(JVMCIObject object);
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor)                                                                                                                         \
+  type get_ ## className ## _ ## name(JVMCIObject obj); \
+  void set_ ## className ## _ ## name(JVMCIObject obj, type x);
+
+#define OOPISH_FIELD(className, name, type, hstype, accessor) \
+  FIELD(className, name, type, accessor)
+
+#define STATIC_FIELD(className, name, type) \
+  type get_ ## className ## _ ## name(); \
+  void set_ ## className ## _ ## name(type x);
+
+#define STATIC_OOPISH_FIELD(className, name, type, hstype) \
+  STATIC_FIELD(className, name, type)
+
+#define EMPTY_CAST
+#define CHAR_FIELD(className,  name) FIELD(className, name, jchar, char_field)
+#define INT_FIELD(className,  name) FIELD(className, name, jint, int_field)
+#define BOOLEAN_FIELD(className,  name) FIELD(className, name, jboolean, bool_field)
+#define LONG_FIELD(className,  name) FIELD(className, name, jlong, long_field)
+#define FLOAT_FIELD(className,  name) FIELD(className, name, jfloat, float_field)
+#define OBJECT_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIObject, oop, obj_field)
+#define OBJECTARRAY_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, objArrayOop, obj_field)
+#define PRIMARRAY_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, typeArrayOop, obj_field)
+
+#define STATIC_INT_FIELD(className, name) STATIC_FIELD(className, name, jint)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_FIELD(className, name, jboolean)
+#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, oop)
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, objArrayOop)
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+  JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+#undef JNI_START_CLASS
+#undef START_CLASS
+#undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+  // End of JVMCIEnv
 };
 
 #endif // SHARE_JVMCI_JVMCIENV_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmciExceptions.hpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,79 @@
+/*
+ * 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_JVMCI_JVMCIEXCEPTIONS_HPP
+#define SHARE_JVMCI_JVMCIEXCEPTIONS_HPP
+
+class JVMCIEnv;
+
+// JVMCIEnv exception utility macros.  Analagous to the regular CHECK, TRAP and THREAD macros.
+
+#define JVMCIENV __jvmci_env__
+#define JVMCI_TRAPS  JVMCIEnv* JVMCIENV
+
+#define JNI_JVMCIENV(env)                                     \
+  JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__);      \
+  JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
+
+#define THREAD_JVMCIENV(thread)                               \
+  JVMCIEnv __stack_jvmci_env__(thread, __FILE__, __LINE__);   \
+  JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
+
+#define JVMCI_PENDING_EXCEPTION                        (JVMCIENV->pending_exception())
+#define JVMCI_HAS_PENDING_EXCEPTION                    (JVMCIENV->has_pending_exception())
+#define JVMCI_CLEAR_PENDING_EXCEPTION                  (JVMCIENV->clear_pending_exception())
+
+#define JVMCI_CHECK                                    JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) return       ; (void)(0
+#define JVMCI_CHECK_(result)                           JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) return result; (void)(0
+#define JVMCI_CHECK_0                                  JVMCI_CHECK_(0)
+#define JVMCI_CHECK_NULL                               JVMCI_CHECK_(NULL)
+#define JVMCI_CHECK_false                              JVMCI_CHECK_(false)
+#define JVMCI_CHECK_OK                                 JVMCI_CHECK_(JVMCI::ok)
+
+#define JVMCI_ERROR(...)       \
+  { JVMCIENV->fthrow_error(__FILE__, __LINE__, __VA_ARGS__); return; }
+
+#define JVMCI_ERROR_(ret, ...) \
+  { JVMCIENV->fthrow_error( __FILE__, __LINE__, __VA_ARGS__); return ret; }
+
+#define JVMCI_ERROR_0(...)    JVMCI_ERROR_(0, __VA_ARGS__)
+#define JVMCI_ERROR_NULL(...) JVMCI_ERROR_(NULL, __VA_ARGS__)
+#define JVMCI_ERROR_OK(...)   JVMCI_ERROR_(JVMCI::ok, __VA_ARGS__)
+
+#define JVMCI_THROW(name) { JVMCIENV->throw_##name(); return; }
+#define JVMCI_THROW_NULL(name) { JVMCIENV->throw_##name(); return NULL; }
+#define JVMCI_THROW_0(name) { JVMCIENV->throw_##name(); return 0; }
+#define JVMCI_THROW_MSG_NULL(name, msg) { JVMCIENV->throw_##name(msg); return NULL; }
+#define JVMCI_THROW_MSG_(name, msg, value) { JVMCIENV->throw_##name(msg); return (value); }
+#define JVMCI_THROW_MSG_0(name, msg) { JVMCIENV->throw_##name(msg); return 0; }
+#define JVMCI_THROW_MSG(name, msg) { JVMCIENV->throw_##name(msg); return; }
+#define JVMCI_THROW_(name, value) { JVMCIENV->throw_##name(); return (value); }
+
+#define JVMCI_CATCH                              \
+  JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) {  \
+    JVMCIENV->describe_pending_exception(true);  \
+    ShouldNotReachHere();                        \
+  } (void)(0
+
+#endif // SHARE_JVMCI_JVMCIEXCEPTIONS_HPP
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Fri May 03 14:59:32 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
@@ -23,95 +23,43 @@
 
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #include "memory/resourceArea.hpp"
-#include "oops/oop.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 
+// ------------------------------------------------------------------
 
-// This macro expands for non-inline functions, in class declarations.
+oop HotSpotJVMCI::resolve(JVMCIObject obj) {
+  return JNIHandles::resolve(obj.as_jobject());
+}
 
-#define START_CLASS(name)                                                                                                                                \
-    void name::check(oop obj, const char* field_name, int offset) {                                                                                          \
-      assert(obj != NULL, "NULL field access of %s.%s", #name, field_name);                                                                                  \
-      assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected, found %s", obj->klass()->external_name());                       \
-      assert(offset != 0, "must be valid offset");                                                                                                           \
-    }
+arrayOop HotSpotJVMCI::resolve(JVMCIArray obj) {
+  return (arrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define END_CLASS
-
-#define FIELD(klass, name, type, accessor, cast)                                                                                                                                \
-    type klass::name(jobject obj)               { check(JNIHandles::resolve(obj), #name, _##name##_offset); return cast JNIHandles::resolve(obj)->accessor(_##name##_offset); }     \
-    void klass::set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj), #name, _##name##_offset); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); }
+objArrayOop HotSpotJVMCI::resolve(JVMCIObjectArray obj) {
+  return (objArrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define EMPTY_CAST
-#define CHAR_FIELD(klass, name) FIELD(klass, name, jchar, char_field, EMPTY_CAST)
-#define INT_FIELD(klass, name) FIELD(klass, name, jint, int_field, EMPTY_CAST)
-#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, jboolean, bool_field, EMPTY_CAST)
-#define LONG_FIELD(klass, name) FIELD(klass, name, jlong, long_field, EMPTY_CAST)
-#define FLOAT_FIELD(klass, name) FIELD(klass, name, jfloat, float_field, EMPTY_CAST)
-#define OOP_FIELD(klass, name, signature) FIELD(klass, name, oop, obj_field, EMPTY_CAST)
-#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(klass, name, objArrayOop, obj_field, (objArrayOop))
-#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(klass, name, typeArrayOop, obj_field, (typeArrayOop))
-#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
-#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
-#define STATIC_OOPISH_FIELD(klassName, name, type, signature)                                                  \
-    type klassName::name() {                                                                                   \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      oop result = HeapAccess<>::oop_load_at(base, _##name##_offset);                                          \
-      return type(result);                                                                                     \
-    }                                                                                                          \
-    void klassName::set_##name(type x) {                                                                       \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName);                                 \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      HeapAccess<>::oop_store_at(base, _##name##_offset, x);                                                   \
-    }
-#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename)                                                     \
-    jtypename klassName::name() {                                                                              \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      return HeapAccess<>::load_at(base, _##name##_offset);                                                    \
-    }                                                                                                          \
-    void klassName::set_##name(jtypename x) {                                                                  \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      HeapAccess<>::store_at(base, _##name##_offset, x);                                                       \
-    }
+typeArrayOop HotSpotJVMCI::resolve(JVMCIPrimitiveArray obj) {
+  return (typeArrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
-#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+JVMCIObject HotSpotJVMCI::wrap(oop obj) {
+  assert(Thread::current()->is_Java_thread(), "must be");
+  return JVMCIObject(JNIHandles::make_local(obj), true);
+}
 
-COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
-#undef START_CLASS
-#undef END_CLASS
-#undef FIELD
-#undef CHAR_FIELD
-#undef INT_FIELD
-#undef BOOLEAN_FIELD
-#undef LONG_FIELD
-#undef FLOAT_FIELD
-#undef OOP_FIELD
-#undef TYPEARRAYOOP_FIELD
-#undef OBJARRAYOOP_FIELD
-#undef STATIC_OOPISH_FIELD
-#undef STATIC_OOP_FIELD
-#undef STATIC_OBJARRAYOOP_FIELD
-#undef STATIC_INT_FIELD
-#undef STATIC_BOOLEAN_FIELD
-#undef STATIC_PRIMITIVE_FIELD
-#undef EMPTY_CAST
-
-// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field.
-// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
-
-void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) {
+/**
+ * Computes the field offset of a static or instance field.
+ * It looks up the name and signature symbols without creating new ones;
+ * all the symbols of these classes need to be already loaded.
+ */
+void HotSpotJVMCI::compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) {
   InstanceKlass* ik = InstanceKlass::cast(klass);
   Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
   Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
@@ -125,7 +73,7 @@
   fieldDescriptor fd;
   if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
     ResourceMark rm;
-    fatal("Invalid layout of %s %s at %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), ik->external_name());
+    fatal("Could not find field %s.%s with signature %s", ik->external_name(), name, signature);
   }
   guarantee(fd.is_static() == static_field, "static/instance mismatch");
   dest_offset = fd.offset();
@@ -137,33 +85,548 @@
   }
 }
 
-// This piece of macro magic creates the contents of the jvmci_compute_offsets method that initializes the field indices of all the access classes.
+#ifndef PRODUCT
+static void check_resolve_method(const char* call_type, Klass* resolved_klass, Symbol* method_name, Symbol* method_signature, TRAPS) {
+  methodHandle method;
+  LinkInfo link_info(resolved_klass, method_name, method_signature, NULL, LinkInfo::skip_access_check);
+  if (strcmp(call_type, "call_static") == 0) {
+    method = LinkResolver::resolve_static_call_or_null(link_info);
+  } else if (strcmp(call_type, "call_virtual") == 0) {
+    method = LinkResolver::resolve_virtual_call_or_null(resolved_klass, link_info);
+  } else if (strcmp(call_type, "call_special") == 0) {
+    method = LinkResolver::resolve_special_call_or_null(link_info);
+  } else {
+    fatal("Unknown or unsupported call type: %s", call_type);
+  }
+  if (method.is_null()) {
+    fatal("Could not resolve %s.%s%s", resolved_klass->external_name(), method_name->as_C_string(), method_signature->as_C_string());
+  }
+}
+#endif
 
-#define START_CLASS(name) { Klass* k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name "");
+jclass JNIJVMCI::_box_classes[T_CONFLICT+1];
+jclass JNIJVMCI::_byte_array;
+jfieldID JNIJVMCI::_box_fields[T_CONFLICT+1];
+jmethodID JNIJVMCI::_box_constructors[T_CONFLICT+1];
+jmethodID JNIJVMCI::_Class_getName_method;
+
+jmethodID JNIJVMCI::_HotSpotResolvedJavaMethodImpl_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotConstantPool_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotResolvedObjectTypeImpl_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method;
+
+#define START_CLASS(className, fullClassName)                          { \
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::fullClassName(), true, CHECK); \
+  className::_klass = InstanceKlass::cast(k); \
+  className::_klass->initialize(CHECK);
 
 #define END_CLASS }
 
-#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field, CHECK);
-#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false)
-#define INT_FIELD(klass, name) FIELD(klass, name, "I", false)
-#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false)
-#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false)
-#define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false)
-#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false)
-#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true)
-#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true)
-#define STATIC_BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", true)
+#define FIELD(className, name, signature, static_field) compute_offset(className::_##name##_offset, className::_klass, #name, signature, static_field, CHECK);
+#define CHAR_FIELD(className, name) FIELD(className, name, "C", false)
+#define INT_FIELD(className, name) FIELD(className, name, "I", false)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false)
+#define LONG_FIELD(className, name) FIELD(className, name, "J", false)
+#define FLOAT_FIELD(className, name) FIELD(className, name, "F", false)
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false)
+#define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true)
+#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
+#ifdef PRODUCT
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+#else
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+  check_resolve_method(#hsCallType, k, vmSymbols::methodName##_name(), vmSymbols::signatureSymbolName(), CHECK);
+#define CONSTRUCTOR(className, signature) { \
+  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK); \
+  check_resolve_method("call_special", k, vmSymbols::object_initializer_name(), sig, CHECK); \
+  }
+#endif
+/**
+ * Computes and initializes the offsets used by HotSpotJVMCI.
+ */
+void HotSpotJVMCI::compute_offsets(TRAPS) {
+  JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, OBJECT_FIELD, OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+}
+
+#undef START_CLASS
+#undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+// ------------------------------------------------------------------
+
+#define START_CLASS(className, fullClassName)                                           \
+  void HotSpotJVMCI::className::initialize(JVMCI_TRAPS) {                               \
+    Thread* THREAD = Thread::current();                                                 \
+    className::klass()->initialize(CHECK);                                              \
+  }                                                                                     \
+  bool HotSpotJVMCI::className::is_instance(JVMCIEnv* env, JVMCIObject object) {        \
+    return resolve(object)->is_a(className::klass());                                   \
+  }                                                                                     \
+  void HotSpotJVMCI::className::check(oop obj, const char* field_name, int offset) {    \
+    assert(obj != NULL, "NULL field access of %s.%s", #className, field_name); \
+    assert(obj->is_a(className::klass()), "wrong class, " #className " expected, found %s", obj->klass()->external_name()); \
+    assert(offset != 0, "must be valid offset");                                        \
+  }                                                                                     \
+  InstanceKlass* HotSpotJVMCI::className::_klass = NULL;
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor, cast)                     \
+  type HotSpotJVMCI::className::name(JVMCIEnv* env, oop obj)               { className::check(obj, #name, className::_##name##_offset); return cast obj->accessor(className::_##name##_offset); } \
+  void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, oop obj, type x) { className::check(obj, #name, className::_##name##_offset); obj->accessor##_put(className::_##name##_offset, x); }
+
+#define EMPTY_CAST
+#define CHAR_FIELD(className, name) FIELD(className, name, jchar, char_field, EMPTY_CAST)
+#define INT_FIELD(className, name) FIELD(className, name, jint, int_field, EMPTY_CAST)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, bool_field, EMPTY_CAST)
+#define LONG_FIELD(className, name) FIELD(className, name, jlong, long_field, EMPTY_CAST)
+#define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, float_field, EMPTY_CAST)
+
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, oop, obj_field, EMPTY_CAST)
+#define OBJECTARRAY_FIELD(className, name, signature) FIELD(className, name, objArrayOop, obj_field, (objArrayOop))
+#define PRIMARRAY_FIELD(className, name, signature) FIELD(className, name, typeArrayOop, obj_field, (typeArrayOop))
+#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, oop)
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, objArrayOop)
+#define STATIC_OOPISH_FIELD(className, name, type)                                                                        \
+    type HotSpotJVMCI::className::name(JVMCIEnv* env) {                                                                   \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      oop result = HeapAccess<>::oop_load_at(base, className::_##name##_offset);                                          \
+      return type(result);                                                                                                \
+    }                                                                                                                     \
+    void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, type x) {                                                     \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      assert(className::klass() != NULL, "Class not yet loaded: " #className);                                            \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      HeapAccess<>::oop_store_at(base, className::_##name##_offset, x);                                                   \
+    }
+#define STATIC_PRIMITIVE_FIELD(className, name, jtypename)                                                                \
+    jtypename HotSpotJVMCI::className::get_##name(JVMCIEnv* env) {                                                        \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      return HeapAccess<>::load_at(base, className::_##name##_offset);                                                    \
+    }                                                                                                                     \
+    void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, jtypename x) {                                                \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      HeapAccess<>::store_at(base, _##name##_offset, x);                                                                  \
+    }
+
+#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean)
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+/**
+ * Generates the method and field definitions for the classes in HotSpotJVMCI. For example:
+ *
+ * void HotSpotJVMCI::Architecture::initialize(JVMCIEnv* env) { ... }
+ * bool HotSpotJVMCI::Architecture::is_instance(JVMCIEnv* env, JVMCIObject object) { ... }
+ * void HotSpotJVMCI::Architecture::check(oop obj, const char* field_name, int offset) { ... }
+ *  oop HotSpotJVMCI::Architecture::wordKind(JVMCIEnv* env, oop obj) { ... }
+ * void HotSpotJVMCI::Architecture::set_wordKind(JVMCIEnv* env, oop obj, oop x) { ... }
+ *
+ * InstanceKlass *HotSpotJVMCI::Architecture::_klass = NULL;
+ */
+JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+#undef START_CLASS
+#undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef STATIC_PRIMITIVE_FIELD
+#undef EMPTY_CAST
+
+/**
+ * Initializes the JNI id of a field. As per the JNI specification,
+ * this ensures the declaring class is initialized.
+ */
+void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, const char* class_name, const char* name, const char* signature, bool static_field) {
+  if (JVMCILibDumpJNIConfig != NULL) {
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+    st->print_cr("field %s %s %s", class_name, name, signature);
+    return;
+  }
+  if (env->ExceptionCheck()) {
+    return;
+  }
+  if (static_field) {
+    // Class initialization barrier
+    fieldid = env->GetStaticFieldID(clazz, name, signature);
+  } else {
+    // Class initialization barrier
+    fieldid = env->GetFieldID(clazz, name, signature);
+  }
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    env->ExceptionClear();
+    ResourceMark rm;
+    Thread* THREAD = Thread::current();
+    fatal("Could not find field %s.%s with signature %s", class_name, name, signature);
+  }
+}
 
+#define START_CLASS(className, fullClassName) {                                             \
+  current_class_name = vmSymbols::fullClassName()->as_C_string();                           \
+  if (JVMCILibDumpJNIConfig != NULL) {                                                      \
+    fileStream* st = JVMCIGlobals::get_jni_config_file();                                   \
+    st->print_cr("class %s", current_class_name);                                           \
+  } else {                                                                                  \
+    jclass k = env->FindClass(current_class_name);                                          \
+    JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", current_class_name);                        \
+    assert(k != NULL, #fullClassName " not initialized");                                   \
+    className::_class = (jclass) env->NewGlobalRef(k);                                      \
+  }
 
-void JVMCIJavaClasses::compute_offsets(TRAPS) {
-  COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+#define END_CLASS current_class_name = NULL; }
+
+#define FIELD(className, name, signature, static_field) initialize_field_id(env, className::_##name##_field_id, className::_class, current_class_name, #name, signature, static_field);
+#define CHAR_FIELD(className, name) FIELD(className, name, "C", false)
+#define INT_FIELD(className, name) FIELD(className, name, "I", false)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false)
+#define LONG_FIELD(className, name) FIELD(className, name, "J", false)
+#define FLOAT_FIELD(className, name) FIELD(className, name, "F", false)
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false)
+#define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true)
+#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
+
+#define GET_JNI_METHOD(jniGetMethod, dst, clazz, methodName, signature)                        \
+          if (JVMCILibDumpJNIConfig != NULL) {                                                       \
+            fileStream* st = JVMCIGlobals::get_jni_config_file();                                    \
+            st->print_cr("method %s %s %s", current_class_name, methodName, signature);              \
+          } else {                                                                                   \
+                  dst = env->jniGetMethod(clazz, methodName, signature);                                   \
+                  JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", current_class_name, methodName, signature); \
+                assert(dst != NULL, "uninitialized");                                          \
+          }
+
+#define GET_JNI_CONSTRUCTOR(clazz, signature) \
+  GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "<init>", signature) \
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+     GET_JNI_METHOD(jniGetMethod,                                        \
+                    className::_##methodName##_method,                   \
+                    className::clazz(),                                  \
+                    vmSymbols::methodName##_name()->as_C_string(),       \
+                    vmSymbols::signatureSymbolName()->as_C_string())
+
+#define CONSTRUCTOR(className, signature) \
+  GET_JNI_CONSTRUCTOR(className, signature)
+
+extern "C" {
+  void     JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
+  jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
 }
 
+#define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
+/**
+ * Initializes the JNI method and field ids used in JNIJVMCI.
+ */
+void JNIJVMCI::initialize_ids(JNIEnv* env) {
+  ResourceMark rm;
+  const char* current_class_name = NULL;
+  JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, OBJECT_FIELD, OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+  IN_CLASS(java_lang_Class);
+  GET_JNI_METHOD(GetMethodID, _Class_getName_method, Class::_class, "getName", "()Ljava/lang/String;");
+
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedPrimitiveType_fromMetaspace_method, HotSpotResolvedPrimitiveType::_class,
+                                                                                          vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                          vmSymbols::primitive_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedObjectTypeImpl_fromMetaspace_method, HotSpotResolvedObjectTypeImpl::_class,
+                                                                                           vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                           vmSymbols::klass_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotConstantPool);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotConstantPool_fromMetaspace_method, HotSpotConstantPool::_class,
+                                                                                  vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                  vmSymbols::constantPool_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedJavaMethodImpl_fromMetaspace_method, HotSpotResolvedJavaMethodImpl::_class,
+                                                                                           vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                           vmSymbols::method_fromMetaspace_signature()->as_C_string());
+
+#define BOX_CLASSES(generate)     \
+  generate(Boolean, T_BOOLEAN, Z) \
+  generate(Byte, T_BYTE, B)       \
+  generate(Character, T_CHAR, C)  \
+  generate(Short, T_SHORT, S)     \
+  generate(Integer, T_INT, I)     \
+  generate(Long, T_LONG, J)       \
+  generate(Float, T_FLOAT, F)     \
+  generate(Double, T_DOUBLE, D)   \
+
+#define DO_BOX_CLASS(klass, basicType, type) \
+  current_class_name = "java/lang/" #klass;                                                                       \
+  if (JVMCILibDumpJNIConfig == NULL) {                                                                            \
+    _box_classes[basicType] = env->FindClass("java/lang/" #klass);                                                \
+    JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", #klass);                                                          \
+    _box_classes[basicType] = (jclass) env->NewGlobalRef(_box_classes[basicType]);                                \
+    assert(_box_classes[basicType] != NULL, "uninitialized");                                                     \
+    _box_fields[basicType] = env->GetFieldID(_box_classes[basicType], "value", #type);                            \
+    JVMCI_EXCEPTION_CHECK(env, "GetFieldID(%s, value, %s)", #klass, #type);                                       \
+    GET_JNI_METHOD(GetMethodID, _box_constructors[basicType], _box_classes[basicType], "<init>", "(" #type ")V"); \
+  } else {                                                                                                        \
+    fileStream* st = JVMCIGlobals::get_jni_config_file();                                                         \
+    st->print_cr("field %s value %s", current_class_name, #type);                                                 \
+    st->print_cr("method %s <init> (%s)V", current_class_name, #type);                                            \
+  }
+
+  BOX_CLASSES(DO_BOX_CLASS);
+
+  if (JVMCILibDumpJNIConfig == NULL) {
+    _byte_array = env->FindClass("[B");
+    JVMCI_EXCEPTION_CHECK(env, "FindClass([B)");
+    _byte_array = (jclass) env->NewGlobalRef(_byte_array);
+    assert(_byte_array != NULL, "uninitialized");
+  } else {
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+    st->print_cr("class [B");
+  }
+
+#define DUMP_ALL_NATIVE_METHODS(class_symbol) do {                                                                  \
+  current_class_name = class_symbol->as_C_string();                                                                 \
+  Klass* k = SystemDictionary::resolve_or_fail(class_symbol, true, CHECK_EXIT);                                     \
+  InstanceKlass* iklass = InstanceKlass::cast(k);                                                                   \
+  Array<Method*>* methods = iklass->methods();                                                                      \
+  for (int i = 0; i < methods->length(); i++) {                                                                     \
+    Method* m = methods->at(i);                                                                                     \
+    if (m->is_native()) {                                                                                           \
+      st->print_cr("method %s %s %s", current_class_name, m->name()->as_C_string(), m->signature()->as_C_string()); \
+    }                                                                                                               \
+  }                                                                                                                 \
+} while(0)
+
+  if (JVMCILibDumpJNIConfig != NULL) {
+    Thread* THREAD = Thread::current();
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+
+    DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
+
+    st->flush();
+    tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
+    vm_exit(0);
+  }
+
+#undef DUMP_ALL_NATIVE_METHODS
+#undef DO_BOX_CLASS
+#undef BOX_CLASSES
+#undef IN_CLASS
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f))
+
+  if (env != JavaThread::current()->jni_environment()) {
+    jclass clazz = env->FindClass("jdk/vm/ci/hotspot/CompilerToVM");
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "Could not find class jdk/vm/ci/hotspot/CompilerToVM");
+    }
+    JNINativeMethod CompilerToVM_native_methods[] = {
+      { CC"registerNatives",     CC"()V", FN_PTR(JVM_RegisterJVMCINatives)     },
+    };
+    env->RegisterNatives(clazz, CompilerToVM_native_methods, 1);
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "");
+    }
+
+    JNINativeMethod JVMCI_native_methods[] = {
+      { CC"initializeRuntime",   CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) },
+    };
+    env->RegisterNatives(JVMCI::clazz(), JVMCI_native_methods, 1);
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "");
+    }
+  }
+}
+
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD2
+
 #define EMPTY0
 #define EMPTY1(x)
 #define EMPTY2(x,y)
-#define FIELD2(klass, name) int klass::_##name##_offset = 0;
-#define FIELD3(klass, name, sig) FIELD2(klass, name)
+#define FIELD3(className, name, sig) FIELD2(className, name)
+#define FIELD2(className, name) \
+  jfieldID JNIJVMCI::className::_##name##_field_id = 0; \
+  int HotSpotJVMCI::className::_##name##_offset = 0;
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+// Generates the definitions of static fields used by the accessors. For example:
+//  jfieldID JNIJVMCI::Architecture::_wordKind_field_id = 0;
+//  jfieldID HotSpotJVMCI::Architecture::_wordKind_offset = 0;
+JVMCI_CLASSES_DO(EMPTY2, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2, METHOD, CONSTRUCTOR)
+
+#undef START_CLASS
+#undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+
+#define START_CLASS(className, fullClassName)                                                                                     \
+  void JNIJVMCI::className::initialize(JVMCI_TRAPS) {                                                                             \
+    /* should already be initialized */                                                                                           \
+  }                                                                                                                               \
+  bool JNIJVMCI::className::is_instance(JVMCIEnv* jvmciEnv, JVMCIObject object) {                                                 \
+    JNIAccessMark jni(jvmciEnv);                                                                                                  \
+    return jni()->IsInstanceOf(object.as_jobject(), className::clazz()) != 0;                                                     \
+  }                                                                                                                               \
+  void JNIJVMCI::className::check(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset) {                 \
+    assert(obj.is_non_null(), "NULL field access of %s.%s", #className, field_name);                                     \
+    assert(jvmciEnv->isa_##className(obj), "wrong class, " #className " expected, found %s", jvmciEnv->klass_name(obj)); \
+    assert(offset != 0, "must be valid offset");                                                                                  \
+  }                                                                                                                               \
+  jclass JNIJVMCI::className::_class = NULL;
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor, cast)                                                                \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) {                                       \
+   className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                                           \
+   JNIAccessMark jni(jvmciEnv);                               \
+   return cast jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id); \
+  }                                                                                                                 \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) {                               \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                                          \
+    JNIAccessMark jni(jvmciEnv); \
+    jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, x);         \
+  } \
+
+#define EMPTY_CAST
+#define CHAR_FIELD(className, name)                    FIELD(className, name, jchar, Char, EMPTY_CAST)
+#define INT_FIELD(className, name)                     FIELD(className, name, jint, Int, EMPTY_CAST)
+#define BOOLEAN_FIELD(className, name)                 FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
+#define LONG_FIELD(className, name)                    FIELD(className, name, jlong, Long, EMPTY_CAST)
+#define FLOAT_FIELD(className, name)                   FIELD(className, name, jfloat, Float, EMPTY_CAST)
 
-COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2)
+#define OBJECT_FIELD(className, name, signature)              OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST)
+#define OBJECTARRAY_FIELD(className, name, signature)         OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
+#define PRIMARRAY_FIELD(className, name, signature)           OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray))
+
+#define STATIC_OBJECT_FIELD(className, name, signature)       STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject))
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature)  STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
+
+#define OOPISH_FIELD(className, name, type, accessor, cast)                                             \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) {                           \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                              \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast wrap(jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id));  \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) {                   \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                              \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, resolve_handle(x)); \
+  }
+
+#define STATIC_OOPISH_FIELD(className, name, type, accessor, cast)                                      \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) {                                            \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast wrap(jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id));  \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) {                                    \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, resolve_handle(x)); \
+  }
 
+#define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast)                                   \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) {                                            \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id);   \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) {                                    \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, x);            \
+  }
+
+#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+  jmethodID JNIJVMCI::className::_##methodName##_method;
+
+#define CONSTRUCTOR(className, signature) \
+  jmethodID JNIJVMCI::className::_constructor;
+
+/**
+ * Generates the method definitions for the classes in HotSpotJVMCI.
+ */
+JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+#undef METHOD
+#undef CONSTRUCTOR
+#undef START_CLASS
+#undef END_CLASS
+#undef FIELD
+#undef CHAR_FIELD
+#undef INT_FIELD
+#undef BOOLEAN_FIELD
+#undef LONG_FIELD
+#undef FLOAT_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef STATIC_PRIMITIVE_FIELD
+#undef OOPISH_FIELD
+#undef EMPTY_CAST
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri May 03 14:59:32 2019 -0400
@@ -24,361 +24,644 @@
 #ifndef SHARE_JVMCI_JVMCIJAVACLASSES_HPP
 #define SHARE_JVMCI_JVMCIJAVACLASSES_HPP
 
-#include "classfile/systemDictionary.hpp"
-#include "oops/access.hpp"
-#include "oops/instanceMirrorKlass.hpp"
-#include "oops/oop.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "jvmci/jvmciExceptions.hpp"
+#include "jvmci/jvmciObject.hpp"
+#include "runtime/jniHandles.hpp"
 
-class JVMCIJavaClasses : AllStatic {
- public:
-  static void compute_offsets(TRAPS);
-};
-
-/* This macro defines the structure of the JVMCI classes accessed from VM code.
- * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles.
+/*
+ * This macro defines the structure of the JVMCI classes accessed from VM code.  It is used to
+ * generate accessors similar to javaClasses.hpp, but with specializations for HotSpot and JNI based
+ * access.
  *
- * The public interface of these classes will look like this:
-
- * class StackSlot : AllStatic {
- * public:
- *   static Klass* klass();
- *   static jint  index(oop obj);
- *   static jint  index(Handle obj);
- *   static jint  index(jobject obj);
- *   static void set_index(oop obj, jint x);
- *   static void set_index(Handle obj, jint x);
- *   static void set_index(jobject obj, jint x);
- * };
+ * HotSpotJVMCI: This class contains accessors based on the VM internal
+ * interface to Java. It is used for JVMCI Java code executing on the HotSpot heap.
  *
+ * JNIJVMCI: This class contains JNI based accessors and is used for JVMCI
+ * Java code executing in the JVMCI shared library.
  */
 
-#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, typeArrayOop_field, objArrayOop_field, static_oop_field, static_objArrayOop_field, static_int_field, static_boolean_field) \
-  start_class(Architecture)                                                                                                                                    \
-    oop_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(TargetDescription)                                                                                                                               \
-    oop_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotResolvedObjectTypeImpl)                                                                                                                   \
-    oop_field(HotSpotResolvedObjectTypeImpl, javaClass, "Ljava/lang/Class;")                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotResolvedJavaMethodImpl)                                                                                                                   \
-    long_field(HotSpotResolvedJavaMethodImpl, metaspaceMethod)                                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(InstalledCode)                                                                                                                                   \
-    long_field(InstalledCode, address)                                                                                                                         \
-    long_field(InstalledCode, entryPoint)                                                                                                                      \
-    long_field(InstalledCode, version)                                                                                                                         \
-    oop_field(InstalledCode, name, "Ljava/lang/String;")                                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotInstalledCode)                                                                                                                            \
-    int_field(HotSpotInstalledCode, size)                                                                                                                      \
-    long_field(HotSpotInstalledCode, codeStart)                                                                                                                \
-    int_field(HotSpotInstalledCode, codeSize)                                                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotNmethod)                                                                                                                                  \
-    boolean_field(HotSpotNmethod, isDefault)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode)                                                                                                                             \
-    oop_field(HotSpotCompiledCode, name, "Ljava/lang/String;")                                                                                                 \
-    typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B")                                                                                                  \
-    int_field(HotSpotCompiledCode, targetCodeSize)                                                                                                             \
-    objArrayOop_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/site/Site;")                                                                               \
-    objArrayOop_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;")                                                            \
-    objArrayOop_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                    \
-    objArrayOop_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;")                                                       \
-    typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B")                                                                                                 \
-    int_field(HotSpotCompiledCode, dataSectionAlignment)                                                                                                       \
-    objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;")                                                             \
-    boolean_field(HotSpotCompiledCode, isImmutablePIC)                                                                                                         \
-    int_field(HotSpotCompiledCode, totalFrameSize)                                                                                                             \
-    oop_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;")                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
-    oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
-    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledNmethod)                                                                                                                          \
-    oop_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                                 \
-    oop_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                                                                        \
-    int_field(HotSpotCompiledNmethod, entryBCI)                                                                                                                \
-    int_field(HotSpotCompiledNmethod, id)                                                                                                                      \
-    long_field(HotSpotCompiledNmethod, jvmciEnv)                                                                                                               \
-    boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess)                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotJVMCIMetaAccessContext)                                                                                                                   \
-    static_objArrayOop_field(HotSpotJVMCIMetaAccessContext, allContexts, "[Ljava/lang/ref/WeakReference;")                                                     \
-    objArrayOop_field(HotSpotJVMCIMetaAccessContext, metadataRoots, "[Ljava/lang/Object;")                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotForeignCallTarget)                                                                                                                        \
-    long_field(HotSpotForeignCallTarget, address)                                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(VMField)                                                                                                                                         \
-    oop_field(VMField, name, "Ljava/lang/String;")                                                                                                             \
-    oop_field(VMField, type, "Ljava/lang/String;")                                                                                                             \
-    long_field(VMField, offset)                                                                                                                                \
-    long_field(VMField, address)                                                                                                                               \
-    oop_field(VMField, value, "Ljava/lang/Object;")                                                                                                            \
-  end_class                                                                                                                                                    \
-  start_class(VMFlag)                                                                                                                                          \
-    oop_field(VMFlag, name, "Ljava/lang/String;")                                                                                                              \
-    oop_field(VMFlag, type, "Ljava/lang/String;")                                                                                                              \
-    oop_field(VMFlag, value, "Ljava/lang/Object;")                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(VMIntrinsicMethod)                                                                                                                               \
-    oop_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;")                                                                                         \
-    oop_field(VMIntrinsicMethod, name, "Ljava/lang/String;")                                                                                                   \
-    oop_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;")                                                                                             \
-    int_field(VMIntrinsicMethod, id)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
-    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                            \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
-    oop_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
-    oop_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_LeafType)                                                                                                                            \
-    oop_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_ConcreteMethod)                                                                                                                      \
-    oop_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                       \
-    oop_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                        \
-    oop_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_CallSiteTargetValue)                                                                                                                 \
-    oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljdk/vm/ci/meta/JavaConstant;")                                                                      \
-    oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljdk/vm/ci/meta/JavaConstant;")                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(site_Site)                                                                                                                                       \
-    int_field(site_Site, pcOffset)                                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(site_Call)                                                                                                                                       \
-    oop_field(site_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;")                                                                                              \
-    oop_field(site_Call, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(site_DataPatch)                                                                                                                                  \
-    oop_field(site_DataPatch, reference, "Ljdk/vm/ci/code/site/Reference;")                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(site_ConstantReference)                                                                                                                          \
-    oop_field(site_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;")                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(site_DataSectionReference)                                                                                                                       \
-    int_field(site_DataSectionReference, offset)                                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(site_InfopointReason)                                                                                                                            \
-    static_oop_field(site_InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                 \
-    static_oop_field(site_InfopointReason, CALL, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                      \
-    static_oop_field(site_InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/site/InfopointReason;")                                                        \
-  end_class                                                                                                                                                    \
-  start_class(site_Infopoint)                                                                                                                                  \
-    oop_field(site_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                         \
-    oop_field(site_Infopoint, reason, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(site_ExceptionHandler)                                                                                                                           \
-    int_field(site_ExceptionHandler, handlerPos)                                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(site_Mark)                                                                                                                                       \
-    oop_field(site_Mark, id, "Ljava/lang/Object;")                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompilationRequestResult)                                                                                                                 \
-    oop_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;")                                                                           \
-    boolean_field(HotSpotCompilationRequestResult, retry)                                                                                                      \
-    int_field(HotSpotCompilationRequestResult, inlinedBytecodes)                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(DebugInfo)                                                                                                                                       \
-    oop_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                \
-    oop_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;")                                                                                        \
-    oop_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;")                                                                                \
-    objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;")                                                                      \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotReferenceMap)                                                                                                                             \
-    objArrayOop_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;")                                                                              \
-    objArrayOop_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;")                                                                          \
-    typeArrayOop_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                                                                 \
-    int_field(HotSpotReferenceMap, maxRegisterSize)                                                                                                            \
-  end_class                                                                                                                                                    \
-  start_class(RegisterSaveLayout)                                                                                                                              \
-    objArrayOop_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;")                                                                             \
-    typeArrayOop_field(RegisterSaveLayout, slots, "[I")                                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(BytecodeFrame)                                                                                                                                   \
-    objArrayOop_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
-    objArrayOop_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
-    int_field(BytecodeFrame, numLocals)                                                                                                                        \
-    int_field(BytecodeFrame, numStack)                                                                                                                         \
-    int_field(BytecodeFrame, numLocks)                                                                                                                         \
-    boolean_field(BytecodeFrame, rethrowException)                                                                                                             \
-    boolean_field(BytecodeFrame, duringCall)                                                                                                                   \
-    static_int_field(BytecodeFrame, UNKNOWN_BCI)                                                                                                               \
-    static_int_field(BytecodeFrame, UNWIND_BCI)                                                                                                                \
-    static_int_field(BytecodeFrame, BEFORE_BCI)                                                                                                                \
-    static_int_field(BytecodeFrame, AFTER_BCI)                                                                                                                 \
-    static_int_field(BytecodeFrame, AFTER_EXCEPTION_BCI)                                                                                                       \
-    static_int_field(BytecodeFrame, INVALID_FRAMESTATE_BCI)                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(BytecodePosition)                                                                                                                                \
-    oop_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                   \
-    oop_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                                 \
-    int_field(BytecodePosition, bci)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(JavaConstant)                                                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(PrimitiveConstant)                                                                                                                               \
-    oop_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;")                                                                                            \
-    long_field(PrimitiveConstant, primitive)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(RawConstant)                                                                                                                                     \
-    long_field(RawConstant, primitive)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(NullConstant)                                                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompressedNullConstant)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotObjectConstantImpl)                                                                                                                       \
-    oop_field(HotSpotObjectConstantImpl, object, "Ljava/lang/Object;")                                                                                         \
-    boolean_field(HotSpotObjectConstantImpl, compressed)                                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotMetaspaceConstantImpl)                                                                                                                    \
-    oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceWrapperObject;")                                                     \
-    boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotSentinelConstant)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(JavaKind)                                                                                                                                        \
-    char_field(JavaKind, typeChar)                                                                                                                             \
-    static_oop_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;")                                                                                           \
-    static_oop_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-    static_oop_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-    static_oop_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;")                                                                                             \
-    static_oop_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;")                                                                                               \
-    static_oop_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(ValueKind)                                                                                                                                       \
-    oop_field(ValueKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(Value)                                                                                                                                           \
-    oop_field(Value, valueKind, "Ljdk/vm/ci/meta/ValueKind;")                                                                                                  \
-    static_oop_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                      \
-  end_class                                                                                                                                                    \
-  start_class(RegisterValue)                                                                                                                                   \
-    oop_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(code_Location)                                                                                                                                   \
-    oop_field(code_Location, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
-    int_field(code_Location, offset)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(code_Register)                                                                                                                                   \
-    int_field(code_Register, number)                                                                                                                           \
-    int_field(code_Register, encoding)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(StackSlot)                                                                                                                                       \
-    int_field(StackSlot, offset)                                                                                                                               \
-    boolean_field(StackSlot, addFrameSize)                                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(VirtualObject)                                                                                                                                   \
-    int_field(VirtualObject, id)                                                                                                                               \
-    oop_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                                        \
-    objArrayOop_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
-    objArrayOop_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(StackLockValue)                                                                                                                                  \
-    oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                                                                             \
-    oop_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                       \
-    boolean_field(StackLockValue, eliminated)                                                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotSpeculationLog)                                                                                                                           \
-    long_field(HotSpotSpeculationLog, lastFailed)                                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotStackFrameReference)                                                                                                                      \
-    oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                                                                    \
-    boolean_field(HotSpotStackFrameReference, objectsMaterialized)                                                                                             \
-    long_field(HotSpotStackFrameReference, stackPointer)                                                                                                       \
-    int_field(HotSpotStackFrameReference, frameNumber)                                                                                                         \
-    int_field(HotSpotStackFrameReference, bci)                                                                                                                 \
-    oop_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                             \
-    objArrayOop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                                                                               \
-    typeArrayOop_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotMetaData)                                                                                                                                 \
-    typeArrayOop_field(HotSpotMetaData, pcDescBytes, "[B")                                                                                                     \
-    typeArrayOop_field(HotSpotMetaData, scopesDescBytes, "[B")                                                                                                 \
-    typeArrayOop_field(HotSpotMetaData, relocBytes, "[B")                                                                                                      \
-    typeArrayOop_field(HotSpotMetaData, exceptionBytes, "[B")                                                                                                  \
-    typeArrayOop_field(HotSpotMetaData, oopMaps, "[B")                                                                                                         \
-    objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotConstantPool)                                                                                                                             \
-    long_field(HotSpotConstantPool, metaspaceConstantPool)                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotJVMCIRuntime)                                                                                                                             \
-    int_field(HotSpotJVMCIRuntime, compilationLevelAdjustment)                                                                                                 \
-  end_class                                                                                                                                                    \
+#define JVMCI_CLASSES_DO(start_class, \
+                         end_class, \
+                         char_field, \
+                         int_field, \
+                         boolean_field, \
+                         long_field, \
+                         float_field, \
+                         object_field, \
+                         primarray_field, \
+                         objectarray_field, \
+                         static_object_field, \
+                         static_objectarray_field, \
+                         static_int_field, \
+                         static_boolean_field, \
+                         jvmci_method, \
+                         jvmci_constructor) \
+  start_class(Services, jdk_vm_ci_services_Services)                                                          \
+    jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, Services, initializeSavedProperties, byte_array_void_signature, (JVMCIObject serializedProperties)) \
+  end_class                                                                                                   \
+  start_class(Architecture, jdk_vm_ci_code_Architecture)                                                      \
+    object_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;")                                     \
+  end_class                                                                                                   \
+  start_class(TargetDescription, jdk_vm_ci_code_TargetDescription)                                            \
+    object_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;")                                    \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedObjectTypeImpl, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl)                 \
+    long_field(HotSpotResolvedObjectTypeImpl, metadataPointer)                                                \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedPrimitiveType, jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType)                   \
+    object_field(HotSpotResolvedPrimitiveType, mirror, "Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;")       \
+  object_field(HotSpotResolvedPrimitiveType, kind, "Ljdk/vm/ci/meta/JavaKind;")                               \
+    static_objectarray_field(HotSpotResolvedPrimitiveType, primitives, "[Ljdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType;") \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedJavaFieldImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl)                   \
+    object_field(HotSpotResolvedJavaFieldImpl, type, "Ljdk/vm/ci/meta/JavaType;")                             \
+    object_field(HotSpotResolvedJavaFieldImpl, holder, "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;")   \
+    int_field(HotSpotResolvedJavaFieldImpl, offset)                                                           \
+    int_field(HotSpotResolvedJavaFieldImpl, modifiers)                                                        \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl)                 \
+    long_field(HotSpotResolvedJavaMethodImpl, metadataHandle)                                                 \
+  end_class                                                                                                   \
+  start_class(InstalledCode, jdk_vm_ci_code_InstalledCode)                                                    \
+    long_field(InstalledCode, address)                                                                        \
+    long_field(InstalledCode, entryPoint)                                                                     \
+    long_field(InstalledCode, version)                                                                        \
+    object_field(InstalledCode, name, "Ljava/lang/String;")                                                   \
+  end_class                                                                                                   \
+  start_class(HotSpotInstalledCode, jdk_vm_ci_hotspot_HotSpotInstalledCode)                                   \
+    int_field(HotSpotInstalledCode, size)                                                                     \
+    long_field(HotSpotInstalledCode, codeStart)                                                               \
+    int_field(HotSpotInstalledCode, codeSize)                                                                 \
+  end_class                                                                                                   \
+  start_class(HotSpotNmethod, jdk_vm_ci_hotspot_HotSpotNmethod)                                               \
+    boolean_field(HotSpotNmethod, isDefault)                                                                  \
+    long_field(HotSpotNmethod, compileIdSnapshot)                                                             \
+    object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;")                 \
+    jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode)                                     \
+    object_field(HotSpotCompiledCode, name, "Ljava/lang/String;")                                             \
+    primarray_field(HotSpotCompiledCode, targetCode, "[B")                                                    \
+    int_field(HotSpotCompiledCode, targetCodeSize)                                                            \
+    objectarray_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/site/Site;")                              \
+    objectarray_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;")           \
+    objectarray_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;")                   \
+    objectarray_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;")      \
+    primarray_field(HotSpotCompiledCode, dataSection, "[B")                                                   \
+    int_field(HotSpotCompiledCode, dataSectionAlignment)                                                      \
+    objectarray_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;")            \
+    boolean_field(HotSpotCompiledCode, isImmutablePIC)                                                        \
+    int_field(HotSpotCompiledCode, totalFrameSize)                                                            \
+    object_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;")                          \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledCode_Comment, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment)                     \
+    object_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                     \
+    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                          \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledNmethod, jdk_vm_ci_hotspot_HotSpotCompiledNmethod)                               \
+    object_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")             \
+    object_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                    \
+    int_field(HotSpotCompiledNmethod, entryBCI)                                                               \
+    int_field(HotSpotCompiledNmethod, id)                                                                     \
+    long_field(HotSpotCompiledNmethod, compileState)                                                           \
+    boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess)                                                    \
+  end_class                                                                                                   \
+  start_class(HotSpotForeignCallTarget, jdk_vm_ci_hotspot_HotSpotForeignCallTarget)                           \
+    long_field(HotSpotForeignCallTarget, address)                                                             \
+  end_class                                                                                                   \
+  start_class(VMField, jdk_vm_ci_hotspot_VMField)                                                             \
+    object_field(VMField, name, "Ljava/lang/String;")                                                         \
+    object_field(VMField, type, "Ljava/lang/String;")                                                         \
+    long_field(VMField, offset)                                                                               \
+    long_field(VMField, address)                                                                              \
+    object_field(VMField, value, "Ljava/lang/Object;")                                                        \
+    jvmci_constructor(VMField, "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/Object;)V")                 \
+  end_class                                                                                                   \
+  start_class(VMFlag, jdk_vm_ci_hotspot_VMFlag)                                                               \
+    object_field(VMFlag, name, "Ljava/lang/String;")                                                          \
+    object_field(VMFlag, type, "Ljava/lang/String;")                                                          \
+    object_field(VMFlag, value, "Ljava/lang/Object;")                                                         \
+    jvmci_constructor(VMFlag, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V")                    \
+  end_class                                                                                                   \
+  start_class(VMIntrinsicMethod, jdk_vm_ci_hotspot_VMIntrinsicMethod)                                         \
+    object_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;")                                     \
+    object_field(VMIntrinsicMethod, name, "Ljava/lang/String;")                                               \
+    object_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;")                                         \
+    int_field(VMIntrinsicMethod, id)                                                                          \
+    jvmci_constructor(VMIntrinsicMethod, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")        \
+  end_class                                                                                                   \
+  start_class(Assumptions_NoFinalizableSubclass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass)            \
+    object_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;")        \
+  end_class                                                                                                   \
+  start_class(Assumptions_ConcreteSubtype, jdk_vm_ci_meta_Assumptions_ConcreteSubtype)                        \
+    object_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                   \
+    object_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;")                   \
+  end_class                                                                                                   \
+  start_class(Assumptions_LeafType, jdk_vm_ci_meta_Assumptions_LeafType)                                      \
+    object_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                          \
+  end_class                                                                                                   \
+  start_class(Assumptions_ConcreteMethod, jdk_vm_ci_meta_Assumptions_ConcreteMethod)                          \
+    object_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                   \
+    object_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                    \
+    object_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                     \
+  end_class                                                                                                   \
+  start_class(Assumptions_CallSiteTargetValue, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue)                \
+    object_field(Assumptions_CallSiteTargetValue, callSite, "Ljdk/vm/ci/meta/JavaConstant;")                  \
+    object_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljdk/vm/ci/meta/JavaConstant;")              \
+  end_class                                                                                                   \
+  start_class(site_Site, jdk_vm_ci_code_site_Site)                                                            \
+    int_field(site_Site, pcOffset)                                                                            \
+  end_class                                                                                                   \
+  start_class(site_Call, jdk_vm_ci_code_site_Call)                                                            \
+    object_field(site_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;")                                          \
+  end_class                                                                                                   \
+  start_class(site_DataPatch, jdk_vm_ci_code_site_DataPatch)                                                  \
+    object_field(site_DataPatch, reference, "Ljdk/vm/ci/code/site/Reference;")                                \
+  end_class                                                                                                   \
+  start_class(site_ConstantReference, jdk_vm_ci_code_site_ConstantReference)                                  \
+    object_field(site_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;")                             \
+  end_class                                                                                                   \
+  start_class(site_DataSectionReference, jdk_vm_ci_code_site_DataSectionReference)                            \
+    int_field(site_DataSectionReference, offset)                                                              \
+  end_class                                                                                                   \
+  start_class(site_InfopointReason, jdk_vm_ci_code_site_InfopointReason)                                      \
+    static_object_field(site_InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/site/InfopointReason;")             \
+    static_object_field(site_InfopointReason, CALL, "Ljdk/vm/ci/code/site/InfopointReason;")                  \
+    static_object_field(site_InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/site/InfopointReason;")    \
+  end_class                                                                                                   \
+  start_class(site_Infopoint, jdk_vm_ci_code_site_Infopoint)                                                  \
+    object_field(site_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                     \
+    object_field(site_Infopoint, reason, "Ljdk/vm/ci/code/site/InfopointReason;")                             \
+  end_class                                                                                                   \
+  start_class(site_ExceptionHandler, jdk_vm_ci_code_site_ExceptionHandler)                                    \
+    int_field(site_ExceptionHandler, handlerPos)                                                              \
+  end_class                                                                                                   \
+  start_class(site_Mark, jdk_vm_ci_code_site_Mark)                                                            \
+    object_field(site_Mark, id, "Ljava/lang/Object;")                                                         \
+  end_class                                                                                                   \
+  start_class(HotSpotCompilationRequestResult, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult)             \
+    object_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;")                       \
+    boolean_field(HotSpotCompilationRequestResult, retry)                                                     \
+    int_field(HotSpotCompilationRequestResult, inlinedBytecodes)                                              \
+  end_class                                                                                                   \
+  start_class(DebugInfo, jdk_vm_ci_code_DebugInfo)                                                            \
+    object_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;")                            \
+    object_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;")                                    \
+    object_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;")                            \
+    objectarray_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;")                     \
+  end_class                                                                                                   \
+  start_class(HotSpotReferenceMap, jdk_vm_ci_hotspot_HotSpotReferenceMap)                                     \
+    objectarray_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;")                             \
+    objectarray_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;")                         \
+    primarray_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                   \
+    int_field(HotSpotReferenceMap, maxRegisterSize)                                                           \
+  end_class                                                                                                   \
+  start_class(RegisterSaveLayout, jdk_vm_ci_code_RegisterSaveLayout)                                          \
+    objectarray_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;")                            \
+    primarray_field(RegisterSaveLayout, slots, "[I")                                                          \
+  end_class                                                                                                   \
+  start_class(BytecodeFrame, jdk_vm_ci_code_BytecodeFrame)                                                    \
+    objectarray_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;")                                   \
+    objectarray_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                 \
+    int_field(BytecodeFrame, numLocals)                                                                       \
+    int_field(BytecodeFrame, numStack)                                                                        \
+    int_field(BytecodeFrame, numLocks)                                                                        \
+    boolean_field(BytecodeFrame, rethrowException)                                                            \
+    boolean_field(BytecodeFrame, duringCall)                                                                  \
+    static_int_field(BytecodeFrame, UNKNOWN_BCI)                                                              \
+    static_int_field(BytecodeFrame, UNWIND_BCI)                                                               \
+    static_int_field(BytecodeFrame, BEFORE_BCI)                                                               \
+    static_int_field(BytecodeFrame, AFTER_BCI)                                                                \
+    static_int_field(BytecodeFrame, AFTER_EXCEPTION_BCI)                                                      \
+    static_int_field(BytecodeFrame, INVALID_FRAMESTATE_BCI)                                                   \
+  end_class                                                                                                   \
+  start_class(BytecodePosition, jdk_vm_ci_code_BytecodePosition)                                              \
+    object_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;")                               \
+    object_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                             \
+    int_field(BytecodePosition, bci)                                                                          \
+  end_class                                                                                                   \
+  start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant)                                                      \
+    static_object_field(JavaConstant, NULL_POINTER, "Ljdk/vm/ci/meta/JavaConstant;")                          \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forFloat, forFloat_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forDouble, forDouble_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod)                                          \
+  end_class                                                                                                   \
+  start_class(PrimitiveConstant, jdk_vm_ci_meta_PrimitiveConstant)                                            \
+    object_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;")                                        \
+    long_field(PrimitiveConstant, primitive)                                                                  \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, PrimitiveConstant, forTypeChar, forTypeChar_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(RawConstant, jdk_vm_ci_meta_RawConstant)                                                        \
+  end_class                                                                                                   \
+  start_class(NullConstant, jdk_vm_ci_meta_NullConstant)                                                      \
+  end_class                                                                                                   \
+  start_class(HotSpotCompressedNullConstant, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant)                 \
+  end_class                                                                                                   \
+  start_class(HotSpotObjectConstantImpl, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl)                         \
+    boolean_field(HotSpotObjectConstantImpl, compressed)                                                      \
+  end_class                                                                                                   \
+  start_class(DirectHotSpotObjectConstantImpl, jdk_vm_ci_hotspot_DirectHotSpotObjectConstantImpl)             \
+    object_field(DirectHotSpotObjectConstantImpl, object, "Ljava/lang/Object;")                               \
+    jvmci_constructor(DirectHotSpotObjectConstantImpl, "(Ljava/lang/Object;Z)V")                              \
+  end_class                                                                                                   \
+  start_class(IndirectHotSpotObjectConstantImpl, jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl)         \
+    long_field(IndirectHotSpotObjectConstantImpl, objectHandle)                                               \
+    jvmci_constructor(IndirectHotSpotObjectConstantImpl, "(JZZ)V")                                            \
+  end_class                                                                                                   \
+  start_class(HotSpotMetaspaceConstantImpl, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl)                   \
+    object_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceObject;")        \
+    boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                   \
+  end_class                                                                                                   \
+  start_class(HotSpotSentinelConstant, jdk_vm_ci_hotspot_HotSpotSentinelConstant)                             \
+  end_class                                                                                                   \
+  start_class(JavaKind, jdk_vm_ci_meta_JavaKind)                                                              \
+    char_field(JavaKind, typeChar)                                                                            \
+    static_object_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;")                                       \
+    static_object_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+    static_object_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+    static_object_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;")                                         \
+    static_object_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;")                                           \
+    static_object_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+  end_class                                                                                                   \
+  start_class(ValueKind, jdk_vm_ci_meta_ValueKind)                                                            \
+    object_field(ValueKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;")                                    \
+  end_class                                                                                                   \
+  start_class(Value, jdk_vm_ci_meta_Value)                                                                    \
+    object_field(Value, valueKind, "Ljdk/vm/ci/meta/ValueKind;")                                              \
+    static_object_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;")                                  \
+  end_class                                                                                                   \
+  start_class(RegisterValue, jdk_vm_ci_code_RegisterValue)                                                    \
+    object_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;")                                             \
+  end_class                                                                                                   \
+  start_class(code_Location, jdk_vm_ci_code_Location)                                                         \
+    object_field(code_Location, reg, "Ljdk/vm/ci/code/Register;")                                             \
+    int_field(code_Location, offset)                                                                          \
+  end_class                                                                                                   \
+  start_class(code_Register, jdk_vm_ci_code_Register)                                                         \
+    int_field(code_Register, number)                                                                          \
+    int_field(code_Register, encoding)                                                                        \
+  end_class                                                                                                   \
+  start_class(StackSlot, jdk_vm_ci_code_StackSlot)                                                            \
+    int_field(StackSlot, offset)                                                                              \
+    boolean_field(StackSlot, addFrameSize)                                                                    \
+  end_class                                                                                                   \
+  start_class(VirtualObject, jdk_vm_ci_code_VirtualObject)                                                    \
+    int_field(VirtualObject, id)                                                                              \
+    object_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                    \
+    objectarray_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;")                                   \
+    objectarray_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                 \
+  end_class                                                                                                   \
+  start_class(StackLockValue, jdk_vm_ci_code_StackLockValue)                                                  \
+    object_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                         \
+    object_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                   \
+    boolean_field(StackLockValue, eliminated)                                                                 \
+  end_class                                                                                                   \
+  start_class(HotSpotStackFrameReference, jdk_vm_ci_hotspot_HotSpotStackFrameReference)                       \
+    object_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                \
+    boolean_field(HotSpotStackFrameReference, objectsMaterialized)                                            \
+    long_field(HotSpotStackFrameReference, stackPointer)                                                      \
+    int_field(HotSpotStackFrameReference, frameNumber)                                                        \
+    int_field(HotSpotStackFrameReference, bci)                                                                \
+    object_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")         \
+    objectarray_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                              \
+    primarray_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                         \
+  end_class                                                                                                   \
+  start_class(HotSpotMetaData, jdk_vm_ci_hotspot_HotSpotMetaData)                                             \
+    primarray_field(HotSpotMetaData, pcDescBytes, "[B")                                                       \
+    primarray_field(HotSpotMetaData, scopesDescBytes, "[B")                                                   \
+    primarray_field(HotSpotMetaData, relocBytes, "[B")                                                        \
+    primarray_field(HotSpotMetaData, exceptionBytes, "[B")                                                    \
+    primarray_field(HotSpotMetaData, oopMaps, "[B")                                                           \
+    object_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                            \
+  end_class                                                                                                   \
+  start_class(HotSpotConstantPool, jdk_vm_ci_hotspot_HotSpotConstantPool)                                     \
+    long_field(HotSpotConstantPool, metadataHandle)                                                           \
+  end_class                                                                                                   \
+  start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime)                                     \
+    objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;")                \
+    jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, decodeThrowable, decodeThrowable_signature, (JVMCIObject encodedThrowable)) \
+    jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
+    jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \
+    jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, callToString, callToString_signature, (JVMCIObject object, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(JVMCIError, jdk_vm_ci_common_JVMCIError)                                                        \
+    jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V")                                                    \
+  end_class                                                                                                   \
+  start_class(InspectedFrameVisitor, jdk_vm_ci_code_stack_InspectedFrameVisitor)                              \
+  end_class                                                                                                   \
+  start_class(JVMCI, jdk_vm_ci_runtime_JVMCI)                                                                 \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, getRuntime, getRuntime_signature, (JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature, (JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(Object, java_lang_Object)                                                                       \
+  end_class                                                                                                   \
+  start_class(String, java_lang_String)                                                                       \
+  end_class                                                                                                   \
+  start_class(Class, java_lang_Class)                                                                         \
+    jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, Class, getName, void_string_signature, (JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException)                       \
+    jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V")                                \
+  end_class                                                                                                   \
+  start_class(IllegalStateException, java_lang_IllegalStateException)                                         \
+    jvmci_constructor(IllegalStateException, "(Ljava/lang/String;)V")                                         \
+  end_class                                                                                                   \
+  start_class(NullPointerException, java_lang_NullPointerException)                                           \
+    jvmci_constructor(NullPointerException, "(Ljava/lang/String;)V")                                          \
+  end_class                                                                                                   \
+  start_class(IllegalArgumentException, java_lang_IllegalArgumentException)                                   \
+    jvmci_constructor(IllegalArgumentException, "(Ljava/lang/String;)V")                                      \
+  end_class                                                                                                   \
+  start_class(InternalError, java_lang_InternalError)                                                         \
+    jvmci_constructor(InternalError, "(Ljava/lang/String;)V")                                                 \
+  end_class                                                                                                   \
+  start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException)                    \
+    jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V")                                 \
+  end_class                                                                                                   \
+  start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError)                                           \
+    jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V")                                          \
+  end_class                                                                                                   \
+  start_class(StackTraceElement, java_lang_StackTraceElement)                                                 \
+    object_field(StackTraceElement, declaringClass, "Ljava/lang/String;")                                     \
+    object_field(StackTraceElement, methodName, "Ljava/lang/String;")                                         \
+    object_field(StackTraceElement, fileName, "Ljava/lang/String;")                                           \
+    int_field(StackTraceElement, lineNumber)                                                                  \
+    jvmci_constructor(StackTraceElement, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")        \
+  end_class                                                                                                   \
+  start_class(Throwable, java_lang_Throwable)                                                                 \
+    object_field(Throwable, detailMessage, "Ljava/lang/String;")                                              \
+  end_class                                                                                                   \
   /* end*/
 
-#define START_CLASS(name)                                                                                                                                      \
-class name : AllStatic {                                                                                                                                       \
-  private:                                                                                                                                                     \
-    friend class JVMCICompiler;                                                                                                                                \
-    static void check(oop obj, const char* field_name, int offset);                                                                                            \
-    static void compute_offsets(TRAPS);                                                                                                                        \
-  public:                                                                                                                                                      \
-  static InstanceKlass* klass() { return SystemDictionary::name##_klass_is_loaded() ? SystemDictionary::name##_klass() : NULL; }
+class JVMCICompiler;
+class JVMCIEnv;
+
+#define START_CLASS(simpleClassName, fullClassName)      \
+  class simpleClassName { \
+    friend class JVMCIEnv; \
+    static void initialize(JVMCI_TRAPS); \
+    static bool is_instance(JVMCIEnv* jvmciEnv, JVMCIObject object); \
 
 #define END_CLASS };
 
-#define FIELD(name, type, accessor, cast)                                                                                                                         \
-    static int _##name##_offset;                                                                                                                                  \
-    static type name(oop obj)                   { check(obj, #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                             \
-    static type name(Handle obj)                { check(obj(), #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                           \
-    static type name(jobject obj);                                                                                                                                \
-    static void set_##name(oop obj, type x)     { check(obj, #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                                \
-    static void set_##name(Handle obj, type x)  { check(obj(), #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                              \
-    static void set_##name(jobject obj, type x);                                                                                                                  \
+#define EMPTY_CAST
+#define CHAR_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jchar)
+#define INT_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jint)
+#define BOOLEAN_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jboolean)
+#define LONG_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jlong)
+#define FLOAT_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jfloat)
+
+#define OBJECT_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIObject, oop)
+#define OBJECTARRAY_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIObjectArray, objArrayOop)
+#define PRIMARRAY_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIPrimitiveArray, typeArrayOop)
+
+#define STATIC_INT_FIELD(simpleClassName, name) STATIC_FIELD(simpleClassName, name, jint)
+#define STATIC_BOOLEAN_FIELD(simpleClassName, name) STATIC_FIELD(simpleClassName, name, jboolean)
+#define STATIC_OBJECT_FIELD(simpleClassName, name, signature) STATIC_OOPISH_FIELD(simpleClassName, name, JVMCIObject, oop)
+#define STATIC_OBJECTARRAY_FIELD(simpleClassName, name, signature) STATIC_OOPISH_FIELD(simpleClassName, name, JVMCIObjectArray, objArrayOop)
+
+#define HS_START_CLASS(simpleClassName, fullClassName)                               \
+  START_CLASS(simpleClassName, fullClassName)                                        \
+  friend class HotSpotJVMCI;                                                         \
+ private:                                                                            \
+  static void check(oop obj, const char* field_name, int offset);                    \
+  static InstanceKlass* _klass;                                                      \
+ public:                                                                             \
+  static InstanceKlass* klass() { assert(_klass != NULL, "uninit"); return _klass; } \
+  static Symbol* symbol() { return vmSymbols::fullClassName(); }
+
+#define FIELD(simpleClassName, name, type)                                                                   \
+  private:                                                                                                   \
+    static int _##name##_offset;                                                                             \
+  public:                                                                                                    \
+    static type get_ ## name(JVMCIEnv* env, JVMCIObject obj) { return name(env, resolve(obj)); }             \
+    static void set_ ## name(JVMCIEnv* env, JVMCIObject obj, type x) { set_ ## name(env, resolve(obj), x); } \
+    static type name(JVMCIEnv* env, oop obj);                                                                \
+    static void set_ ## name(JVMCIEnv* env, oop obj, type x);
+
+#define OOPISH_FIELD(simpleClassName, name, type, hstype)                                                                \
+  private:                                                                                                                       \
+    static int _##name##_offset;                                                                                                 \
+  public:                                                                                                                        \
+    static type get_  ## name(JVMCIEnv* env, JVMCIObject obj) { return (type) wrap(name(env, resolve(obj))); }                   \
+    static void set_  ## name(JVMCIEnv* env, JVMCIObject obj, type x) { set_  ## name(env, resolve(obj), (hstype) resolve(x)); } \
+    static hstype name(JVMCIEnv* env, oop obj);                                                                                  \
+    static void set_  ## name(JVMCIEnv* env, oop obj, hstype x);
+
+#define STATIC_FIELD(simpleClassName, name, type)     \
+  private:                                            \
+    static int _##name##_offset;                      \
+  public:                                             \
+    static type get_  ## name(JVMCIEnv* env);         \
+    static void set_  ## name(JVMCIEnv* env, type x);
+
+#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype)                                  \
+  private:                                                                                        \
+    static int _##name##_offset;                                                                  \
+  public:                                                                                         \
+    static type get_  ## name(JVMCIEnv* env) { return (type) wrap(name(env)); }                   \
+    static void set_  ## name(JVMCIEnv* env, type x) { set_  ## name(env, (hstype) resolve(x)); } \
+    static hstype name(JVMCIEnv* env);                                                            \
+    static void set_  ## name(JVMCIEnv* env, hstype hstype);
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, simpleClassName, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+/**
+ * VM internal interface to Java classes, methods and objects. For example:
+ *
+ * class HotSpotJVMCI {
+ *   ...
+ *   class Architecture {
+ *     static void initialize(JVMCIEnv* env);
+ *     static bool is_instance(JVMCIEnv* env, JVMCIObject object);
+ *    private:
+ *     static void check(oop obj, const char *field_name, int offset);
+ *    public:
+ *     static InstanceKlass *klass() { ... }
+ *     static Symbol *symbol() { return vmSymbols::jdk_vm_ci_code_Architecture(); }
+ *    private:
+ *     static int _wordKind_offset;
+ *    public:
+ *     static JVMCIObject get_wordKind(JVMCIEnv *env, JVMCIObject obj) { ... }
+ *     static void set_wordKind(JVMCIEnv *env, JVMCIObject obj, JVMCIObject x) { ... }
+ *     static oop wordKind(JVMCIEnv *env, oop obj);
+ *     static void set_wordKind(JVMCIEnv *env, oop obj, oop x);
+ *   }
+ *   ...
+ * };
+ */
+class HotSpotJVMCI {
+  friend class JVMCIEnv;
+
+ public:
+
+  static oop resolve(JVMCIObject obj);
+
+  static arrayOop resolve(JVMCIArray obj);
+  static objArrayOop resolve(JVMCIObjectArray obj);
+  static typeArrayOop resolve(JVMCIPrimitiveArray obj);
+
+  static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, true); }
+  static JVMCIObject wrap(oop obj);
+
+  static inline Method* asMethod(JVMCIEnv* env, oop jvmci_method) {
+    return *(Method**) HotSpotResolvedJavaMethodImpl::metadataHandle(env, jvmci_method);
+  }
+  static inline ConstantPool* asConstantPool(JVMCIEnv* env, oop jvmci_constant_pool) {
+    return *(ConstantPool**) HotSpotConstantPool::metadataHandle(env, jvmci_constant_pool);
+  }
+  static inline Klass* asKlass(JVMCIEnv* env, oop jvmci_type) {
+    return (Klass*) HotSpotResolvedObjectTypeImpl::metadataPointer(env, jvmci_type);
+  }
+
+  static void compute_offsets(TRAPS);
+  static void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS);
 
-#define EMPTY_CAST
-#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field, EMPTY_CAST)
-#define INT_FIELD(klass, name) FIELD(name, jint, int_field, EMPTY_CAST)
-#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field, EMPTY_CAST)
-#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field, EMPTY_CAST)
-#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field, EMPTY_CAST)
-#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field, EMPTY_CAST)
-#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(name, objArrayOop, obj_field, (objArrayOop))
-#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(name, typeArrayOop, obj_field, (typeArrayOop))
-#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
-#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
-#define STATIC_OOPISH_FIELD(klassName, name, type, signature)                                                  \
-    static int _##name##_offset;                                                                               \
-    static type name();                                                                                        \
-    static void set_##name(type x);
-#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename)                                                     \
-    static int _##name##_offset;                                                                               \
-    static jtypename name();                                                                                   \
-    static void set_##name(jtypename x);
+  JVMCI_CLASSES_DO(HS_START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+};
+
+#undef HS_START_CLASS
+
+#define JNI_START_CLASS(simpleClassName, fullClassName)                                             \
+  START_CLASS(simpleClassName, fullClassName)                                                       \
+  friend class JNIJVMCI;                                                                            \
+  private:                                                                                          \
+  static void check(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset);  \
+  static jclass _class;                                                                             \
+public:                                                                                             \
+ static jclass clazz() { assert(_class != NULL, #fullClassName " uninitialized"); return _class; }                         \
+ static jclass fullClassName ##_class()  { assert(_class != NULL, "uninit"); return _class; }
+
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OOPISH_FIELD
+
+#define FIELD(simpleClassName, name, type)                                \
+  private:                                                                \
+    static jfieldID _##name##_field_id;                                   \
+  public:                                                                 \
+    static type get_  ## name(JVMCIEnv* jvmciEnv, JVMCIObject obj);       \
+    static void set_  ## name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x);
+
+#define OOPISH_FIELD(simpleClassName, name, type, hstype) \
+  FIELD(simpleClassName, name, type)
+
+#define STATIC_FIELD(simpleClassName, name, type)   \
+  private:                                          \
+    static jfieldID _##name##_field_id;             \
+  public:                                           \
+    static type get_  ## name(JVMCIEnv* jvmciEnv);  \
+    static void set_  ## name(JVMCIEnv* jvmciEnv, type x);
+
+#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype) \
+  STATIC_FIELD(simpleClassName, name, type)
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+  public:                                                                                                           \
+    static jmethodID methodName##_method() { return _##methodName##_method; }                                       \
+  private:                                                                                                          \
+    static jmethodID _##methodName##_method;
+
+#define CONSTRUCTOR(className, signature)                                                                           \
+  public:                                                                                                           \
+    static jmethodID constructor() { return _constructor; }                                                         \
+  private:                                                                                                          \
+    static jmethodID _constructor;
 
-#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
-#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+/**
+ * JNI based interface to Java classes, methods and objects. For example:
+ *
+ * class JNIJVMCI {
+ *   ...
+ *   class Architecture {
+ *     static void initialize(JVMCIEnv* env);
+ *     static bool is_instance(JVMCIEnv* env, JVMCIObject object);
+ *    private:
+ *     static void check(oop obj, const char *field_name, int offset);
+ *     static jclass _class;
+ *    public:
+ *     static jclass clazz() { return _class; }
+ *     static jclass jdk_vm_ci_code_Architecture_class() { return _class; }
+ *    private:
+ *     static jfieldID _wordKind_field_id;
+ *    public:
+ *     static JVMCIObject get_wordKind(JVMCIEnv *env, JVMCIObject obj) { ... }
+ *     static void set_wordKind(JVMCIEnv *env, JVMCIObject obj, JVMCIObject x) { ... }
+ *   }
+ *   ...
+ * };
+ */
+class JNIJVMCI {
+  friend class JVMCIEnv;
 
-COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+  static jclass _byte_array;
+  static jclass _box_classes[T_CONFLICT+1];
+  static jfieldID _box_fields[T_CONFLICT+1];
+  static jmethodID _box_constructors[T_CONFLICT+1];
+  static jmethodID _Class_getName_method;
+
+  static jmethodID _HotSpotResolvedJavaMethodImpl_fromMetaspace_method;
+  static jmethodID _HotSpotConstantPool_fromMetaspace_method;
+  static jmethodID _HotSpotResolvedObjectTypeImpl_fromMetaspace_method;
+  static jmethodID _HotSpotResolvedPrimitiveType_fromMetaspace_method;
+
+ public:
+  static jmethodID Class_getName_method() { return _Class_getName_method; }
+
+  static jclass    byte_array()           { assert(_byte_array != NULL, "uninit");      return _byte_array; }
+
+  static jclass    box_class(BasicType type)       { assert(_box_classes[type]!= NULL, "uninit");      return _box_classes[type]; }
+  static jfieldID  box_field(BasicType type)       { assert(_box_fields[type]!= NULL, "uninit");       return _box_fields[type]; }
+  static jmethodID box_constructor(BasicType type) { assert(_box_constructors[type]!= NULL, "uninit"); return _box_constructors[type]; }
+
+  static jmethodID HotSpotResolvedJavaMethodImpl_fromMetaspace_method()     { assert(_HotSpotResolvedJavaMethodImpl_fromMetaspace_method     != NULL, "uninit"); return _HotSpotResolvedJavaMethodImpl_fromMetaspace_method; }
+  static jmethodID HotSpotConstantPool_fromMetaspace_method()           { assert(_HotSpotConstantPool_fromMetaspace_method           != NULL, "uninit"); return _HotSpotConstantPool_fromMetaspace_method; }
+  static jmethodID HotSpotResolvedObjectTypeImpl_fromMetaspace_method() { assert(_HotSpotResolvedObjectTypeImpl_fromMetaspace_method != NULL, "uninit"); return _HotSpotResolvedObjectTypeImpl_fromMetaspace_method; }
+  static jmethodID HotSpotResolvedPrimitiveType_fromMetaspace_method()  { assert(_HotSpotResolvedPrimitiveType_fromMetaspace_method  != NULL, "uninit"); return _HotSpotResolvedPrimitiveType_fromMetaspace_method; }
+
+  static void initialize_ids(JNIEnv* env);
+  static void initialize_field_id(JNIEnv* env, jfieldID &dest_offset, jclass klass, const char* klass_name, const char* name, const char* signature, bool static_field);
+
+  static jobject resolve_handle(JVMCIObject obj) { return obj.as_jobject(); }
+  static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, false); }
+
+  JVMCI_CLASSES_DO(JNI_START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+};
+
+#undef JNI_START_CLASS
 #undef START_CLASS
 #undef END_CLASS
+#undef METHOD
+#undef CONSTRUCTOR
 #undef FIELD
 #undef CHAR_FIELD
 #undef INT_FIELD
 #undef BOOLEAN_FIELD
 #undef LONG_FIELD
 #undef FLOAT_FIELD
-#undef OOP_FIELD
-#undef TYPEARRAYOOP_FIELD
-#undef OBJARRAYOOP_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
 #undef STATIC_OOPISH_FIELD
-#undef STATIC_OOP_FIELD
-#undef STATIC_OBJARRAYOOP_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
 #undef STATIC_INT_FIELD
 #undef STATIC_BOOLEAN_FIELD
 #undef STATIC_PRIMITIVE_FIELD
 #undef EMPTY_CAST
 
-void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS);
-
 #endif // SHARE_JVMCI_JVMCIJAVACLASSES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmciObject.hpp	Fri May 03 14:59:32 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.
+ */
+
+#ifndef SHARE_JVMCI_JVMCIOBJECT_HPP
+#define SHARE_JVMCI_JVMCIOBJECT_HPP
+
+#include "jni.h"
+#include "utilities/debug.hpp"
+
+class JVMCIArray;
+class JVMCIPrimitiveArray;
+class JVMCIObjectArray;
+
+class JVMCIObject {
+
+ private:
+  jobject _object;
+  bool _is_hotspot;
+
+ public:
+  JVMCIObject(): _object(NULL), _is_hotspot(false) {}
+  JVMCIObject(jobject o, bool is_hotspot): _object(o), _is_hotspot(is_hotspot) { }
+
+  static JVMCIObject create(jobject o, bool is_hotspot) { JVMCIObject r(o, is_hotspot); return r; }
+  jobject as_jobject() { return _object; }
+  jobject as_jweak()   { return (jweak) _object; }
+  jstring as_jstring() { return (jstring) _object; }
+  bool is_hotspot() { return _is_hotspot; }
+
+  bool is_null() const { return _object == NULL; }
+  bool is_non_null() const { return _object != NULL; }
+
+  operator JVMCIArray();
+  operator JVMCIPrimitiveArray();
+  operator JVMCIObjectArray();
+};
+
+class JVMCIArray : public JVMCIObject {
+ public:
+  JVMCIArray() {}
+  JVMCIArray(jobject o, bool is_hotspot): JVMCIObject(o, is_hotspot) {}
+  jarray as_jobject() { return (jarray) JVMCIObject::as_jobject(); }
+};
+
+class JVMCIObjectArray : public JVMCIArray {
+ public:
+  JVMCIObjectArray() {}
+  JVMCIObjectArray(void* v): JVMCIArray() { assert(v == NULL, "must be NULL"); }
+  JVMCIObjectArray(jobject o, bool is_hotspot): JVMCIArray(o, is_hotspot) {}
+
+  jobjectArray as_jobject() { return (jobjectArray) JVMCIArray::as_jobject(); }
+};
+
+class JVMCIPrimitiveArray : public JVMCIArray {
+ public:
+  JVMCIPrimitiveArray() {}
+  JVMCIPrimitiveArray(void* v): JVMCIArray() { assert(v == NULL, "must be NULL"); }
+  JVMCIPrimitiveArray(jobject o, bool is_hotspot): JVMCIArray(o, is_hotspot) {}
+
+  jbooleanArray as_jbooleanArray() { return (jbooleanArray) as_jobject(); }
+  jbyteArray    as_jbyteArray()    { return (jbyteArray) as_jobject();    }
+  jcharArray    as_jcharArray()    { return (jcharArray) as_jobject();    }
+  jshortArray   as_jshortArray()   { return (jshortArray) as_jobject();   }
+  jintArray     as_jintArray()     { return (jintArray) as_jobject();     }
+  jfloatArray   as_jfloatArray()   { return (jfloatArray) as_jobject();   }
+  jlongArray    as_jlongArray()    { return (jlongArray) as_jobject();    }
+  jdoubleArray  as_jdoubleArray()  { return (jdoubleArray) as_jobject();  }
+};
+
+inline JVMCIObject::operator JVMCIArray() { return JVMCIArray(_object, _is_hotspot); }
+inline JVMCIObject::operator JVMCIPrimitiveArray() { return JVMCIPrimitiveArray(_object, _is_hotspot); }
+inline JVMCIObject::operator JVMCIObjectArray() { return JVMCIObjectArray(_object, _is_hotspot); }
+
+#endif // SHARE_JVMCI_JVMCIOBJECT_HPP
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri May 03 14:59:32 2019 -0400
@@ -22,70 +22,24 @@
  */
 
 #include "precompiled.hpp"
-#include "jvm.h"
-#include "asm/codeBuffer.hpp"
-#include "classfile/javaClasses.inline.hpp"
-#include "code/codeCache.hpp"
-#include "code/compiledMethod.inline.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/disassembler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #include "logging/log.hpp"
-#include "memory/allocation.inline.hpp"
 #include "memory/oopFactory.hpp"
-#include "memory/resourceArea.hpp"
+#include "oops/constantPool.inline.hpp"
+#include "oops/method.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/frame.inline.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/jniHandles.inline.hpp"
-#include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/threadSMR.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/defaultStream.hpp"
-#include "utilities/macros.hpp"
 #if INCLUDE_G1GC
 #include "gc/g1/g1ThreadLocalData.hpp"
 #endif // INCLUDE_G1GC
 
-#if defined(_MSC_VER)
-#define strtoll _strtoi64
-#endif
-
-jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
-bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
-bool JVMCIRuntime::_well_known_classes_initialized = false;
-JVMCIRuntime::CompLevelAdjustment JVMCIRuntime::_comp_level_adjustment = JVMCIRuntime::none;
-bool JVMCIRuntime::_shutdown_called = false;
-
-BasicType JVMCIRuntime::kindToBasicType(Handle kind, TRAPS) {
-  if (kind.is_null()) {
-    THROW_(vmSymbols::java_lang_NullPointerException(), T_ILLEGAL);
-  }
-  jchar ch = JavaKind::typeChar(kind);
-  switch(ch) {
-    case 'Z': return T_BOOLEAN;
-    case 'B': return T_BYTE;
-    case 'S': return T_SHORT;
-    case 'C': return T_CHAR;
-    case 'I': return T_INT;
-    case 'F': return T_FLOAT;
-    case 'J': return T_LONG;
-    case 'D': return T_DOUBLE;
-    case 'A': return T_OBJECT;
-    case '-': return T_ILLEGAL;
-    default:
-      JVMCI_ERROR_(T_ILLEGAL, "unexpected Kind: %c", ch);
-  }
-}
-
 // Simple helper to see if the caller of a runtime stub which
 // entered the VM has been deoptimized
 
@@ -152,23 +106,23 @@
   JRT_BLOCK;
   assert(klass->is_klass(), "not a class");
   Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
-  InstanceKlass* ik = InstanceKlass::cast(klass);
+  InstanceKlass* h = InstanceKlass::cast(klass);
   {
     RetryableAllocationMark ram(thread, null_on_fail);
-    ik->check_valid_for_instantiation(true, CHECK);
+    h->check_valid_for_instantiation(true, CHECK);
     oop obj;
     if (null_on_fail) {
-      if (!ik->is_initialized()) {
+      if (!h->is_initialized()) {
         // Cannot re-execute class initialization without side effects
         // so return without attempting the initialization
         return;
       }
     } else {
       // make sure klass is initialized
-      ik->initialize(CHECK);
+      h->initialize(CHECK);
     }
     // allocate instance and return via TLS
-    obj = ik->allocate_instance(CHECK);
+    obj = h->allocate_instance(CHECK);
     thread->set_vm_result(obj);
   }
   JRT_BLOCK_END;
@@ -290,6 +244,7 @@
   }
 #ifdef ASSERT
   assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
+  assert(oopDesc::is_oop(exception()), "just checking");
   // Check that exception is a subclass of Throwable, otherwise we have a VerifyError
   if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
     if (ExitVMOnVerifyError) vm_exit(-1);
@@ -370,10 +325,11 @@
     thread->set_exception_oop(exception());
     thread->set_exception_pc(pc);
 
-    // the exception cache is used only by non-implicit exceptions
-    // Update the exception cache only when there didn't happen
-    // another exception during the computation of the compiled
-    // exception handler. Checking for exception oop equality is not
+    // The exception cache is used only for non-implicit exceptions
+    // Update the exception cache only when another exception did
+    // occur during the computation of the compiled exception handler
+    // (e.g., when loading the class of the catch type).
+    // Checking for exception oop equality is not
     // sufficient because some exceptions are pre-allocated and reused.
     if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {
       cm->add_handler_for_exception_and_pc(exception, pc, continuation);
@@ -430,12 +386,11 @@
     TRACE_jvmci_3("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(mark), p2i(lock));
     tty->flush();
   }
-#ifdef ASSERT
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
-#endif
   Handle h_obj(thread, obj);
+  assert(oopDesc::is_oop(h_obj()), "must be NULL or an object");
   if (UseBiasedLocking) {
     // Retry fast entry if bias is revoked to avoid unnecessary inflation
     ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
@@ -456,7 +411,7 @@
   // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
   EXCEPTION_MARK;
 
-#ifdef DEBUG
+#ifdef ASSERT
   if (!oopDesc::is_oop(obj)) {
     ResetNoHandleMark rhm;
     nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
@@ -587,10 +542,8 @@
     size_t detail_msg_length = strlen(buf) * 2;
     detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
     jio_snprintf(detail_msg, detail_msg_length, buf, value);
-    report_vm_error(__FILE__, __LINE__, error_msg, "%s", detail_msg);
-  } else {
-    report_vm_error(__FILE__, __LINE__, error_msg);
   }
+  report_vm_error(__FILE__, __LINE__, error_msg, "%s", detail_msg);
 JRT_END
 
 JRT_LEAF(oopDesc*, JVMCIRuntime::load_and_clear_exception(JavaThread* thread))
@@ -694,278 +647,934 @@
   }
 JRT_END
 
-JRT_ENTRY(int, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
+JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
   deopt_caller();
-  return value;
+  return (jint) value;
 JRT_END
 
-void JVMCIRuntime::force_initialization(TRAPS) {
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
-
-  ResourceMark rm;
-  TempNewSymbol getCompiler = SymbolTable::new_symbol("getCompiler", CHECK);
-  TempNewSymbol sig = SymbolTable::new_symbol("()Ljdk/vm/ci/runtime/JVMCICompiler;", CHECK);
-  Handle jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
-  JavaValue result(T_OBJECT);
-  JavaCalls::call_virtual(&result, jvmciRuntime, HotSpotJVMCIRuntime::klass(), getCompiler, sig, CHECK);
-}
 
 // private static JVMCIRuntime JVMCI.initializeRuntime()
-JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+  JNI_JVMCIENV(env);
   if (!EnableJVMCI) {
-    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+    JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
   }
-  JVMCIRuntime::initialize_HotSpotJVMCIRuntime(CHECK_NULL);
-  jobject ret = JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(CHECK_NULL);
-  return ret;
+  JVMCIENV->runtime()->initialize_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);
+  JVMCIObject runtime = JVMCIENV->runtime()->get_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(runtime);
 JVM_END
 
-Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, const char* signature, JavaCallArguments* args, TRAPS) {
-  TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_(Handle()));
-  Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_(Handle()));
-  TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_(Handle()));
-  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_(Handle()));
-  JavaValue result(T_OBJECT);
-  if (args == NULL) {
-    JavaCalls::call_static(&result, klass, runtime, sig, CHECK_(Handle()));
+void JVMCIRuntime::call_getCompiler(TRAPS) {
+  THREAD_JVMCIENV(JavaThread::current());
+  JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);
+  initialize(JVMCIENV);
+  JVMCIENV->call_HotSpotJVMCIRuntime_getCompiler(jvmciRuntime, JVMCI_CHECK);
+}
+
+void JVMCINMethodData::initialize(
+  int nmethod_mirror_index,
+  const char* name,
+  FailedSpeculation** failed_speculations)
+{
+  _failed_speculations = failed_speculations;
+  _nmethod_mirror_index = nmethod_mirror_index;
+  if (name != NULL) {
+    _has_name = true;
+    char* dest = (char*) this->name();
+    strcpy(dest, name);
   } else {
-    JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_(Handle()));
+    _has_name = false;
+  }
+}
+
+void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) {
+  uint index = (speculation >> 32) & 0xFFFFFFFF;
+  int length = (int) speculation;
+  if (index + length > (uint) nm->speculations_size()) {
+    fatal(INTPTR_FORMAT "[index: %d, length: %d] out of bounds wrt encoded speculations of length %u", speculation, index, length, nm->speculations_size());
+  }
+  address data = nm->speculations_begin() + index;
+  FailedSpeculation::add_failed_speculation(nm, _failed_speculations, data, length);
+}
+
+oop JVMCINMethodData::get_nmethod_mirror(nmethod* nm) {
+  if (_nmethod_mirror_index == -1) {
+    return NULL;
+  }
+  return nm->oop_at(_nmethod_mirror_index);
+}
+
+void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
+  assert(_nmethod_mirror_index != -1, "cannot set JVMCI mirror for nmethod");
+  oop* addr = nm->oop_addr_at(_nmethod_mirror_index);
+  assert(new_mirror != NULL, "use clear_nmethod_mirror to clear the mirror");
+  assert(*addr == NULL, "cannot overwrite non-null mirror");
+
+  *addr = new_mirror;
+
+  // Since we've patched some oops in the nmethod,
+  // (re)register it with the heap.
+  Universe::heap()->register_nmethod(nm);
+}
+
+void JVMCINMethodData::clear_nmethod_mirror(nmethod* nm) {
+  if (_nmethod_mirror_index != -1) {
+    oop* addr = nm->oop_addr_at(_nmethod_mirror_index);
+    *addr = NULL;
   }
-  return Handle(THREAD, (oop)result.get_jobject());
+}
+
+void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
+  oop nmethod_mirror = get_nmethod_mirror(nm);
+  if (nmethod_mirror == NULL) {
+    return;
+  }
+
+  // Update the values in the mirror if it still refers to nm.
+  // We cannot use JVMCIObject to wrap the mirror as this is called
+  // during GC, forbidding the creation of JNIHandles.
+  JVMCIEnv* jvmciEnv = NULL;
+  nmethod* current = (nmethod*) HotSpotJVMCI::InstalledCode::address(jvmciEnv, nmethod_mirror);
+  if (nm == current) {
+    if (!nm->is_alive()) {
+      // Break the link from the mirror to nm such that
+      // future invocations via the mirror will result in
+      // an InvalidInstalledCodeException.
+      HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
+      HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
+    } else if (nm->is_not_entrant()) {
+      // Zero the entry point so any new invocation will fail but keep
+      // the address link around that so that existing activations can
+      // be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).
+      HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
+    }
+  }
+}
+
+void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    if (JVMCIENV->is_hotspot() && UseJVMCINativeLibrary) {
+      JVMCI_THROW_MSG(InternalError, "JVMCI has already been enabled in the JVMCI shared library");
+    }
+  }
+
+  initialize(JVMCIENV);
+
+  // This should only be called in the context of the JVMCI class being initialized
+  JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK);
+
+  _HotSpotJVMCIRuntime_instance = JVMCIENV->make_global(result);
 }
 
-Handle JVMCIRuntime::get_HotSpotJVMCIRuntime(TRAPS) {
-  initialize_JVMCI(CHECK_(Handle()));
-  return Handle(THREAD, JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance));
+void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {
+  assert(this != NULL, "sanity");
+  // Check first without JVMCI_lock
+  if (_initialized) {
+    return;
+  }
+
+  MutexLocker locker(JVMCI_lock);
+  // Check again under JVMCI_lock
+  if (_initialized) {
+    return;
+  }
+
+  while (_being_initialized) {
+    JVMCI_lock->wait();
+    if (_initialized) {
+      return;
+    }
+  }
+
+  _being_initialized = true;
+
+  {
+    MutexUnlocker unlock(JVMCI_lock);
+
+    HandleMark hm;
+    ResourceMark rm;
+    JavaThread* THREAD = JavaThread::current();
+    if (JVMCIENV->is_hotspot()) {
+      HotSpotJVMCI::compute_offsets(CHECK_EXIT);
+    } else {
+      JNIAccessMark jni(JVMCIENV);
+
+      JNIJVMCI::initialize_ids(jni.env());
+      if (jni()->ExceptionCheck()) {
+        jni()->ExceptionDescribe();
+        fatal("JNI exception during init");
+      }
+    }
+    create_jvmci_primitive_type(T_BOOLEAN, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_BYTE, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_CHAR, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_SHORT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_INT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_LONG, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_FLOAT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_DOUBLE, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_VOID, JVMCI_CHECK_EXIT_((void)0));
+
+    if (!JVMCIENV->is_hotspot()) {
+      JVMCIENV->copy_saved_properties();
+    }
+  }
+
+  _initialized = true;
+  _being_initialized = false;
+  JVMCI_lock->notify_all();
+}
+
+JVMCIObject JVMCIRuntime::create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS) {
+  Thread* THREAD = Thread::current();
+  // These primitive types are long lived and are created before the runtime is fully set up
+  // so skip registering them for scanning.
+  JVMCIObject mirror = JVMCIENV->get_object_constant(java_lang_Class::primitive_mirror(type), false, true);
+  if (JVMCIENV->is_hotspot()) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(mirror)));
+    args.push_int(type2char(type));
+    JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedPrimitiveType::klass(), vmSymbols::fromMetaspace_name(), vmSymbols::primitive_fromMetaspace_signature(), &args, CHECK_(JVMCIObject()));
+
+    return JVMCIENV->wrap(JNIHandles::make_local((oop)result.get_jobject()));
+  } else {
+    JNIAccessMark jni(JVMCIENV);
+    jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedPrimitiveType::clazz(),
+                                           JNIJVMCI::HotSpotResolvedPrimitiveType_fromMetaspace_method(),
+                                           mirror.as_jobject(), type2char(type));
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return JVMCIENV->wrap(result);
+  }
+}
+
+void JVMCIRuntime::initialize_JVMCI(JVMCI_TRAPS) {
+  if (!is_HotSpotJVMCIRuntime_initialized()) {
+    initialize(JVMCI_CHECK);
+    JVMCIENV->call_JVMCI_getRuntime(JVMCI_CHECK);
+  }
+}
+
+JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
+  initialize(JVMCIENV);
+  initialize_JVMCI(JVMCI_CHECK_(JVMCIObject()));
+  return _HotSpotJVMCIRuntime_instance;
 }
 
-void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
-  guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime");
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
-  // This should only be called in the context of the JVMCI class being initialized
-  InstanceKlass* klass = SystemDictionary::JVMCI_klass();
-  guarantee(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD),
-         "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
+
+// private void CompilerToVM.registerNatives()
+JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
+
+#ifdef _LP64
+#ifndef TARGET_ARCH_sparc
+  uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
+  uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
+  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+#endif // TARGET_ARCH_sparc
+#else
+  fatal("check TLAB allocation code for address space conflicts");
+#endif
+
+  JNI_JVMCIENV(env);
+
+  if (!EnableJVMCI) {
+    JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
+  }
+
+  JVMCIENV->runtime()->initialize(JVMCIENV);
+
+  {
+    ResourceMark rm;
+    HandleMark hm(thread);
+    ThreadToNativeFromVM trans(thread);
+
+    // Ensure _non_oop_bits is initialized
+    Universe::non_oop_word();
 
-  Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
-                             "runtime",
-                             "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
-  int adjustment = HotSpotJVMCIRuntime::compilationLevelAdjustment(result);
-  assert(adjustment >= JVMCIRuntime::none &&
-         adjustment <= JVMCIRuntime::by_full_signature,
-         "compilation level adjustment out of bounds");
-  _comp_level_adjustment = (CompLevelAdjustment) adjustment;
-  _HotSpotJVMCIRuntime_initialized = true;
-  _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result);
+    if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count())) {
+      if (!env->ExceptionCheck()) {
+        for (int i = 0; i < CompilerToVM::methods_count(); i++) {
+          if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods + i, 1)) {
+            guarantee(false, "Error registering JNI method %s%s", CompilerToVM::methods[i].name, CompilerToVM::methods[i].signature);
+            break;
+          }
+        }
+      } else {
+        env->ExceptionDescribe();
+      }
+      guarantee(false, "Failed registering CompilerToVM native methods");
+    }
+  }
+JVM_END
+
+
+void JVMCIRuntime::shutdown() {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    _shutdown_called = true;
+
+    THREAD_JVMCIENV(JavaThread::current());
+    JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);
+  }
+}
+
+void JVMCIRuntime::bootstrap_finished(TRAPS) {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    THREAD_JVMCIENV(JavaThread::current());
+    JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV);
+  }
 }
 
-void JVMCIRuntime::initialize_JVMCI(TRAPS) {
-  if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
-    callStatic("jdk/vm/ci/runtime/JVMCI",
-               "getRuntime",
-               "()Ljdk/vm/ci/runtime/JVMCIRuntime;", NULL, CHECK);
+void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool clear) {
+  if (HAS_PENDING_EXCEPTION) {
+    Handle exception(THREAD, PENDING_EXCEPTION);
+    const char* exception_file = THREAD->exception_file();
+    int exception_line = THREAD->exception_line();
+    CLEAR_PENDING_EXCEPTION;
+    if (exception->is_a(SystemDictionary::ThreadDeath_klass())) {
+      // Don't print anything if we are being killed.
+    } else {
+      java_lang_Throwable::print(exception(), tty);
+      tty->cr();
+      java_lang_Throwable::print_stack_trace(exception, tty);
+
+      // Clear and ignore any exceptions raised during printing
+      CLEAR_PENDING_EXCEPTION;
+    }
+    if (!clear) {
+      THREAD->set_pending_exception(exception(), exception_file, exception_line);
+    }
   }
-  assert(_HotSpotJVMCIRuntime_initialized == true, "what?");
 }
 
-bool JVMCIRuntime::can_initialize_JVMCI() {
-  // Initializing JVMCI requires the module system to be initialized past phase 3.
-  // The JVMCI API itself isn't available until phase 2 and ServiceLoader (which
-  // JVMCI initialization requires) isn't usable until after phase 3. Testing
-  // whether the system loader is initialized satisfies all these invariants.
-  if (SystemDictionary::java_system_loader() == NULL) {
-    return false;
+
+void JVMCIRuntime::exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message) {
+  JavaThread* THREAD = JavaThread::current();
+
+  static volatile int report_error = 0;
+  if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) {
+    // Only report an error once
+    tty->print_raw_cr(message);
+    if (JVMCIENV != NULL) {
+      JVMCIENV->describe_pending_exception(true);
+    } else {
+      describe_pending_hotspot_exception(THREAD, true);
+    }
+  } else {
+    // Allow error reporting thread to print the stack trace.  Windows
+    // doesn't allow uninterruptible wait for JavaThreads
+    const bool interruptible = true;
+    os::sleep(THREAD, 200, interruptible);
   }
-  assert(Universe::is_module_initialized(), "must be");
+
+  before_exit(THREAD);
+  vm_exit(-1);
+}
+
+// ------------------------------------------------------------------
+// Note: the logic of this method should mirror the logic of
+// constantPoolOopDesc::verify_constant_pool_resolve.
+bool JVMCIRuntime::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) {
+  if (accessing_klass->is_objArray_klass()) {
+    accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass();
+  }
+  if (!accessing_klass->is_instance_klass()) {
+    return true;
+  }
+
+  if (resolved_klass->is_objArray_klass()) {
+    // Find the element klass, if this is an array.
+    resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
+  }
+  if (resolved_klass->is_instance_klass()) {
+    Reflection::VerifyClassAccessResults result =
+      Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true);
+    return result == Reflection::ACCESS_OK;
+  }
   return true;
 }
 
-void JVMCIRuntime::initialize_well_known_classes(TRAPS) {
-  if (JVMCIRuntime::_well_known_classes_initialized == false) {
-    guarantee(can_initialize_JVMCI(), "VM is not yet sufficiently booted to initialize JVMCI");
-    SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
-    SystemDictionary::resolve_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK);
-    JVMCIJavaClasses::compute_offsets(CHECK);
-    JVMCIRuntime::_well_known_classes_initialized = true;
-  }
-}
+// ------------------------------------------------------------------
+Klass* JVMCIRuntime::get_klass_by_name_impl(Klass*& accessing_klass,
+                                          const constantPoolHandle& cpool,
+                                          Symbol* sym,
+                                          bool require_local) {
+  JVMCI_EXCEPTION_CONTEXT;
 
-void JVMCIRuntime::metadata_do(void f(Metadata*)) {
-  // For simplicity, the existence of HotSpotJVMCIMetaAccessContext in
-  // the SystemDictionary well known classes should ensure the other
-  // classes have already been loaded, so make sure their order in the
-  // table enforces that.
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotConstantPool) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-
-  if (HotSpotJVMCIMetaAccessContext::klass() == NULL ||
-      !HotSpotJVMCIMetaAccessContext::klass()->is_linked()) {
-    // Nothing could be registered yet
-    return;
+  // Now we need to check the SystemDictionary
+  if (sym->char_at(0) == 'L' &&
+    sym->char_at(sym->utf8_length()-1) == ';') {
+    // This is a name from a signature.  Strip off the trimmings.
+    // Call recursive to keep scope of strippedsym.
+    TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                    sym->utf8_length()-2,
+                    CHECK_NULL);
+    return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);
   }
 
-  // WeakReference<HotSpotJVMCIMetaAccessContext>[]
-  objArrayOop allContexts = HotSpotJVMCIMetaAccessContext::allContexts();
-  if (allContexts == NULL) {
-    return;
+  Handle loader(THREAD, (oop)NULL);
+  Handle domain(THREAD, (oop)NULL);
+  if (accessing_klass != NULL) {
+    loader = Handle(THREAD, accessing_klass->class_loader());
+    domain = Handle(THREAD, accessing_klass->protection_domain());
   }
 
-  // These must be loaded at this point but the linking state doesn't matter.
-  assert(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass() != NULL, "must be loaded");
-  assert(SystemDictionary::HotSpotConstantPool_klass() != NULL, "must be loaded");
-  assert(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass() != NULL, "must be loaded");
+  Klass* found_klass;
+  {
+    ttyUnlocker ttyul;  // release tty lock to avoid ordering problems
+    MutexLocker ml(Compile_lock);
+    if (!require_local) {
+      found_klass = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_NULL);
+    } else {
+      found_klass = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_NULL);
+    }
+  }
 
-  for (int i = 0; i < allContexts->length(); i++) {
-    oop ref = allContexts->obj_at(i);
-    if (ref != NULL) {
-      oop referent = java_lang_ref_Reference::referent(ref);
-      if (referent != NULL) {
-        // Chunked Object[] with last element pointing to next chunk
-        objArrayOop metadataRoots = HotSpotJVMCIMetaAccessContext::metadataRoots(referent);
-        while (metadataRoots != NULL) {
-          for (int typeIndex = 0; typeIndex < metadataRoots->length() - 1; typeIndex++) {
-            oop reference = metadataRoots->obj_at(typeIndex);
-            if (reference == NULL) {
-              continue;
-            }
-            oop metadataRoot = java_lang_ref_Reference::referent(reference);
-            if (metadataRoot == NULL) {
-              continue;
-            }
-            if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-              Method* method = CompilerToVM::asMethod(metadataRoot);
-              f(method);
-            } else if (metadataRoot->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
-              ConstantPool* constantPool = CompilerToVM::asConstantPool(metadataRoot);
-              f(constantPool);
-            } else if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-              Klass* klass = CompilerToVM::asKlass(metadataRoot);
-              f(klass);
-            } else {
-              metadataRoot->print();
-              ShouldNotReachHere();
-            }
-          }
-          metadataRoots = (objArrayOop)metadataRoots->obj_at(metadataRoots->length() - 1);
-          assert(metadataRoots == NULL || metadataRoots->is_objArray(), "wrong type");
+  // If we fail to find an array klass, look again for its element type.
+  // The element type may be available either locally or via constraints.
+  // In either case, if we can find the element type in the system dictionary,
+  // we must build an array type around it.  The CI requires array klasses
+  // to be loaded if their element klasses are loaded, except when memory
+  // is exhausted.
+  if (sym->char_at(0) == '[' &&
+      (sym->char_at(1) == '[' || sym->char_at(1) == 'L')) {
+    // We have an unloaded array.
+    // Build it on the fly if the element class exists.
+    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                                                 sym->utf8_length()-1,
+                                                 CHECK_NULL);
+
+    // Get element Klass recursively.
+    Klass* elem_klass =
+      get_klass_by_name_impl(accessing_klass,
+                             cpool,
+                             elem_sym,
+                             require_local);
+    if (elem_klass != NULL) {
+      // Now make an array for it
+      return elem_klass->array_klass(THREAD);
+    }
+  }
+
+  if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) {
+    // Look inside the constant pool for pre-resolved class entries.
+    for (int i = cpool->length() - 1; i >= 1; i--) {
+      if (cpool->tag_at(i).is_klass()) {
+        Klass*  kls = cpool->resolved_klass_at(i);
+        if (kls->name() == sym) {
+          return kls;
         }
       }
     }
   }
+
+  return found_klass;
+}
+
+// ------------------------------------------------------------------
+Klass* JVMCIRuntime::get_klass_by_name(Klass* accessing_klass,
+                                  Symbol* klass_name,
+                                  bool require_local) {
+  ResourceMark rm;
+  constantPoolHandle cpool;
+  return get_klass_by_name_impl(accessing_klass,
+                                                 cpool,
+                                                 klass_name,
+                                                 require_local);
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_klass_by_index.
+Klass* JVMCIRuntime::get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                        int index,
+                                        bool& is_accessible,
+                                        Klass* accessor) {
+  JVMCI_EXCEPTION_CONTEXT;
+  Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index);
+  Symbol* klass_name = NULL;
+  if (klass == NULL) {
+    klass_name = cpool->klass_name_at(index);
+  }
+
+  if (klass == NULL) {
+    // Not found in constant pool.  Use the name to do the lookup.
+    Klass* k = get_klass_by_name_impl(accessor,
+                                        cpool,
+                                        klass_name,
+                                        false);
+    // Calculate accessibility the hard way.
+    if (k == NULL) {
+      is_accessible = false;
+    } else if (k->class_loader() != accessor->class_loader() &&
+               get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) {
+      // Loaded only remotely.  Not linked yet.
+      is_accessible = false;
+    } else {
+      // Linked locally, and we must also check public/private, etc.
+      is_accessible = check_klass_accessibility(accessor, k);
+    }
+    if (!is_accessible) {
+      return NULL;
+    }
+    return k;
+  }
+
+  // It is known to be accessible, since it was found in the constant pool.
+  is_accessible = true;
+  return klass;
+}
+
+// ------------------------------------------------------------------
+// Get a klass from the constant pool.
+Klass* JVMCIRuntime::get_klass_by_index(const constantPoolHandle& cpool,
+                                   int index,
+                                   bool& is_accessible,
+                                   Klass* accessor) {
+  ResourceMark rm;
+  Klass* result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);
+  return result;
 }
 
-// private static void CompilerToVM.registerNatives()
-JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
-  if (!EnableJVMCI) {
-    THROW_MSG(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled");
+// ------------------------------------------------------------------
+// Implementation of get_field_by_index.
+//
+// Implementation note: the results of field lookups are cached
+// in the accessor klass.
+void JVMCIRuntime::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc,
+                                        int index) {
+  JVMCI_EXCEPTION_CONTEXT;
+
+  assert(klass->is_linked(), "must be linked before using its constant-pool");
+
+  constantPoolHandle cpool(thread, klass->constants());
+
+  // Get the field's name, signature, and type.
+  Symbol* name  = cpool->name_ref_at(index);
+
+  int nt_index = cpool->name_and_type_ref_index_at(index);
+  int sig_index = cpool->signature_ref_index_at(nt_index);
+  Symbol* signature = cpool->symbol_at(sig_index);
+
+  // Get the field's declared holder.
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  Klass* declared_holder = get_klass_by_index(cpool, holder_index,
+                                               holder_is_accessible,
+                                               klass);
+
+  // The declared holder of this field may not have been loaded.
+  // Bail out with partial field information.
+  if (!holder_is_accessible) {
+    return;
+  }
+
+
+  // Perform the field lookup.
+  Klass*  canonical_holder =
+    InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc);
+  if (canonical_holder == NULL) {
+    return;
+  }
+
+  assert(canonical_holder == field_desc.field_holder(), "just checking");
+}
+
+// ------------------------------------------------------------------
+// Get a field by index from a klass's constant pool.
+void JVMCIRuntime::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index) {
+  ResourceMark rm;
+  return get_field_by_index_impl(accessor, fd, index);
+}
+
+// ------------------------------------------------------------------
+// Perform an appropriate method lookup based on accessor, holder,
+// name, signature, and bytecode.
+methodHandle JVMCIRuntime::lookup_method(InstanceKlass* accessor,
+                               Klass*        holder,
+                               Symbol*       name,
+                               Symbol*       sig,
+                               Bytecodes::Code bc,
+                               constantTag   tag) {
+  // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl().
+  assert(check_klass_accessibility(accessor, holder), "holder not accessible");
+
+  methodHandle dest_method;
+  LinkInfo link_info(holder, name, sig, accessor, LinkInfo::needs_access_check, tag);
+  switch (bc) {
+  case Bytecodes::_invokestatic:
+    dest_method =
+      LinkResolver::resolve_static_call_or_null(link_info);
+    break;
+  case Bytecodes::_invokespecial:
+    dest_method =
+      LinkResolver::resolve_special_call_or_null(link_info);
+    break;
+  case Bytecodes::_invokeinterface:
+    dest_method =
+      LinkResolver::linktime_resolve_interface_method_or_null(link_info);
+    break;
+  case Bytecodes::_invokevirtual:
+    dest_method =
+      LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
+    break;
+  default: ShouldNotReachHere();
   }
 
-#ifdef _LP64
-#ifndef SPARC
-  uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
-  uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
-  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
-#endif // !SPARC
-#else
-  fatal("check TLAB allocation code for address space conflicts");
-#endif // _LP64
+  return dest_method;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIRuntime::get_method_by_index_impl(const constantPoolHandle& cpool,
+                                          int index, Bytecodes::Code bc,
+                                          InstanceKlass* accessor) {
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+    bool is_resolved = !cpce->is_f1_null();
+    if (is_resolved) {
+      // Get the invoker Method* from the constant pool.
+      // (The appendix argument, if any, will be noted in the method's signature.)
+      Method* adapter = cpce->f1_as_method();
+      return methodHandle(adapter);
+    }
+
+    return NULL;
+  }
+
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+
+  // Get the method's name and signature.
+  Symbol* name_sym = cpool->name_ref_at(index);
+  Symbol* sig_sym  = cpool->signature_ref_at(index);
 
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
+  if (cpool->has_preresolution()
+      || ((holder == SystemDictionary::MethodHandle_klass() || holder == SystemDictionary::VarHandle_klass()) &&
+          MethodHandles::is_signature_polymorphic_name(holder, name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (holder_is_accessible) { // Our declared holder is loaded.
+    constantTag tag = cpool->tag_ref_at(index);
+    methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);
+    if (!m.is_null()) {
+      // We found the method.
+      return m;
+    }
+  }
+
+  // Either the declared holder was not loaded, or the method could
+  // not be found.
+
+  return NULL;
+}
+
+// ------------------------------------------------------------------
+InstanceKlass* JVMCIRuntime::get_instance_klass_for_declared_method_holder(Klass* method_holder) {
+  // For the case of <array>.clone(), the method holder can be an ArrayKlass*
+  // instead of an InstanceKlass*.  For that case simply pretend that the
+  // declared holder is Object.clone since that's where the call will bottom out.
+  if (method_holder->is_instance_klass()) {
+    return InstanceKlass::cast(method_holder);
+  } else if (method_holder->is_array_klass()) {
+    return InstanceKlass::cast(SystemDictionary::Object_klass());
+  } else {
+    ShouldNotReachHere();
+  }
+  return NULL;
+}
+
 
-  {
-    ThreadToNativeFromVM trans(thread);
-    env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count());
+// ------------------------------------------------------------------
+methodHandle JVMCIRuntime::get_method_by_index(const constantPoolHandle& cpool,
+                                     int index, Bytecodes::Code bc,
+                                     InstanceKlass* accessor) {
+  ResourceMark rm;
+  return get_method_by_index_impl(cpool, index, bc, accessor);
+}
+
+// ------------------------------------------------------------------
+// Check for changes to the system dictionary during compilation
+// class loads, evolution, breakpoints
+JVMCI::CodeInstallResult JVMCIRuntime::validate_compile_task_dependencies(Dependencies* dependencies, JVMCICompileState* compile_state, char** failure_detail) {
+  // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
+  if (compile_state != NULL && compile_state->jvmti_state_changed()) {
+    *failure_detail = (char*) "Jvmti state change during compilation invalidated dependencies";
+    return JVMCI::dependencies_failed;
   }
-JVM_END
+
+  // Dependencies must be checked when the system dictionary changes
+  // or if we don't know whether it has changed (i.e., compile_state == NULL).
+  bool counter_changed = compile_state == NULL || compile_state->system_dictionary_modification_counter() != SystemDictionary::number_of_modifications();
+  CompileTask* task = compile_state == NULL ? NULL : compile_state->task();
+  Dependencies::DepType result = dependencies->validate_dependencies(task, counter_changed, failure_detail);
+  if (result == Dependencies::end_marker) {
+    return JVMCI::ok;
+  }
+
+  if (!Dependencies::is_klass_type(result) || counter_changed) {
+    return JVMCI::dependencies_failed;
+  }
+  // The dependencies were invalid at the time of installation
+  // without any intervening modification of the system
+  // dictionary.  That means they were invalidly constructed.
+  return JVMCI::dependencies_invalid;
+}
+
+
+void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& method, int entry_bci) {
+  JVMCI_EXCEPTION_CONTEXT
+
+  JVMCICompileState* compile_state = JVMCIENV->compile_state();
 
-void JVMCIRuntime::shutdown(TRAPS) {
-  if (_HotSpotJVMCIRuntime_instance != NULL) {
-    _shutdown_called = true;
-    HandleMark hm(THREAD);
-    Handle receiver = get_HotSpotJVMCIRuntime(CHECK);
-    JavaValue result(T_VOID);
-    JavaCallArguments args;
-    args.push_oop(receiver);
-    JavaCalls::call_special(&result, receiver->klass(), vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, CHECK);
+  bool is_osr = entry_bci != InvocationEntryBci;
+  if (compiler->is_bootstrapping() && is_osr) {
+    // no OSR compilations during bootstrap - the compiler is just too slow at this point,
+    // and we know that there are no endless loops
+    compile_state->set_failure(true, "No OSR during boostrap");
+    return;
+  }
+
+  HandleMark hm;
+  JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
+  if (JVMCIENV->has_pending_exception()) {
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "exception getting HotSpotJVMCIRuntime object");
+    return;
+  }
+  JVMCIObject jvmci_method = JVMCIENV->get_jvmci_method(method, JVMCIENV);
+  if (JVMCIENV->has_pending_exception()) {
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "exception getting JVMCI wrapper method");
+    return;
+  }
+
+  JVMCIObject result_object = JVMCIENV->call_HotSpotJVMCIRuntime_compileMethod(receiver, jvmci_method, entry_bci,
+                                                                     (jlong) compile_state, compile_state->task()->compile_id());
+  if (!JVMCIENV->has_pending_exception()) {
+    if (result_object.is_non_null()) {
+      JVMCIObject failure_message = JVMCIENV->get_HotSpotCompilationRequestResult_failureMessage(result_object);
+      if (failure_message.is_non_null()) {
+        // Copy failure reason into resource memory first ...
+        const char* failure_reason = JVMCIENV->as_utf8_string(failure_message);
+        // ... and then into the C heap.
+        failure_reason = os::strdup(failure_reason, mtJVMCI);
+        bool retryable = JVMCIENV->get_HotSpotCompilationRequestResult_retry(result_object) != 0;
+        compile_state->set_failure(retryable, failure_reason, true);
+      } else {
+        if (compile_state->task()->code() == NULL) {
+          compile_state->set_failure(true, "no nmethod produced");
+        } else {
+          compile_state->task()->set_num_inlined_bytecodes(JVMCIENV->get_HotSpotCompilationRequestResult_inlinedBytecodes(result_object));
+          compiler->inc_methods_compiled();
+        }
+      }
+    } else {
+      assert(false, "JVMCICompiler.compileMethod should always return non-null");
+    }
+  } else {
+    // An uncaught exception was thrown during compilation. Generally these
+    // should be handled by the Java code in some useful way but if they leak
+    // through to here report them instead of dying or silently ignoring them.
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "unexpected exception thrown");
+  }
+  if (compiler->is_bootstrapping()) {
+    compiler->set_bootstrap_compilation_request_handled();
   }
 }
 
-CompLevel JVMCIRuntime::adjust_comp_level_inner(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread) {
-  JVMCICompiler* compiler = JVMCICompiler::instance(false, thread);
-  if (compiler != NULL && compiler->is_bootstrapping()) {
-    return level;
-  }
-  if (!is_HotSpotJVMCIRuntime_initialized() || _comp_level_adjustment == JVMCIRuntime::none) {
-    // JVMCI cannot participate in compilation scheduling until
-    // JVMCI is initialized and indicates it wants to participate.
-    return level;
+
+// ------------------------------------------------------------------
+JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
+                                const methodHandle& method,
+                                nmethod*& nm,
+                                int entry_bci,
+                                CodeOffsets* offsets,
+                                int orig_pc_offset,
+                                CodeBuffer* code_buffer,
+                                int frame_words,
+                                OopMapSet* oop_map_set,
+                                ExceptionHandlerTable* handler_table,
+                                AbstractCompiler* compiler,
+                                DebugInformationRecorder* debug_info,
+                                Dependencies* dependencies,
+                                int compile_id,
+                                bool has_unsafe_access,
+                                bool has_wide_vector,
+                                JVMCIObject compiled_code,
+                                JVMCIObject nmethod_mirror,
+                                FailedSpeculation** failed_speculations,
+                                char* speculations,
+                                int speculations_len) {
+  JVMCI_EXCEPTION_CONTEXT;
+  nm = NULL;
+  int comp_level = CompLevel_full_optimization;
+  char* failure_detail = NULL;
+
+  bool install_default = JVMCIENV->get_HotSpotNmethod_isDefault(nmethod_mirror) != 0;
+  assert(JVMCIENV->isa_HotSpotNmethod(nmethod_mirror), "must be");
+  JVMCIObject name = JVMCIENV->get_InstalledCode_name(nmethod_mirror);
+  const char* nmethod_mirror_name = name.is_null() ? NULL : JVMCIENV->as_utf8_string(name);
+  int nmethod_mirror_index;
+  if (!install_default) {
+    // Reserve or initialize mirror slot in the oops table.
+    OopRecorder* oop_recorder = debug_info->oop_recorder();
+    nmethod_mirror_index = oop_recorder->allocate_oop_index(nmethod_mirror.is_hotspot() ? nmethod_mirror.as_jobject() : NULL);
+  } else {
+    // A default HotSpotNmethod mirror is never tracked by the nmethod
+    nmethod_mirror_index = -1;
   }
 
-#define CHECK_RETURN THREAD); \
-  if (HAS_PENDING_EXCEPTION) { \
-    Handle exception(THREAD, PENDING_EXCEPTION); \
-    CLEAR_PENDING_EXCEPTION; \
-  \
-    if (exception->is_a(SystemDictionary::ThreadDeath_klass())) { \
-      /* In the special case of ThreadDeath, we need to reset the */ \
-      /* pending async exception so that it is propagated.        */ \
-      thread->set_pending_async_exception(exception()); \
-      return level; \
-    } \
-    tty->print("Uncaught exception while adjusting compilation level: "); \
-    java_lang_Throwable::print(exception(), tty); \
-    tty->cr(); \
-    java_lang_Throwable::print_stack_trace(exception, tty); \
-    if (HAS_PENDING_EXCEPTION) { \
-      CLEAR_PENDING_EXCEPTION; \
-    } \
-    return level; \
-  } \
-  (void)(0
+  JVMCI::CodeInstallResult result;
+  {
+    // To prevent compile queue updates.
+    MutexLocker locker(MethodCompileQueue_lock, THREAD);
+
+    // Prevent SystemDictionary::add_to_hierarchy from running
+    // and invalidating our dependencies until we install this method.
+    MutexLocker ml(Compile_lock);
+
+    // Encode the dependencies now, so we can check them right away.
+    dependencies->encode_content_bytes();
+
+    // Record the dependencies for the current compile in the log
+    if (LogCompilation) {
+      for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
+        deps.log_dependency();
+      }
+    }
+
+    // Check for {class loads, evolution, breakpoints} during compilation
+    result = validate_compile_task_dependencies(dependencies, JVMCIENV->compile_state(), &failure_detail);
+    if (result != JVMCI::ok) {
+      // While not a true deoptimization, it is a preemptive decompile.
+      MethodData* mdp = method()->method_data();
+      if (mdp != NULL) {
+        mdp->inc_decompile_count();
+#ifdef ASSERT
+        if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
+          ResourceMark m;
+          tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
+        }
+#endif
+      }
+
+      // All buffers in the CodeBuffer are allocated in the CodeCache.
+      // If the code buffer is created on each compile attempt
+      // as in C2, then it must be freed.
+      //code_buffer->free_blob();
+    } else {
+      ImplicitExceptionTable implicit_tbl;
+      nm =  nmethod::new_nmethod(method,
+                                 compile_id,
+                                 entry_bci,
+                                 offsets,
+                                 orig_pc_offset,
+                                 debug_info, dependencies, code_buffer,
+                                 frame_words, oop_map_set,
+                                 handler_table, &implicit_tbl,
+                                 compiler, comp_level,
+                                 speculations, speculations_len,
+                                 nmethod_mirror_index, nmethod_mirror_name, failed_speculations);
 
 
-  Thread* THREAD = thread;
-  HandleMark hm;
-  Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_RETURN);
-  Handle name;
-  Handle sig;
-  if (_comp_level_adjustment == JVMCIRuntime::by_full_signature) {
-    name = java_lang_String::create_from_symbol(method->name(), CHECK_RETURN);
-    sig = java_lang_String::create_from_symbol(method->signature(), CHECK_RETURN);
-  } else {
-    name = Handle();
-    sig = Handle();
+      // Free codeBlobs
+      if (nm == NULL) {
+        // The CodeCache is full.  Print out warning and disable compilation.
+        {
+          MutexUnlocker ml(Compile_lock);
+          MutexUnlocker locker(MethodCompileQueue_lock);
+          CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level));
+        }
+      } else {
+        nm->set_has_unsafe_access(has_unsafe_access);
+        nm->set_has_wide_vectors(has_wide_vector);
+
+        // Record successful registration.
+        // (Put nm into the task handle *before* publishing to the Java heap.)
+        if (JVMCIENV->compile_state() != NULL) {
+          JVMCIENV->compile_state()->task()->set_code(nm);
+        }
+
+        JVMCINMethodData* data = nm->jvmci_nmethod_data();
+        assert(data != NULL, "must be");
+        if (install_default) {
+          assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == NULL, "must be");
+          if (entry_bci == InvocationEntryBci) {
+            if (TieredCompilation) {
+              // If there is an old version we're done with it
+              CompiledMethod* old = method->code();
+              if (TraceMethodReplacement && old != NULL) {
+                ResourceMark rm;
+                char *method_name = method->name_and_sig_as_C_string();
+                tty->print_cr("Replacing method %s", method_name);
+              }
+              if (old != NULL ) {
+                old->make_not_entrant();
+              }
+            }
+            if (TraceNMethodInstalls) {
+              ResourceMark rm;
+              char *method_name = method->name_and_sig_as_C_string();
+              ttyLocker ttyl;
+              tty->print_cr("Installing method (%d) %s [entry point: %p]",
+                            comp_level,
+                            method_name, nm->entry_point());
+            }
+            // Allow the code to be executed
+            method->set_code(method, nm);
+          } else {
+            if (TraceNMethodInstalls ) {
+              ResourceMark rm;
+              char *method_name = method->name_and_sig_as_C_string();
+              ttyLocker ttyl;
+              tty->print_cr("Installing osr method (%d) %s @ %d",
+                            comp_level,
+                            method_name,
+                            entry_bci);
+            }
+            InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
+          }
+        } else {
+          assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == HotSpotJVMCI::resolve(nmethod_mirror), "must be");
+        }
+        nm->make_in_use();
+      }
+      result = nm != NULL ? JVMCI::ok :JVMCI::cache_full;
+    }
   }
 
-  JavaValue result(T_INT);
-  JavaCallArguments args;
-  args.push_oop(receiver);
-  args.push_oop(Handle(THREAD, method->method_holder()->java_mirror()));
-  args.push_oop(name);
-  args.push_oop(sig);
-  args.push_int(is_osr);
-  args.push_int(level);
-  JavaCalls::call_special(&result, receiver->klass(), vmSymbols::adjustCompilationLevel_name(),
-                          vmSymbols::adjustCompilationLevel_signature(), &args, CHECK_RETURN);
+  // String creation must be done outside lock
+  if (failure_detail != NULL) {
+    // A failure to allocate the string is silently ignored.
+    JVMCIObject message = JVMCIENV->create_string(failure_detail, JVMCIENV);
+    JVMCIENV->set_HotSpotCompiledNmethod_installationFailureMessage(compiled_code, message);
+  }
 
-  int comp_level = result.get_jint();
-  if (comp_level < CompLevel_none || comp_level > CompLevel_full_optimization) {
-    assert(false, "compilation level out of bounds");
-    return level;
+  // JVMTI -- compiled method notification (must be done outside lock)
+  if (nm != NULL) {
+    nm->post_compiled_method_load_event();
   }
-  return (CompLevel) comp_level;
-#undef CHECK_RETURN
-}
 
-void JVMCIRuntime::bootstrap_finished(TRAPS) {
-  HandleMark hm(THREAD);
-  Handle receiver = get_HotSpotJVMCIRuntime(CHECK);
-  JavaValue result(T_VOID);
-  JavaCallArguments args;
-  args.push_oop(receiver);
-  JavaCalls::call_special(&result, receiver->klass(), vmSymbols::bootstrapFinished_method_name(), vmSymbols::void_method_signature(), &args, CHECK);
+  return result;
 }
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Fri May 03 14:59:32 2019 -0400
@@ -24,23 +24,68 @@
 #ifndef SHARE_JVMCI_JVMCIRUNTIME_HPP
 #define SHARE_JVMCI_JVMCIRUNTIME_HPP
 
-#include "interpreter/interpreter.hpp"
-#include "memory/allocation.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/deoptimization.hpp"
+#include "code/nmethod.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmciExceptions.hpp"
+#include "jvmci/jvmciObject.hpp"
+
+class JVMCIEnv;
+class JVMCICompiler;
+class JVMCICompileState;
 
-#define JVMCI_ERROR(...)       \
-  { Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::jdk_vm_ci_common_JVMCIError(), __VA_ARGS__); return; }
+// Encapsulates the JVMCI metadata for an nmethod.
+// JVMCINMethodData objects are inlined into nmethods
+// at nmethod::_jvmci_data_offset.
+class JVMCINMethodData {
+  // Index for the HotSpotNmethod mirror in the nmethod's oops table.
+  // This is -1 if there is no mirror in the oops table.
+  int _nmethod_mirror_index;
+
+  // Is HotSpotNmethod.name non-null? If so, the value is
+  // embedded in the end of this object.
+  bool _has_name;
+
+  // Address of the failed speculations list to which a speculation
+  // is appended when it causes a deoptimization.
+  FailedSpeculation** _failed_speculations;
 
-#define JVMCI_ERROR_(ret, ...) \
-  { Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::jdk_vm_ci_common_JVMCIError(), __VA_ARGS__); return ret; }
+public:
+  // Computes the size of a JVMCINMethodData object
+  static int compute_size(const char* nmethod_mirror_name) {
+    int size = sizeof(JVMCINMethodData);
+    if (nmethod_mirror_name != NULL) {
+      size += (int) strlen(nmethod_mirror_name) + 1;
+    }
+    return size;
+  }
+
+  void initialize(int nmethod_mirror_index,
+             const char* name,
+             FailedSpeculation** failed_speculations);
+
+  // Adds `speculation` to the failed speculations list.
+  void add_failed_speculation(nmethod* nm, jlong speculation);
 
-#define JVMCI_ERROR_0(...)    JVMCI_ERROR_(0, __VA_ARGS__)
-#define JVMCI_ERROR_NULL(...) JVMCI_ERROR_(NULL, __VA_ARGS__)
-#define JVMCI_ERROR_OK(...)   JVMCI_ERROR_(JVMCIEnv::ok, __VA_ARGS__)
-#define CHECK_OK              CHECK_(JVMCIEnv::ok)
+  // Gets the JVMCI name of the nmethod (which may be NULL).
+  const char* name() { return _has_name ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : NULL; }
+
+  // Clears the HotSpotNmethod.address field in the  mirror. If nm
+  // is dead, the HotSpotNmethod.entryPoint field is also cleared.
+  void invalidate_nmethod_mirror(nmethod* nm);
+
+  // Gets the mirror from nm's oops table.
+  oop get_nmethod_mirror(nmethod* nm);
 
-class JVMCIRuntime: public AllStatic {
+  // Sets the mirror in nm's oops table.
+  void set_nmethod_mirror(nmethod* nm, oop mirror);
+
+  // Clears the mirror in nm's oops table.
+  void clear_nmethod_mirror(nmethod* nm);
+};
+
+// A top level class that represents an initialized JVMCI runtime.
+// There is one instance of this class per HotSpotJVMCIRuntime object.
+class JVMCIRuntime: public CHeapObj<mtJVMCI> {
  public:
   // Constants describing whether JVMCI wants to be able to adjust the compilation
   // level selected for a method by the VM compilation policy and if so, based on
@@ -52,74 +97,187 @@
   };
 
  private:
-  static jobject _HotSpotJVMCIRuntime_instance;
-  static bool _HotSpotJVMCIRuntime_initialized;
-  static bool _well_known_classes_initialized;
+  volatile bool _being_initialized;
+  volatile bool _initialized;
+
+  JVMCIObject _HotSpotJVMCIRuntime_instance;
+
+  bool _shutdown_called;
+
+  JVMCIObject create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS);
 
-  static CompLevelAdjustment _comp_level_adjustment;
+  // Implementation methods for loading and constant pool access.
+  static Klass* get_klass_by_name_impl(Klass*& accessing_klass,
+                                       const constantPoolHandle& cpool,
+                                       Symbol* klass_name,
+                                       bool require_local);
+  static Klass*   get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                          int klass_index,
+                                          bool& is_accessible,
+                                          Klass* loading_klass);
+  static void   get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd,
+                                        int field_index);
+  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
+                                                int method_index, Bytecodes::Code bc,
+                                                InstanceKlass* loading_klass);
 
-  static bool _shutdown_called;
-
-  static CompLevel adjust_comp_level_inner(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread);
+  // Helper methods
+  static bool       check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass);
+  static methodHandle  lookup_method(InstanceKlass*  accessor,
+                                     Klass*  holder,
+                                     Symbol*         name,
+                                     Symbol*         sig,
+                                     Bytecodes::Code bc,
+                                     constantTag     tag);
 
  public:
-  static bool is_HotSpotJVMCIRuntime_initialized() {
-    return _HotSpotJVMCIRuntime_initialized;
+  JVMCIRuntime() {
+    _initialized = false;
+    _being_initialized = false;
+    _shutdown_called = false;
   }
 
   /**
+   * Compute offsets and construct any state required before executing JVMCI code.
+   */
+  void initialize(JVMCIEnv* jvmciEnv);
+
+  /**
    * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
    */
-  static Handle get_HotSpotJVMCIRuntime(TRAPS);
+  JVMCIObject get_HotSpotJVMCIRuntime(JVMCI_TRAPS);
 
-  static jobject get_HotSpotJVMCIRuntime_jobject(TRAPS) {
-    initialize_JVMCI(CHECK_NULL);
-    assert(_HotSpotJVMCIRuntime_initialized, "must be");
-    return _HotSpotJVMCIRuntime_instance;
+  bool is_HotSpotJVMCIRuntime_initialized() {
+    return _HotSpotJVMCIRuntime_instance.is_non_null();
   }
 
-  static Handle callStatic(const char* className, const char* methodName, const char* returnType, JavaCallArguments* args, TRAPS);
-
-  /**
-   * Determines if the VM is sufficiently booted to initialize JVMCI.
-   */
-  static bool can_initialize_JVMCI();
-
   /**
    * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
    */
-  static void initialize_JVMCI(TRAPS);
+  void initialize_JVMCI(JVMCI_TRAPS);
 
   /**
    * Explicitly initialize HotSpotJVMCIRuntime itself
    */
-  static void initialize_HotSpotJVMCIRuntime(TRAPS);
+  void initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS);
 
-  static void initialize_well_known_classes(TRAPS);
-
-  static void metadata_do(void f(Metadata*));
+  void call_getCompiler(TRAPS);
 
-  static void shutdown(TRAPS);
+  void shutdown();
 
-  static void bootstrap_finished(TRAPS);
-
-  static bool shutdown_called() {
+  bool shutdown_called() {
     return _shutdown_called;
   }
 
+  void bootstrap_finished(TRAPS);
+
+  // Look up a klass by name from a particular class loader (the accessor's).
+  // If require_local, result must be defined in that class loader, or NULL.
+  // If !require_local, a result from remote class loader may be reported,
+  // if sufficient class loader constraints exist such that initiating
+  // a class loading request from the given loader is bound to return
+  // the class defined in the remote loader (or throw an error).
+  //
+  // Return an unloaded klass if !require_local and no class at all is found.
+  //
+  // The CI treats a klass as loaded if it is consistently defined in
+  // another loader, even if it hasn't yet been loaded in all loaders
+  // that could potentially see it via delegation.
+  static Klass* get_klass_by_name(Klass* accessing_klass,
+                                  Symbol* klass_name,
+                                  bool require_local);
+
+  // Constant pool access.
+  static Klass*   get_klass_by_index(const constantPoolHandle& cpool,
+                                     int klass_index,
+                                     bool& is_accessible,
+                                     Klass* loading_klass);
+  static void   get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd,
+                                   int field_index);
+  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
+                                           int method_index, Bytecodes::Code bc,
+                                           InstanceKlass* loading_klass);
+
+  // converts the Klass* representing the holder of a method into a
+  // InstanceKlass*.  This is needed since the holder of a method in
+  // the bytecodes could be an array type.  Basically this converts
+  // array types into java/lang/Object and other types stay as they are.
+  static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass);
+
+  // Helper routine for determining the validity of a compilation
+  // with respect to concurrent class loading.
+  static JVMCI::CodeInstallResult validate_compile_task_dependencies(Dependencies* target, JVMCICompileState* task, char** failure_detail);
+
+  // Compiles `target` with the JVMCI compiler.
+  void compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& target, int entry_bci);
+
+  // Register the result of a compilation.
+  JVMCI::CodeInstallResult register_method(JVMCIEnv* JVMCIENV,
+                       const methodHandle&       target,
+                       nmethod*&                 nm,
+                       int                       entry_bci,
+                       CodeOffsets*              offsets,
+                       int                       orig_pc_offset,
+                       CodeBuffer*               code_buffer,
+                       int                       frame_words,
+                       OopMapSet*                oop_map_set,
+                       ExceptionHandlerTable*    handler_table,
+                       AbstractCompiler*         compiler,
+                       DebugInformationRecorder* debug_info,
+                       Dependencies*             dependencies,
+                       int                       compile_id,
+                       bool                      has_unsafe_access,
+                       bool                      has_wide_vector,
+                       JVMCIObject               compiled_code,
+                       JVMCIObject               nmethod_mirror,
+                       FailedSpeculation**       failed_speculations,
+                       char*                     speculations,
+                       int                       speculations_len);
+
   /**
-   * Lets JVMCI modify the compilation level currently selected for a method by
-   * the VM compilation policy.
-   *
-   * @param method the method being scheduled for compilation
-   * @param is_osr specifies if the compilation is an OSR compilation
-   * @param level the compilation level currently selected by the VM compilation policy
-   * @param thread the current thread
-   * @return the compilation level to use for the compilation
+   * Exits the VM due to an unexpected exception.
    */
-  static CompLevel adjust_comp_level(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread);
+  static void exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message);
+
+  static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);
+
+#define CHECK_EXIT THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(NULL, buf); \
+    return; \
+  } \
+  (void)(0
 
-  static BasicType kindToBasicType(Handle kind, TRAPS);
+#define CHECK_EXIT_(v) THREAD);                 \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(NULL, buf); \
+    return v; \
+  } \
+  (void)(0
+
+#define JVMCI_CHECK_EXIT JVMCIENV); \
+  if (JVMCIENV->has_pending_exception()) {      \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(JVMCIENV, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define JVMCI_CHECK_EXIT_(result) JVMCIENV); \
+  if (JVMCIENV->has_pending_exception()) {      \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(JVMCIENV, buf); \
+    return result; \
+  } \
+  (void)(0
+
+  static BasicType kindToBasicType(const Handle& kind, TRAPS);
 
   static void new_instance_common(JavaThread* thread, Klass* klass, bool null_on_fail);
   static void new_array_common(JavaThread* thread, Klass* klass, jint length, bool null_on_fail);
@@ -179,11 +337,8 @@
   static void throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
   static void throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
 
-  // Forces initialization of the JVMCI runtime.
-  static void force_initialization(TRAPS);
-
   // Test only function
-  static int test_deoptimize_call_int(JavaThread* thread, int value);
+  static jint test_deoptimize_call_int(JavaThread* thread, int value);
 };
 
 // Tracing macros.
@@ -194,10 +349,10 @@
 #define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else
 #define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else
 
-#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print("JVMCITrace-1: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print("   JVMCITrace-2: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print("      JVMCITrace-3: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print("         JVMCITrace-4: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print("            JVMCITrace-5: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print(PTR_FORMAT " JVMCITrace-1: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print(PTR_FORMAT "    JVMCITrace-2: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print(PTR_FORMAT "       JVMCITrace-3: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print(PTR_FORMAT "          JVMCITrace-4: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print(PTR_FORMAT "             JVMCITrace-5: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
 
 #endif // SHARE_JVMCI_JVMCIRUNTIME_HPP
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp	Fri May 03 14:59:32 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
@@ -27,8 +27,11 @@
 #include "jvmci/jvmci_globals.hpp"
 #include "gc/shared/gcConfig.hpp"
 #include "utilities/defaultStream.hpp"
+#include "utilities/ostream.hpp"
 #include "runtime/globals_extension.hpp"
 
+fileStream* JVMCIGlobals::_jni_config_file = NULL;
+
 JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
             MATERIALIZE_PD_DEVELOPER_FLAG, \
             MATERIALIZE_PRODUCT_FLAG, \
@@ -79,6 +82,10 @@
       return false;
     }
     FLAG_SET_DEFAULT(EnableJVMCI, true);
+    if (BootstrapJVMCI && UseJVMCINativeLibrary) {
+      jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary");
+      return false;
+    }
   }
 
   if (!EnableJVMCI) {
@@ -97,7 +104,9 @@
   CHECK_NOT_SET(JVMCINMethodSizeLimit,        EnableJVMCI)
   CHECK_NOT_SET(MethodProfileWidth,           EnableJVMCI)
   CHECK_NOT_SET(JVMCIPrintProperties,         EnableJVMCI)
-  CHECK_NOT_SET(TraceUncollectedSpeculations, EnableJVMCI)
+  CHECK_NOT_SET(UseJVMCINativeLibrary,        EnableJVMCI)
+  CHECK_NOT_SET(JVMCILibPath,                 EnableJVMCI)
+  CHECK_NOT_SET(JVMCILibDumpJNIConfig,        EnableJVMCI)
 
 #ifndef PRODUCT
 #define JVMCI_CHECK4(type, name, value, doc) assert(name##checked, #name " flag not checked");
@@ -110,10 +119,21 @@
 #undef JVMCI_CHECK3
 #undef JVMCI_CHECK4
 #undef JVMCI_FLAG_CHECKED
-#endif
+#endif // PRODUCT
 #undef CHECK_NOT_SET
+
+  if (JVMCILibDumpJNIConfig != NULL) {
+    _jni_config_file = new(ResourceObj::C_HEAP, mtJVMCI) fileStream(JVMCILibDumpJNIConfig);
+    if (_jni_config_file == NULL || !_jni_config_file->is_open()) {
+      jio_fprintf(defaultStream::error_stream(),
+          "Could not open file for dumping JVMCI shared library JNI config: %s\n", JVMCILibDumpJNIConfig);
+      return false;
+    }
+  }
+
   return true;
 }
+
 void JVMCIGlobals::check_jvmci_supported_gc() {
   if (EnableJVMCI) {
     // Check if selected GC is supported by JVMCI and Java compiler
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,7 @@
 #ifndef SHARE_JVMCI_JVMCI_GLOBALS_HPP
 #define SHARE_JVMCI_JVMCI_GLOBALS_HPP
 
-#include "runtime/globals.hpp"
+#include "utilities/ostream.hpp"
 
 //
 // Defines all global flags used by the JVMCI compiler. Only flags that need
@@ -62,11 +62,13 @@
           "Print JVMCI bootstrap progress and summary")                     \
                                                                             \
   experimental(intx, JVMCIThreads, 1,                                       \
-          "Force number of JVMCI compiler threads to use")                  \
+          "Force number of JVMCI compiler threads to use. Ignored if "      \
+          "UseJVMCICompiler is false.")                                     \
           range(1, max_jint)                                                \
                                                                             \
   experimental(intx, JVMCIHostThreads, 1,                                   \
-          "Force number of compiler threads for JVMCI host compiler")       \
+          "Force number of C1 compiler threads. Ignored if "                \
+          "UseJVMCICompiler is false.")                                     \
           range(1, max_jint)                                                \
                                                                             \
   NOT_COMPILER2(product(intx, MaxVectorSize, 64,                            \
@@ -97,8 +99,17 @@
   experimental(intx, MethodProfileWidth, 0,                                 \
           "Number of methods to record in call profile")                    \
                                                                             \
-  develop(bool, TraceUncollectedSpeculations, false,                        \
-          "Print message when a failed speculation was not collected")      \
+  experimental(ccstr, JVMCILibPath, NULL,                                   \
+          "LD path for loading the JVMCI shared library")                   \
+                                                                            \
+  experimental(ccstr, JVMCILibDumpJNIConfig, NULL,                          \
+          "Dumps to the given file a description of the classes, fields "   \
+          "and methods the JVMCI shared library must provide")              \
+                                                                            \
+  experimental(bool, UseJVMCINativeLibrary, false,                          \
+          "Execute JVMCI Java code from a shared library "                  \
+          "instead of loading it from class files and executing it "        \
+          "on the HotSpot heap")                                            \
                                                                             \
   NOT_COMPILER2(diagnostic(bool, UseMultiplyToLenIntrinsic, false,          \
           "Enables intrinsification of BigInteger.multiplyToLen()"))        \
@@ -130,14 +141,22 @@
             IGNORE_CONSTRAINT, \
             IGNORE_WRITEABLE)
 
+// The base name for the shared library containing the JVMCI based compiler
+#define JVMCI_SHARED_LIBRARY_NAME "jvmcicompiler"
+
 class JVMCIGlobals {
+ private:
+  static fileStream* _jni_config_file;
  public:
-  // Return true if jvmci flags are consistent. If not consistent,
+
+  // Returns true if jvmci flags are consistent. If not consistent,
   // an error message describing the inconsistency is printed before
   // returning false.
   static bool check_jvmci_flags_are_consistent();
 
   // Check and exit VM with error if selected GC is not supported by JVMCI.
   static void check_jvmci_supported_gc();
+
+  static fileStream* get_jni_config_file() { return _jni_config_file; }
 };
 #endif // SHARE_JVMCI_JVMCI_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/metadataHandleBlock.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,158 @@
+/*
+ * 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 "jvmci/metadataHandleBlock.hpp"
+
+MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
+intptr_t             MetadataHandleBlock::_free_list = 0;
+int                  MetadataHandleBlock::_allocate_before_rebuild = 0;
+
+jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
+  assert(obj->is_valid() && obj->is_metadata(), "must be");
+
+  if (_last == NULL) {
+    // This is the first allocation.
+    _last = this;
+  }
+
+  HandleRecord* handle = get_handle();
+
+  if (handle != NULL) {
+    handle->set_value(obj);
+#ifdef METADATA_TRACK_NAMES
+    handle->set_name(obj->print_value_string());
+#endif
+    return (jmetadata) handle;
+  }
+
+  // Check if unused block follow last
+  if (_last->_next != NULL) {
+    // update last and retry
+    _last = _last->_next;
+    return allocate_metadata_handle(obj);
+  }
+
+  // No space available, we have to rebuild free list or expand
+  if (_allocate_before_rebuild == 0) {
+    rebuild_free_list();        // updates _allocate_before_rebuild counter
+  } else {
+    // Append new block
+    // This can block, but the caller has a metadata handle around this object.
+    _last->_next = allocate_block();
+    _last = _last->_next;
+    _allocate_before_rebuild--;
+  }
+  return allocate_metadata_handle(obj);  // retry
+}
+
+
+void MetadataHandleBlock::rebuild_free_list() {
+  assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
+  int free = 0;
+  int blocks = 0;
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* handle = &(current->_handles)[index];
+      if (handle->value() == NULL) {
+        // this handle was cleared out by a delete call, reuse it
+        chain_free_list(handle);
+        free++;
+      }
+    }
+    // we should not rebuild free list if there are unused handles at the end
+    assert(current->_top == block_size_in_handles, "just checking");
+    blocks++;
+  }
+  // Heuristic: if more than half of the handles are NOT free we rebuild next time
+  // as well, otherwise we append a corresponding number of new blocks before
+  // attempting a free list rebuild again.
+  int total = blocks * block_size_in_handles;
+  int extra = total - 2*free;
+  if (extra > 0) {
+    // Not as many free handles as we would like - compute number of new blocks to append
+    _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
+  }
+}
+
+void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* root = &(current->_handles)[index];
+      Metadata* value = root->value();
+      // traverse heap pointers only, not deleted handles or free list
+      // pointers
+      if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
+        assert(value->is_valid(), "invalid metadata %s", get_name(index));
+        f(value);
+      }
+    }
+    // the next handle block is valid only if current block is full
+    if (current->_top < block_size_in_handles) {
+      break;
+    }
+  }
+}
+
+// Visit any live metadata handles and clean them up.  Since clearing of these handles is driven by
+// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
+void MetadataHandleBlock::do_unloading() {
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* handle = &(current->_handles)[index];
+      Metadata* value = handle->value();
+      // traverse heap pointers only, not deleted handles or free list
+      // pointers
+      if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
+        Klass* klass = NULL;
+        if (value->is_klass()) {
+          klass = (Klass*)value;
+        } else if (value->is_method()) {
+          Method* m = (Method*)value;
+          klass = m->method_holder();
+        } else if (value->is_constantPool()) {
+          ConstantPool* cp = (ConstantPool*)value;
+          klass = cp->pool_holder();
+        } else {
+          ShouldNotReachHere();
+        }
+        if (klass->class_loader_data()->is_unloading()) {
+          // This needs to be marked so that it's no longer scanned
+          // but can't be put on the free list yet. The
+          // HandleCleaner will set this to NULL and
+          // put it on the free list.
+          jlong old_value = Atomic::cmpxchg((jlong) (ptr_tag), (jlong*)handle, (jlong) value);
+          if (old_value == (jlong) value) {
+            // Success
+          } else {
+            guarantee(old_value == 0, "only other possible value");
+          }
+        }
+      }
+    }
+    // the next handle block is valid only if current block is full
+    if (current->_top < block_size_in_handles) {
+      break;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/metadataHandleBlock.hpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,170 @@
+/*
+ * 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_JVMCI_METADATAHANDLEBLOCK_HPP
+#define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
+
+#include "oops/constantPool.hpp"
+#include "oops/metadata.hpp"
+#include "oops/method.hpp"
+#include "runtime/handles.hpp"
+#include "runtime/os.hpp"
+
+#ifdef ASSERT
+#define METADATA_TRACK_NAMES
+#endif
+
+struct _jmetadata {
+ private:
+  Metadata* _value;
+#ifdef METADATA_TRACK_NAMES
+  // Debug data for tracking stale metadata
+  const char* _name;
+#endif
+
+ public:
+  Metadata* value() { return _value; }
+
+#ifdef METADATA_TRACK_NAMES
+  void initialize() {
+    _value = NULL;
+    _name = NULL;
+  }
+#endif
+
+  void set_value(Metadata* value) {
+    _value = value;
+  }
+
+#ifdef METADATA_TRACK_NAMES
+  const char* name() { return _name; }
+  void set_name(const char* name) {
+    if (_name != NULL) {
+      os::free((void*) _name);
+      _name = NULL;
+    }
+    if (name != NULL) {
+      _name = os::strdup(name);
+    }
+  }
+#endif
+};
+
+typedef struct _jmetadata HandleRecord;
+typedef struct _jmetadata *jmetadata;
+
+// JVMCI maintains direct references to metadata. To make these references safe in the face of
+// class redefinition, they are held in handles so they can be scanned during GC. They are
+// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
+// passed back to the Java code which is responsible for setting the handle to NULL when it
+// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
+// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
+class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
+ private:
+  enum SomeConstants {
+    block_size_in_handles  = 32,      // Number of handles per handle block
+    ptr_tag = 1,
+    ptr_mask = ~((intptr_t)ptr_tag)
+  };
+
+
+  // Free handles always have their low bit set so those pointers can
+  // be distinguished from handles which are in use.  The last handle
+  // on the free list has a NULL pointer with the tag bit set, so it's
+  // clear that the handle has been reclaimed.  The _free_list is
+  // always a real pointer to a handle.
+
+  HandleRecord    _handles[block_size_in_handles]; // The handles
+  int             _top;                         // Index of next unused handle
+  MetadataHandleBlock* _next;                   // Link to next block
+
+  // The following instance variables are only used by the first block in a chain.
+  // Having two types of blocks complicates the code and the space overhead is negligible.
+  static MetadataHandleBlock* _last;                   // Last block in use
+  static intptr_t        _free_list;                   // Handle free list
+  static int             _allocate_before_rebuild;     // Number of blocks to allocate before rebuilding free list
+
+  MetadataHandleBlock() {
+    _top = 0;
+    _next = NULL;
+#ifdef METADATA_TRACK_NAMES
+    for (int i = 0; i < block_size_in_handles; i++) {
+      _handles[i].initialize();
+    }
+#endif
+  }
+
+  const char* get_name(int index) {
+#ifdef METADATA_TRACK_NAMES
+    return _handles[index].name();
+#else
+    return "<missing>";
+#endif
+  }
+
+  static HandleRecord* get_free_handle() {
+    assert(_free_list != 0, "should check before calling");
+    HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
+    _free_list = (ptr_mask & (intptr_t) (handle->value()));
+    assert(_free_list != ptr_tag, "should be null");
+    handle->set_value(NULL);
+    return handle;
+  }
+
+  static HandleRecord* get_handle() {
+    assert(_last != NULL, "sanity");
+    // Try last block
+    if (_last->_top < block_size_in_handles) {
+      return &(_last->_handles)[_last->_top++];
+    } else if (_free_list != 0) {
+      // Try free list
+      return get_free_handle();
+    }
+    return NULL;
+  }
+
+  void rebuild_free_list();
+
+  jmetadata allocate_metadata_handle(Metadata* metadata);
+
+ public:
+  jmetadata allocate_handle(const methodHandle& handle)       { return allocate_metadata_handle(handle()); }
+  jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
+
+  static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
+
+  // Adds `handle` to the free list in this block
+  static void chain_free_list(HandleRecord* handle) {
+    handle->set_value((Metadata*) (ptr_tag | _free_list));
+#ifdef METADATA_TRACK_NAMES
+    handle->set_name(NULL);
+#endif
+    _free_list = (intptr_t) handle;
+  }
+
+  void metadata_do(void f(Metadata*));
+
+  void do_unloading();
+};
+
+#endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
--- a/src/hotspot/share/jvmci/systemDictionary_jvmci.hpp	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
-#define SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
-
-#if !INCLUDE_JVMCI
-#define JVMCI_WK_KLASSES_DO(do_klass)
-#else
-#define JVMCI_WK_KLASSES_DO(do_klass)                                                                      \
-  /* JVMCI classes. These are loaded on-demand. */                                                         \
-  do_klass(JVMCI_klass,                                  jdk_vm_ci_runtime_JVMCI                          ) \
-  do_klass(HotSpotCompiledCode_klass,                    jdk_vm_ci_hotspot_HotSpotCompiledCode            ) \
-  do_klass(HotSpotCompiledCode_Comment_klass,            jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment    ) \
-  do_klass(HotSpotCompiledNmethod_klass,                 jdk_vm_ci_hotspot_HotSpotCompiledNmethod         ) \
-  do_klass(HotSpotForeignCallTarget_klass,               jdk_vm_ci_hotspot_HotSpotForeignCallTarget       ) \
-  do_klass(HotSpotReferenceMap_klass,                    jdk_vm_ci_hotspot_HotSpotReferenceMap            ) \
-  do_klass(HotSpotInstalledCode_klass,                   jdk_vm_ci_hotspot_HotSpotInstalledCode           ) \
-  do_klass(HotSpotNmethod_klass,                         jdk_vm_ci_hotspot_HotSpotNmethod                 ) \
-  do_klass(HotSpotResolvedJavaMethodImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl  ) \
-  do_klass(HotSpotResolvedObjectTypeImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl  ) \
-  do_klass(HotSpotCompressedNullConstant_klass,          jdk_vm_ci_hotspot_HotSpotCompressedNullConstant  ) \
-  do_klass(HotSpotObjectConstantImpl_klass,              jdk_vm_ci_hotspot_HotSpotObjectConstantImpl      ) \
-  do_klass(HotSpotMetaspaceConstantImpl_klass,           jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl   ) \
-  do_klass(HotSpotSentinelConstant_klass,                jdk_vm_ci_hotspot_HotSpotSentinelConstant        ) \
-  do_klass(HotSpotStackFrameReference_klass,             jdk_vm_ci_hotspot_HotSpotStackFrameReference     ) \
-  do_klass(HotSpotMetaData_klass,                        jdk_vm_ci_hotspot_HotSpotMetaData                ) \
-  do_klass(HotSpotConstantPool_klass,                    jdk_vm_ci_hotspot_HotSpotConstantPool            ) \
-  do_klass(HotSpotJVMCIMetaAccessContext_klass,          jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext  ) \
-  do_klass(HotSpotJVMCIRuntime_klass,                    jdk_vm_ci_hotspot_HotSpotJVMCIRuntime            ) \
-  do_klass(HotSpotSpeculationLog_klass,                  jdk_vm_ci_hotspot_HotSpotSpeculationLog          ) \
-  do_klass(HotSpotCompilationRequestResult_klass,        jdk_vm_ci_hotspot_HotSpotCompilationRequestResult) \
-  do_klass(VMField_klass,                                jdk_vm_ci_hotspot_VMField                        ) \
-  do_klass(VMFlag_klass,                                 jdk_vm_ci_hotspot_VMFlag                         ) \
-  do_klass(VMIntrinsicMethod_klass,                      jdk_vm_ci_hotspot_VMIntrinsicMethod              ) \
-  do_klass(Assumptions_ConcreteMethod_klass,             jdk_vm_ci_meta_Assumptions_ConcreteMethod        ) \
-  do_klass(Assumptions_NoFinalizableSubclass_klass,      jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass ) \
-  do_klass(Assumptions_ConcreteSubtype_klass,            jdk_vm_ci_meta_Assumptions_ConcreteSubtype       ) \
-  do_klass(Assumptions_LeafType_klass,                   jdk_vm_ci_meta_Assumptions_LeafType              ) \
-  do_klass(Assumptions_CallSiteTargetValue_klass,        jdk_vm_ci_meta_Assumptions_CallSiteTargetValue   ) \
-  do_klass(Architecture_klass,                           jdk_vm_ci_code_Architecture                      ) \
-  do_klass(TargetDescription_klass,                      jdk_vm_ci_code_TargetDescription                 ) \
-  do_klass(BytecodePosition_klass,                       jdk_vm_ci_code_BytecodePosition                  ) \
-  do_klass(DebugInfo_klass,                              jdk_vm_ci_code_DebugInfo                         ) \
-  do_klass(RegisterSaveLayout_klass,                     jdk_vm_ci_code_RegisterSaveLayout                ) \
-  do_klass(BytecodeFrame_klass,                          jdk_vm_ci_code_BytecodeFrame                     ) \
-  do_klass(InstalledCode_klass,                          jdk_vm_ci_code_InstalledCode                     ) \
-  do_klass(code_Location_klass,                          jdk_vm_ci_code_Location                          ) \
-  do_klass(code_Register_klass,                          jdk_vm_ci_code_Register                          ) \
-  do_klass(RegisterValue_klass,                          jdk_vm_ci_code_RegisterValue                     ) \
-  do_klass(StackSlot_klass,                              jdk_vm_ci_code_StackSlot                         ) \
-  do_klass(StackLockValue_klass,                         jdk_vm_ci_code_StackLockValue                    ) \
-  do_klass(VirtualObject_klass,                          jdk_vm_ci_code_VirtualObject                     ) \
-  do_klass(site_Call_klass,                              jdk_vm_ci_code_site_Call                         ) \
-  do_klass(site_ConstantReference_klass,                 jdk_vm_ci_code_site_ConstantReference            ) \
-  do_klass(site_DataPatch_klass,                         jdk_vm_ci_code_site_DataPatch                    ) \
-  do_klass(site_DataSectionReference_klass,              jdk_vm_ci_code_site_DataSectionReference         ) \
-  do_klass(site_ExceptionHandler_klass,                  jdk_vm_ci_code_site_ExceptionHandler             ) \
-  do_klass(site_Mark_klass,                              jdk_vm_ci_code_site_Mark                         ) \
-  do_klass(site_Infopoint_klass,                         jdk_vm_ci_code_site_Infopoint                    ) \
-  do_klass(site_Site_klass,                              jdk_vm_ci_code_site_Site                         ) \
-  do_klass(site_InfopointReason_klass,                   jdk_vm_ci_code_site_InfopointReason              ) \
-  do_klass(InspectedFrameVisitor_klass,                  jdk_vm_ci_code_stack_InspectedFrameVisitor       ) \
-  do_klass(JavaConstant_klass,                           jdk_vm_ci_meta_JavaConstant                      ) \
-  do_klass(PrimitiveConstant_klass,                      jdk_vm_ci_meta_PrimitiveConstant                 ) \
-  do_klass(RawConstant_klass,                            jdk_vm_ci_meta_RawConstant                       ) \
-  do_klass(NullConstant_klass,                           jdk_vm_ci_meta_NullConstant                      ) \
-  do_klass(ExceptionHandler_klass,                       jdk_vm_ci_meta_ExceptionHandler                  ) \
-  do_klass(JavaKind_klass,                               jdk_vm_ci_meta_JavaKind                          ) \
-  do_klass(ValueKind_klass,                              jdk_vm_ci_meta_ValueKind                         ) \
-  do_klass(Value_klass,                                  jdk_vm_ci_meta_Value                             )
-#endif
-
-#endif // SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Fri May 03 14:59:32 2019 -0400
@@ -23,27 +23,16 @@
  */
 
 #include "precompiled.hpp"
-#include "code/codeBlob.hpp"
-#include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
-#include "gc/shared/cardTable.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
-#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
 #include "jvmci/vmStructs_compiler_runtime.hpp"
 #include "jvmci/vmStructs_jvmci.hpp"
-#include "oops/oop.hpp"
-#include "oops/oopHandle.hpp"
 #include "oops/objArrayKlass.hpp"
-#include "runtime/flags/jvmFlag.hpp"
-#include "runtime/globals.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/thread.hpp"
-#include "runtime/vm_version.hpp"
 #if INCLUDE_G1GC
-#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/g1ThreadLocalData.hpp"
@@ -180,7 +169,7 @@
   volatile_nonstatic_field(JavaThread,         _is_method_handle_return,                      int)                                   \
   nonstatic_field(JavaThread,                  _osthread,                                     OSThread*)                             \
   nonstatic_field(JavaThread,                  _pending_deoptimization,                       int)                                   \
-  nonstatic_field(JavaThread,                  _pending_failed_speculation,                   long)                                  \
+  nonstatic_field(JavaThread,                  _pending_failed_speculation,                   jlong)                                 \
   nonstatic_field(JavaThread,                  _pending_transfer_to_interpreter,              bool)                                  \
   nonstatic_field(JavaThread,                  _jvmci_counters,                               jlong*)                                \
   nonstatic_field(JavaThread,                  _should_post_on_exceptions_flag,               int)                                   \
@@ -189,12 +178,6 @@
   static_field(java_lang_Class,                _klass_offset,                                 int)                                   \
   static_field(java_lang_Class,                _array_klass_offset,                           int)                                   \
                                                                                                                                      \
-  nonstatic_field(JVMCIEnv,                    _task,                                         CompileTask*)                          \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_hotswap_or_post_breakpoint,         jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_access_local_variables,             jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_post_on_exceptions,                 jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_pop_frame,                          jbyte)                                 \
-                                                                                                                                     \
   nonstatic_field(InvocationCounter,           _counter,                                      unsigned int)                          \
                                                                                                                                      \
   nonstatic_field(Klass,                       _secondary_super_cache,                        Klass*)                                \
@@ -209,6 +192,7 @@
   nonstatic_field(Klass,                       _java_mirror,                                  OopHandle)                             \
   nonstatic_field(Klass,                       _modifier_flags,                               jint)                                  \
   nonstatic_field(Klass,                       _access_flags,                                 AccessFlags)                           \
+  nonstatic_field(Klass,                       _class_loader_data,                            ClassLoaderData*)                      \
                                                                                                                                      \
   nonstatic_field(LocalVariableTableElement,   start_bci,                                     u2)                                    \
   nonstatic_field(LocalVariableTableElement,   length,                                        u2)                                    \
@@ -359,6 +343,7 @@
   declare_toplevel_type(JVMFlag)                                          \
   declare_toplevel_type(JVMFlag*)                                         \
   declare_toplevel_type(InvocationCounter)                                \
+  declare_toplevel_type(JVMCICompileState)                                \
   declare_toplevel_type(JVMCIEnv)                                         \
   declare_toplevel_type(LocalVariableTableElement)                        \
   declare_toplevel_type(narrowKlass)                                      \
@@ -401,6 +386,7 @@
   declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \
   declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM)             \
   declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC)   \
+  declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE)   \
                                                                           \
   declare_constant(JVM_CONSTANT_Utf8)                                     \
   declare_constant(JVM_CONSTANT_Unicode)                                  \
@@ -417,6 +403,8 @@
   declare_constant(JVM_CONSTANT_MethodHandle)                             \
   declare_constant(JVM_CONSTANT_MethodType)                               \
   declare_constant(JVM_CONSTANT_InvokeDynamic)                            \
+  declare_constant(JVM_CONSTANT_Module)                                   \
+  declare_constant(JVM_CONSTANT_Package)                                  \
   declare_constant(JVM_CONSTANT_ExternalMax)                              \
                                                                           \
   declare_constant(JVM_CONSTANT_Invalid)                                  \
@@ -542,11 +530,11 @@
   declare_constant(JumpData::taken_off_set)                               \
   declare_constant(JumpData::displacement_off_set)                        \
                                                                           \
-  declare_constant(JVMCIEnv::ok)                                          \
-  declare_constant(JVMCIEnv::dependencies_failed)                         \
-  declare_constant(JVMCIEnv::dependencies_invalid)                        \
-  declare_constant(JVMCIEnv::cache_full)                                  \
-  declare_constant(JVMCIEnv::code_too_large)                              \
+  declare_preprocessor_constant("JVMCIEnv::ok",                   JVMCI::ok)                      \
+  declare_preprocessor_constant("JVMCIEnv::dependencies_failed",  JVMCI::dependencies_failed)     \
+  declare_preprocessor_constant("JVMCIEnv::dependencies_invalid", JVMCI::dependencies_invalid)    \
+  declare_preprocessor_constant("JVMCIEnv::cache_full",           JVMCI::cache_full)              \
+  declare_preprocessor_constant("JVMCIEnv::code_too_large",       JVMCI::code_too_large)          \
   declare_constant(JVMCIRuntime::none)                                    \
   declare_constant(JVMCIRuntime::by_holder)                               \
   declare_constant(JVMCIRuntime::by_full_signature)                       \
--- a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp	Fri May 03 14:59:32 2019 -0400
@@ -28,80 +28,110 @@
 #if !INCLUDE_JVMCI
 #define JVMCI_VM_SYMBOLS_DO(template, do_alias)
 #else
-#define JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                                            \
-  template(jdk_vm_ci_runtime_JVMCI,                               "jdk/vm/ci/runtime/JVMCI")                               \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledCode,                 "jdk/vm/ci/hotspot/HotSpotCompiledCode")                 \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment")         \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              "jdk/vm/ci/hotspot/HotSpotCompiledNmethod")              \
-  template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            "jdk/vm/ci/hotspot/HotSpotForeignCallTarget")            \
-  template(jdk_vm_ci_hotspot_HotSpotReferenceMap,                 "jdk/vm/ci/hotspot/HotSpotReferenceMap")                 \
-  template(jdk_vm_ci_hotspot_CompilerToVM,                        "jdk/vm/ci/hotspot/CompilerToVM")                        \
-  template(jdk_vm_ci_hotspot_HotSpotInstalledCode,                "jdk/vm/ci/hotspot/HotSpotInstalledCode")                \
-  template(jdk_vm_ci_hotspot_HotSpotNmethod,                      "jdk/vm/ci/hotspot/HotSpotNmethod")                      \
-  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl")       \
-  template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl")       \
-  template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant")       \
-  template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl")           \
-  template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl")        \
-  template(jdk_vm_ci_hotspot_HotSpotSentinelConstant,             "jdk/vm/ci/hotspot/HotSpotSentinelConstant")             \
-  template(jdk_vm_ci_hotspot_HotSpotStackFrameReference,          "jdk/vm/ci/hotspot/HotSpotStackFrameReference")          \
-  template(jdk_vm_ci_hotspot_HotSpotMetaData,                     "jdk/vm/ci/hotspot/HotSpotMetaData")                     \
-  template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                 \
-  template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext")       \
-  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                 \
-  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")               \
-  template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult")     \
-  template(jdk_vm_ci_hotspot_VMField,                             "jdk/vm/ci/hotspot/VMField")                             \
-  template(jdk_vm_ci_hotspot_VMFlag,                              "jdk/vm/ci/hotspot/VMFlag")                              \
-  template(jdk_vm_ci_hotspot_VMIntrinsicMethod,                   "jdk/vm/ci/hotspot/VMIntrinsicMethod")                   \
-  template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                           \
-  template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                      \
-  template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                            \
-  template(jdk_vm_ci_meta_NullConstant,                           "jdk/vm/ci/meta/NullConstant")                           \
-  template(jdk_vm_ci_meta_ExceptionHandler,                       "jdk/vm/ci/meta/ExceptionHandler")                       \
-  template(jdk_vm_ci_meta_JavaKind,                               "jdk/vm/ci/meta/JavaKind")                               \
-  template(jdk_vm_ci_meta_ValueKind,                              "jdk/vm/ci/meta/ValueKind")                              \
-  template(jdk_vm_ci_meta_Value,                                  "jdk/vm/ci/meta/Value")                                  \
-  template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            "jdk/vm/ci/meta/Assumptions$ConcreteSubtype")            \
-  template(jdk_vm_ci_meta_Assumptions_LeafType,                   "jdk/vm/ci/meta/Assumptions$LeafType")                   \
-  template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")      \
-  template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")             \
-  template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")        \
-  template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                           \
-  template(jdk_vm_ci_code_BytecodeFrame,                          "jdk/vm/ci/code/BytecodeFrame")                          \
-  template(jdk_vm_ci_code_BytecodePosition,                       "jdk/vm/ci/code/BytecodePosition")                       \
-  template(jdk_vm_ci_code_DebugInfo,                              "jdk/vm/ci/code/DebugInfo")                              \
-  template(jdk_vm_ci_code_InstalledCode,                          "jdk/vm/ci/code/InstalledCode")                          \
-  template(jdk_vm_ci_code_Location,                               "jdk/vm/ci/code/Location")                               \
-  template(jdk_vm_ci_code_Register,                               "jdk/vm/ci/code/Register")                               \
-  template(jdk_vm_ci_code_RegisterValue,                          "jdk/vm/ci/code/RegisterValue")                          \
-  template(jdk_vm_ci_code_StackSlot,                              "jdk/vm/ci/code/StackSlot")                              \
-  template(jdk_vm_ci_code_StackLockValue,                         "jdk/vm/ci/code/StackLockValue")                         \
-  template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                      \
-  template(jdk_vm_ci_code_VirtualObject,                          "jdk/vm/ci/code/VirtualObject")                          \
-  template(jdk_vm_ci_code_RegisterSaveLayout,                     "jdk/vm/ci/code/RegisterSaveLayout")                     \
-  template(jdk_vm_ci_code_InvalidInstalledCodeException,          "jdk/vm/ci/code/InvalidInstalledCodeException")          \
-  template(jdk_vm_ci_code_site_Call,                              "jdk/vm/ci/code/site/Call")                              \
-  template(jdk_vm_ci_code_site_ConstantReference,                 "jdk/vm/ci/code/site/ConstantReference")                 \
-  template(jdk_vm_ci_code_site_DataPatch,                         "jdk/vm/ci/code/site/DataPatch")                         \
-  template(jdk_vm_ci_code_site_DataSectionReference,              "jdk/vm/ci/code/site/DataSectionReference")              \
-  template(jdk_vm_ci_code_site_ExceptionHandler,                  "jdk/vm/ci/code/site/ExceptionHandler")                  \
-  template(jdk_vm_ci_code_site_Mark,                              "jdk/vm/ci/code/site/Mark")                              \
-  template(jdk_vm_ci_code_site_Infopoint,                         "jdk/vm/ci/code/site/Infopoint")                         \
-  template(jdk_vm_ci_code_stack_InspectedFrameVisitor,            "jdk/vm/ci/code/stack/InspectedFrameVisitor")            \
-  template(jdk_vm_ci_code_site_Site,                              "jdk/vm/ci/code/site/Site")                              \
-  template(jdk_vm_ci_code_site_InfopointReason,                   "jdk/vm/ci/code/site/InfopointReason")                   \
-  template(jdk_vm_ci_common_JVMCIError,                           "jdk/vm/ci/common/JVMCIError")                           \
-  template(visitFrame_name,                                       "visitFrame")                                            \
-  template(visitFrame_signature,                                  "(Ljdk/vm/ci/code/stack/InspectedFrame;)Ljava/lang/Object;") \
-  template(adjustCompilationLevel_name,                           "adjustCompilationLevel")                                \
-  template(adjustCompilationLevel_signature,                      "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ZI)I") \
-  template(compileMethod_name,                                    "compileMethod")                                         \
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                                                           \
+  template(jdk_vm_ci_services_Services,                           "jdk/vm/ci/services/Services")                                          \
+  template(jdk_vm_ci_runtime_JVMCI,                               "jdk/vm/ci/runtime/JVMCI")                                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode,                 "jdk/vm/ci/hotspot/HotSpotCompiledCode")                                \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment")                        \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              "jdk/vm/ci/hotspot/HotSpotCompiledNmethod")                             \
+  template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            "jdk/vm/ci/hotspot/HotSpotForeignCallTarget")                           \
+  template(jdk_vm_ci_hotspot_HotSpotReferenceMap,                 "jdk/vm/ci/hotspot/HotSpotReferenceMap")                                \
+  template(jdk_vm_ci_hotspot_CompilerToVM,                        "jdk/vm/ci/hotspot/CompilerToVM")                                       \
+  template(jdk_vm_ci_hotspot_HotSpotInstalledCode,                "jdk/vm/ci/hotspot/HotSpotInstalledCode")                               \
+  template(jdk_vm_ci_hotspot_HotSpotNmethod,                      "jdk/vm/ci/hotspot/HotSpotNmethod")                                     \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType,        "jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType")                       \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl,        "jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl")                       \
+  template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant")                      \
+  template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl")                          \
+  template(jdk_vm_ci_hotspot_DirectHotSpotObjectConstantImpl,     "jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl")                    \
+  template(jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl,   "jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl")                  \
+  template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl")                       \
+  template(jdk_vm_ci_hotspot_HotSpotSentinelConstant,             "jdk/vm/ci/hotspot/HotSpotSentinelConstant")                            \
+  template(jdk_vm_ci_hotspot_HotSpotStackFrameReference,          "jdk/vm/ci/hotspot/HotSpotStackFrameReference")                         \
+  template(jdk_vm_ci_hotspot_HotSpotMetaData,                     "jdk/vm/ci/hotspot/HotSpotMetaData")                                    \
+  template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                                \
+  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                                \
+  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult")                    \
+  template(jdk_vm_ci_hotspot_VMField,                             "jdk/vm/ci/hotspot/VMField")                                            \
+  template(jdk_vm_ci_hotspot_VMFlag,                              "jdk/vm/ci/hotspot/VMFlag")                                             \
+  template(jdk_vm_ci_hotspot_VMIntrinsicMethod,                   "jdk/vm/ci/hotspot/VMIntrinsicMethod")                                  \
+  template(jdk_vm_ci_meta_ResolvedJavaMethod,                     "jdk/vm/ci/meta/ResolvedJavaMethod")                                    \
+  template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                                          \
+  template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                                     \
+  template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                                           \
+  template(jdk_vm_ci_meta_NullConstant,                           "jdk/vm/ci/meta/NullConstant")                                          \
+  template(jdk_vm_ci_meta_ExceptionHandler,                       "jdk/vm/ci/meta/ExceptionHandler")                                      \
+  template(jdk_vm_ci_meta_JavaKind,                               "jdk/vm/ci/meta/JavaKind")                                              \
+  template(jdk_vm_ci_meta_ValueKind,                              "jdk/vm/ci/meta/ValueKind")                                             \
+  template(jdk_vm_ci_meta_Value,                                  "jdk/vm/ci/meta/Value")                                                 \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            "jdk/vm/ci/meta/Assumptions$ConcreteSubtype")                           \
+  template(jdk_vm_ci_meta_Assumptions_LeafType,                   "jdk/vm/ci/meta/Assumptions$LeafType")                                  \
+  template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")                     \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")                            \
+  template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")                       \
+  template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                                          \
+  template(jdk_vm_ci_code_BytecodeFrame,                          "jdk/vm/ci/code/BytecodeFrame")                                         \
+  template(jdk_vm_ci_code_BytecodePosition,                       "jdk/vm/ci/code/BytecodePosition")                                      \
+  template(jdk_vm_ci_code_DebugInfo,                              "jdk/vm/ci/code/DebugInfo")                                             \
+  template(jdk_vm_ci_code_InstalledCode,                          "jdk/vm/ci/code/InstalledCode")                                         \
+  template(jdk_vm_ci_code_Location,                               "jdk/vm/ci/code/Location")                                              \
+  template(jdk_vm_ci_code_Register,                               "jdk/vm/ci/code/Register")                                              \
+  template(jdk_vm_ci_code_RegisterValue,                          "jdk/vm/ci/code/RegisterValue")                                         \
+  template(jdk_vm_ci_code_StackSlot,                              "jdk/vm/ci/code/StackSlot")                                             \
+  template(jdk_vm_ci_code_StackLockValue,                         "jdk/vm/ci/code/StackLockValue")                                        \
+  template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                                     \
+  template(jdk_vm_ci_code_VirtualObject,                          "jdk/vm/ci/code/VirtualObject")                                         \
+  template(jdk_vm_ci_code_RegisterSaveLayout,                     "jdk/vm/ci/code/RegisterSaveLayout")                                    \
+  template(jdk_vm_ci_code_InvalidInstalledCodeException,          "jdk/vm/ci/code/InvalidInstalledCodeException")                         \
+  template(jdk_vm_ci_code_site_Call,                              "jdk/vm/ci/code/site/Call")                                             \
+  template(jdk_vm_ci_code_site_ConstantReference,                 "jdk/vm/ci/code/site/ConstantReference")                                \
+  template(jdk_vm_ci_code_site_DataPatch,                         "jdk/vm/ci/code/site/DataPatch")                                        \
+  template(jdk_vm_ci_code_site_DataSectionReference,              "jdk/vm/ci/code/site/DataSectionReference")                             \
+  template(jdk_vm_ci_code_site_ExceptionHandler,                  "jdk/vm/ci/code/site/ExceptionHandler")                                 \
+  template(jdk_vm_ci_code_site_Mark,                              "jdk/vm/ci/code/site/Mark")                                             \
+  template(jdk_vm_ci_code_site_Infopoint,                         "jdk/vm/ci/code/site/Infopoint")                                        \
+  template(jdk_vm_ci_code_stack_InspectedFrameVisitor,            "jdk/vm/ci/code/stack/InspectedFrameVisitor")                           \
+  template(jdk_vm_ci_code_site_Site,                              "jdk/vm/ci/code/site/Site")                                             \
+  template(jdk_vm_ci_code_site_InfopointReason,                   "jdk/vm/ci/code/site/InfopointReason")                                  \
+  template(jdk_vm_ci_common_JVMCIError,                           "jdk/vm/ci/common/JVMCIError")                                          \
+                                                                                                                                          \
+  template(visitFrame_name,                                       "visitFrame")                                                           \
+  template(visitFrame_signature,                                  "(Ljdk/vm/ci/code/stack/InspectedFrame;)Ljava/lang/Object;")            \
+  template(compileMethod_name,                                    "compileMethod")                                                        \
   template(compileMethod_signature,                               "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \
-  template(fromMetaspace_name,                                    "fromMetaspace")                                         \
-  template(method_fromMetaspace_signature,                        "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")      \
-  template(constantPool_fromMetaspace_signature,                  "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;")            \
-  template(klass_fromMetaspace_signature,                         "(Ljava/lang/Class;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;")
+  template(encodeThrowable_name,                                  "encodeThrowable")                                                      \
+  template(encodeThrowable_signature,                             "(Ljava/lang/Throwable;)Ljava/lang/String;")                            \
+  template(decodeThrowable_name,                                  "decodeThrowable")                                                      \
+  template(decodeThrowable_signature,                             "(Ljava/lang/String;)Ljava/lang/Throwable;")                            \
+  template(fromMetaspace_name,                                    "fromMetaspace")                                                        \
+  template(method_fromMetaspace_signature,                        "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                     \
+  template(constantPool_fromMetaspace_signature,                  "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;")                           \
+  template(klass_fromMetaspace_signature,                         "(JLjava/lang/String;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
+  template(primitive_fromMetaspace_signature,                     "(Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;C)Ljdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType;") \
+  template(getRuntime_name,                                       "getRuntime")                                                           \
+  template(getRuntime_signature,                                  "()Ljdk/vm/ci/runtime/JVMCIRuntime;")                                   \
+  template(initializeRuntime_name,                                "initializeRuntime")                                                    \
+  do_alias(initializeRuntime_signature, getRuntime_signature)                                                                             \
+  template(runtime_name,                                          "runtime")                                                              \
+  template(runtime_signature,                                     "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;")                            \
+  template(getCompiler_name,                                      "getCompiler")                                                          \
+  template(getCompiler_signature,                                 "()Ljdk/vm/ci/runtime/JVMCICompiler;")                                  \
+  template(callToString_name,                                     "callToString")                                                         \
+  template(callToString_signature,                                "(Ljava/lang/Object;)Ljava/lang/String;")                               \
+  template(getName_name,                                          "getName")                                                              \
+  template(bootstrapFinished_name,                                "bootstrapFinished")                                                    \
+  template(forTypeChar_name,                                      "forTypeChar")                                                          \
+  template(forTypeChar_signature,                                 "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;")                               \
+  template(forFloat_name,                                         "forFloat")                                                             \
+  template(forFloat_signature,                                    "(F)Ljdk/vm/ci/meta/PrimitiveConstant;")                                \
+  template(forDouble_name,                                        "forDouble")                                                            \
+  template(forDouble_signature,                                   "(D)Ljdk/vm/ci/meta/PrimitiveConstant;")                                \
+  template(method_string_bool_long_signature,                     "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
+  template(initializeSavedProperties_name,                        "initializeSavedProperties")                                            \
+
 #endif
 
 #endif // SHARE_JVMCI_VMSYMBOLS_JVMCI_HPP
--- a/src/hotspot/share/memory/allocation.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/allocation.hpp	Fri May 03 14:59:32 2019 -0400
@@ -118,6 +118,7 @@
   f(mtCode,          "Code")        /* generated code                            */ \
   f(mtGC,            "GC")                                                          \
   f(mtCompiler,      "Compiler")                                                    \
+  f(mtJVMCI,         "JVMCI")                                                       \
   f(mtInternal,      "Internal")    /* memory used by VM, but does not belong to */ \
                                     /* any of above categories, and not used by  */ \
                                     /* NMT                                       */ \
--- a/src/hotspot/share/memory/metaspace.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/metaspace.cpp	Fri May 03 14:59:32 2019 -0400
@@ -841,7 +841,7 @@
 
 // Prints an ASCII representation of the given space.
 void MetaspaceUtils::print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype) {
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   const bool for_class = mdtype == Metaspace::ClassType ? true : false;
   VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list();
   if (vsl != NULL) {
@@ -906,7 +906,7 @@
 
 // Utils to check if a pointer or range is part of a committed metaspace region.
 metaspace::VirtualSpaceNode* MetaspaceUtils::find_enclosing_virtual_space(const void* p) {
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   VirtualSpaceNode* vsn = Metaspace::space_list()->find_enclosing_space(p);
   if (Metaspace::using_class_space() && vsn == NULL) {
     vsn = Metaspace::class_space_list()->find_enclosing_space(p);
@@ -1402,8 +1402,8 @@
 }
 
 void Metaspace::purge() {
-  MutexLockerEx cl(MetaspaceExpand_lock,
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock,
+                 Mutex::_no_safepoint_check_flag);
   purge(NonClassType);
   if (using_class_space()) {
     purge(ClassType);
@@ -1480,7 +1480,7 @@
     _class_vsm = new SpaceManager(Metaspace::ClassType, type, lock);
   }
 
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
 
   // Allocate chunk for metadata objects
   initialize_first_chunk(type, Metaspace::NonClassType);
@@ -1549,7 +1549,7 @@
 
   DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_external_deallocs));
 
-  MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
 
   if (is_class && Metaspace::using_class_space()) {
     class_vsm()->deallocate(ptr, word_size);
@@ -1589,7 +1589,7 @@
 }
 
 void ClassLoaderMetaspace::add_to_statistics(ClassLoaderMetaspaceStatistics* out) const {
-  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
   add_to_statistics_locked(out);
 }
 
@@ -1639,7 +1639,7 @@
 
   static void test_virtual_space_list_large_chunk() {
     VirtualSpaceList* vs_list = new VirtualSpaceList(os::vm_allocation_granularity());
-    MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
     // A size larger than VirtualSpaceSize (256k) and add one page to make it _not_ be
     // vm_allocation_granularity aligned on Windows.
     size_t large_size = (size_t)(2*256*K + (os::vm_page_size()/BytesPerWord));
--- a/src/hotspot/share/memory/metaspace/chunkManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/metaspace/chunkManager.cpp	Fri May 03 14:59:32 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
@@ -227,7 +227,7 @@
 
 #ifdef ASSERT
 void ChunkManager::verify(bool slow) const {
-  MutexLockerEx cl(MetaspaceExpand_lock,
+  MutexLocker cl(MetaspaceExpand_lock,
                      Mutex::_no_safepoint_check_flag);
   locked_verify(slow);
 }
@@ -630,7 +630,7 @@
 }
 
 void ChunkManager::collect_statistics(ChunkManagerStatistics* out) const {
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
     out->chunk_stats(i).add(num_free_chunks(i), size_free_chunks_in_bytes(i) / sizeof(MetaWord));
   }
--- a/src/hotspot/share/memory/metaspace/spaceManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/metaspace/spaceManager.cpp	Fri May 03 14:59:32 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
@@ -179,7 +179,7 @@
   assert(current_chunk() == NULL ||
          current_chunk()->allocate(word_size) == NULL,
          "Don't need to expand");
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
 
   if (log_is_enabled(Trace, gc, metaspace, freelist)) {
     size_t words_left = 0;
@@ -284,8 +284,7 @@
   // This call this->_lock which can't be done while holding MetaspaceExpand_lock
   DEBUG_ONLY(verify_metrics());
 
-  MutexLockerEx fcl(MetaspaceExpand_lock,
-                    Mutex::_no_safepoint_check_flag);
+  MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
 
   account_for_spacemanager_death();
 
@@ -402,7 +401,7 @@
 }
 
 MetaWord* SpaceManager::allocate(size_t word_size) {
-  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
   size_t raw_word_size = get_allocation_word_size(word_size);
   BlockFreelist* fl =  block_freelists();
   MetaWord* p = NULL;
@@ -498,7 +497,7 @@
 }
 
 void SpaceManager::add_to_statistics(SpaceManagerStatistics* out) const {
-  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
   add_to_statistics_locked(out);
 }
 
@@ -519,7 +518,7 @@
 }
 
 void SpaceManager::verify_metrics() const {
-  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
   verify_metrics_locked();
 }
 #endif // ASSERT
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp	Fri May 03 14:59:32 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
@@ -172,8 +172,7 @@
                                    _virtual_space_count(0),
                                    _envelope_lo((address)max_uintx),
                                    _envelope_hi(NULL) {
-  MutexLockerEx cl(MetaspaceExpand_lock,
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   create_new_virtual_space(word_size);
 }
 
@@ -186,8 +185,7 @@
                                    _virtual_space_count(0),
                                    _envelope_lo((address)max_uintx),
                                    _envelope_hi(NULL) {
-  MutexLockerEx cl(MetaspaceExpand_lock,
-                   Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   VirtualSpaceNode* class_entry = new VirtualSpaceNode(is_class(), rs);
   bool succeeded = class_entry->initialize();
   if (succeeded) {
--- a/src/hotspot/share/memory/universe.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/universe.cpp	Fri May 03 14:59:32 2019 -0400
@@ -663,11 +663,16 @@
 
   initialize_global_behaviours();
 
+  GCConfig::arguments()->initialize_heap_sizes();
+
   jint status = Universe::initialize_heap();
   if (status != JNI_OK) {
     return status;
   }
 
+  Universe::initialize_compressed_oops();
+  Universe::initialize_tlab();
+
   SystemDictionary::initialize_oop_storage();
 
   Metaspace::global_initialize();
@@ -725,9 +730,16 @@
   return JNI_OK;
 }
 
-CollectedHeap* Universe::create_heap() {
+jint Universe::initialize_heap() {
   assert(_collectedHeap == NULL, "Heap already created");
-  return GCConfig::arguments()->create_heap();
+  _collectedHeap = GCConfig::arguments()->create_heap();
+  jint status = _collectedHeap->initialize();
+
+  if (status == JNI_OK) {
+    log_info(gc)("Using %s", _collectedHeap->name());
+  }
+
+  return status;
 }
 
 // Choose the heap base address and oop encoding mode
@@ -737,17 +749,7 @@
 // ZeroBased - Use zero based compressed oops with encoding when
 //     NarrowOopHeapBaseMin + heap_size < 32Gb
 // HeapBased - Use compressed oops with heap base + encoding.
-
-jint Universe::initialize_heap() {
-  _collectedHeap = create_heap();
-  jint status = _collectedHeap->initialize();
-  if (status != JNI_OK) {
-    return status;
-  }
-  log_info(gc)("Using %s", _collectedHeap->name());
-
-  ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
-
+void Universe::initialize_compressed_oops() {
 #ifdef _LP64
   if (UseCompressedOops) {
     // Subtract a page because something can get allocated at heap base.
@@ -787,16 +789,15 @@
   assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
          Universe::narrow_oop_shift() == 0, "invalid value");
 #endif
+}
 
-  // We will never reach the CATCH below since Exceptions::_throw will cause
-  // the VM to exit if an exception is thrown during initialization
-
+void Universe::initialize_tlab() {
+  ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
   if (UseTLAB) {
     assert(Universe::heap()->supports_tlab_allocation(),
            "Should support thread-local allocation buffers");
     ThreadLocalAllocBuffer::startup_initialization();
   }
-  return JNI_OK;
 }
 
 void Universe::print_compressed_oops_mode(outputStream* st) {
@@ -1205,7 +1206,7 @@
   }
   if (should_verify_subset(Verify_CodeCache)) {
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     log_debug(gc, verify)("CodeCache");
     CodeCache::verify();
   }
--- a/src/hotspot/share/memory/universe.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/memory/universe.hpp	Fri May 03 14:59:32 2019 -0400
@@ -213,8 +213,9 @@
   static size_t _heap_capacity_at_last_gc;
   static size_t _heap_used_at_last_gc;
 
-  static CollectedHeap* create_heap();
   static jint initialize_heap();
+  static void initialize_compressed_oops();
+  static void initialize_tlab();
   static void initialize_basic_type_mirrors(TRAPS);
   static void fixup_mirrors(TRAPS);
 
--- a/src/hotspot/share/oops/constantPool.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/constantPool.cpp	Fri May 03 14:59:32 2019 -0400
@@ -30,6 +30,7 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "interpreter/bootstrapInfo.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/heapInspection.hpp"
@@ -909,9 +910,8 @@
 
   case JVM_CONSTANT_Dynamic:
     {
-      Klass* current_klass  = this_cp->pool_holder();
-      Symbol* constant_name = this_cp->uncached_name_ref_at(index);
-      Symbol* constant_type = this_cp->uncached_signature_ref_at(index);
+      // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop.
+      BootstrapInfo bootstrap_specifier(this_cp, index);
 
       // The initial step in resolving an unresolved symbolic reference to a
       // dynamically-computed constant is to resolve the symbolic reference to a
@@ -921,27 +921,18 @@
       // bootstrap method's CP index for the CONSTANT_MethodHandle_info. No need to
       // set a DynamicConstantInError here since any subsequent use of this
       // bootstrap method will encounter the resolution of MethodHandleInError.
-      oop bsm_info = this_cp->resolve_bootstrap_specifier_at(index, THREAD);
-      Exceptions::wrap_dynamic_exception(CHECK_NULL);
-      assert(bsm_info != NULL, "");
-      // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_Dynamic.
-      Handle bootstrap_specifier = Handle(THREAD, bsm_info);
-
-      // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop.
-      Handle value = SystemDictionary::link_dynamic_constant(current_klass,
-                                                             index,
-                                                             bootstrap_specifier,
-                                                             constant_name,
-                                                             constant_type,
-                                                             THREAD);
-      result_oop = value();
+      // Both the first, (resolution of the BSM and its static arguments), and the second tasks,
+      // (invocation of the BSM), of JVMS Section 5.4.3.6 occur within invoke_bootstrap_method()
+      // for the bootstrap_specifier created above.
+      SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD);
       Exceptions::wrap_dynamic_exception(THREAD);
       if (HAS_PENDING_EXCEPTION) {
         // Resolution failure of the dynamically-computed constant, save_and_throw_exception
         // will check for a LinkageError and store a DynamicConstantInError.
         save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
       }
-      BasicType type = FieldType::basic_type(constant_type);
+      result_oop = bootstrap_specifier.resolved_value()();
+      BasicType type = FieldType::basic_type(bootstrap_specifier.signature());
       if (!is_reference_type(type)) {
         // Make sure the primitive value is properly boxed.
         // This is a JDK responsibility.
@@ -961,6 +952,10 @@
           THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), fail);
         }
       }
+
+      if (TraceMethodHandles) {
+        bootstrap_specifier.print_msg_on(tty, "resolve_constant_at_impl");
+      }
       break;
     }
 
@@ -1102,119 +1097,6 @@
   return str;
 }
 
-
-oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) {
-  assert((this_cp->tag_at(index).is_invoke_dynamic() ||
-          this_cp->tag_at(index).is_dynamic_constant()), "Corrupted constant pool");
-  Handle bsm;
-  int argc;
-  {
-    // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&mtype], plus optional arguments
-    // JVM_CONSTANT_Dynamic is an ordered pair of [bootm, name&ftype], plus optional arguments
-    // In both cases, the bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
-    // It is accompanied by the optional arguments.
-    int bsm_index = this_cp->bootstrap_method_ref_index_at(index);
-    oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
-    if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) {
-      THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle");
-    }
-
-    // Extract the optional static arguments.
-    argc = this_cp->bootstrap_argument_count_at(index);
-
-    // if there are no static arguments, return the bsm by itself:
-    if (argc == 0 && UseBootstrapCallInfo < 2)  return bsm_oop;
-
-    bsm = Handle(THREAD, bsm_oop);
-  }
-
-  // We are going to return an ordered pair of {bsm, info}, using a 2-array.
-  objArrayHandle info;
-  {
-    objArrayOop info_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL);
-    info = objArrayHandle(THREAD, info_oop);
-  }
-
-  info->obj_at_put(0, bsm());
-
-  bool use_BSCI;
-  switch (UseBootstrapCallInfo) {
-  default: use_BSCI = true;  break;  // stress mode
-  case 0:  use_BSCI = false; break;  // stress mode
-  case 1:                            // normal mode
-    // If we were to support an alternative mode of BSM invocation,
-    // we'd convert to pull mode here if the BSM could be a candidate
-    // for that alternative mode.  We can't easily test for things
-    // like varargs here, but we can get away with approximate testing,
-    // since the JDK runtime will make up the difference either way.
-    // For now, exercise the pull-mode path if the BSM is of arity 2,
-    // or if there is a potential condy loop (see below).
-    oop mt_oop = java_lang_invoke_MethodHandle::type(bsm());
-    use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2);
-    break;
-  }
-
-  // Here's a reason to use BSCI even if it wasn't requested:
-  // If a condy uses a condy argument, we want to avoid infinite
-  // recursion (condy loops) in the C code.  It's OK in Java,
-  // because Java has stack overflow checking, so we punt
-  // potentially cyclic cases from C to Java.
-  if (!use_BSCI && this_cp->tag_at(index).is_dynamic_constant()) {
-    bool found_unresolved_condy = false;
-    for (int i = 0; i < argc; i++) {
-      int arg_index = this_cp->bootstrap_argument_index_at(index, i);
-      if (this_cp->tag_at(arg_index).is_dynamic_constant()) {
-        // potential recursion point condy -> condy
-        bool found_it = false;
-        this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL);
-        if (!found_it) { found_unresolved_condy = true; break; }
-      }
-    }
-    if (found_unresolved_condy)
-      use_BSCI = true;
-  }
-
-  const int SMALL_ARITY = 5;
-  if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
-    // If there are only a few arguments, and none of them need linking,
-    // push them, instead of asking the JDK runtime to turn around and
-    // pull them, saving a JVM/JDK transition in some simple cases.
-    bool all_resolved = true;
-    for (int i = 0; i < argc; i++) {
-      bool found_it = false;
-      int arg_index = this_cp->bootstrap_argument_index_at(index, i);
-      this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL);
-      if (!found_it) { all_resolved = false; break; }
-    }
-    if (all_resolved)
-      use_BSCI = false;
-  }
-
-  if (!use_BSCI) {
-    // return {bsm, {arg...}}; resolution of arguments is done immediately, before JDK code is called
-    objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_NULL);
-    info->obj_at_put(1, args_oop);   // may overwrite with args[0] below
-    objArrayHandle args(THREAD, args_oop);
-    copy_bootstrap_arguments_at_impl(this_cp, index, 0, argc, args, 0, true, Handle(), CHECK_NULL);
-    if (argc == 1) {
-      // try to discard the singleton array
-      oop arg_oop = args->obj_at(0);
-      if (arg_oop != NULL && !arg_oop->is_array()) {
-        // JVM treats arrays and nulls specially in this position,
-        // but other things are just single arguments
-        info->obj_at_put(1, arg_oop);
-      }
-    }
-  } else {
-    // return {bsm, {arg_count, pool_index}}; JDK code must pull the arguments as needed
-    typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL);
-    ints_oop->int_at_put(0, argc);
-    ints_oop->int_at_put(1, index);
-    info->obj_at_put(1, ints_oop);
-  }
-  return info();
-}
-
 void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
                                                     int start_arg, int end_arg,
                                                     objArrayHandle info, int pos,
@@ -1848,8 +1730,8 @@
 } // end compare_operand_to()
 
 // Search constant pool search_cp for a bootstrap specifier that matches
-// this constant pool's bootstrap specifier at pattern_i index.
-// Return the index of a matching bootstrap specifier or (-1) if there is no match.
+// this constant pool's bootstrap specifier data at pattern_i index.
+// Return the index of a matching bootstrap attribute record or (-1) if there is no match.
 int ConstantPool::find_matching_operand(int pattern_i,
                     const constantPoolHandle& search_cp, int search_len, TRAPS) {
   for (int i = 0; i < search_len; i++) {
@@ -1858,7 +1740,7 @@
       return i;
     }
   }
-  return -1;  // bootstrap specifier not found; return unused index (-1)
+  return -1;  // bootstrap specifier data not found; return unused index (-1)
 } // end find_matching_operand()
 
 
--- a/src/hotspot/share/oops/constantPool.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/constantPool.hpp	Fri May 03 14:59:32 2019 -0400
@@ -746,11 +746,6 @@
     return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, &found_it, THREAD);
   }
 
-  oop resolve_bootstrap_specifier_at(int index, TRAPS) {
-    constantPoolHandle h_this(THREAD, this);
-    return resolve_bootstrap_specifier_at_impl(h_this, index, THREAD);
-  }
-
   void copy_bootstrap_arguments_at(int index,
                                    int start_arg, int end_arg,
                                    objArrayHandle info, int pos,
@@ -871,7 +866,6 @@
 
   static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index,
                                       bool* status_return, TRAPS);
-  static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS);
   static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
                                                int start_arg, int end_arg,
                                                objArrayHandle info, int pos,
--- a/src/hotspot/share/oops/instanceKlass.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Fri May 03 14:59:32 2019 -0400
@@ -2187,7 +2187,7 @@
   for (int m = 0; m < methods()->length(); m++) {
     MethodData* mdo = methods()->at(m)->method_data();
     if (mdo != NULL) {
-      MutexLockerEx ml(SafepointSynchronize::is_at_safepoint() ? NULL : mdo->extra_data_lock());
+      MutexLocker ml(SafepointSynchronize::is_at_safepoint() ? NULL : mdo->extra_data_lock());
       mdo->clean_method_data(/*always_clean*/false);
     }
   }
@@ -2968,7 +2968,7 @@
   // only one compilation can be active
   {
     // This is a short non-blocking critical region, so the no safepoint check is ok.
-    MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
     assert(n->is_osr_method(), "wrong kind of nmethod");
     n->set_osr_link(osr_nmethods_head());
     set_osr_nmethods_head(n);
@@ -2993,7 +2993,7 @@
 // Remove osr nmethod from the list. Return true if found and removed.
 bool InstanceKlass::remove_osr_nmethod(nmethod* n) {
   // This is a short non-blocking critical region, so the no safepoint check is ok.
-  MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
   assert(n->is_osr_method(), "wrong kind of nmethod");
   nmethod* last = NULL;
   nmethod* cur  = osr_nmethods_head();
@@ -3037,7 +3037,7 @@
 
 int InstanceKlass::mark_osr_nmethods(const Method* m) {
   // This is a short non-blocking critical region, so the no safepoint check is ok.
-  MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
   nmethod* osr = osr_nmethods_head();
   int found = 0;
   while (osr != NULL) {
@@ -3053,7 +3053,7 @@
 
 nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const {
   // This is a short non-blocking critical region, so the no safepoint check is ok.
-  MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
   nmethod* osr = osr_nmethods_head();
   nmethod* best = NULL;
   while (osr != NULL) {
--- a/src/hotspot/share/oops/markOop.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/markOop.cpp	Fri May 03 14:59:32 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
@@ -37,9 +37,9 @@
     if (mon == NULL) {
       st->print("NULL (this should never be seen!)");
     } else {
-      st->print("{count=0x%08x,waiters=0x%08x"
+      st->print("{contentions=0x%08x,waiters=0x%08x"
                 ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
-                mon->count(), mon->waiters(), mon->recursions(),
+                mon->contentions(), mon->waiters(), mon->recursions(),
                 p2i(mon->owner()));
     }
   } else if (is_locked()) {
--- a/src/hotspot/share/oops/method.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/method.cpp	Fri May 03 14:59:32 2019 -0400
@@ -116,6 +116,11 @@
 void Method::deallocate_contents(ClassLoaderData* loader_data) {
   MetadataFactory::free_metadata(loader_data, constMethod());
   set_constMethod(NULL);
+#if INCLUDE_JVMCI
+  if (method_data()) {
+    FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
+  }
+#endif
   MetadataFactory::free_metadata(loader_data, method_data());
   set_method_data(NULL);
   MetadataFactory::free_metadata(loader_data, method_counters());
@@ -928,7 +933,7 @@
 
 // Revert to using the interpreter and clear out the nmethod
 void Method::clear_code(bool acquire_lock /* = true */) {
-  MutexLockerEx pl(acquire_lock ? Patching_lock : NULL, Mutex::_no_safepoint_check_flag);
+  MutexLocker pl(acquire_lock ? Patching_lock : NULL, Mutex::_no_safepoint_check_flag);
   // this may be NULL if c2i adapters have not been made yet
   // Only should happen at allocate time.
   if (adapter() == NULL) {
@@ -1161,7 +1166,7 @@
 
 // Install compiled code.  Instantly it can execute.
 void Method::set_code(const methodHandle& mh, CompiledMethod *code) {
-  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
   assert( code, "use clear_code to remove code" );
   assert( mh->check_code(), "" );
 
@@ -2064,7 +2069,7 @@
     // Have to add jmethod_ids() to class loader data thread-safely.
     // Also have to add the method to the list safely, which the cld lock
     // protects as well.
-    MutexLockerEx ml(cld->metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(cld->metaspace_lock(),  Mutex::_no_safepoint_check_flag);
     if (cld->jmethod_ids() == NULL) {
       cld->set_jmethod_ids(new JNIMethodBlock(capacity));
     } else {
@@ -2088,7 +2093,7 @@
     // Have to add jmethod_ids() to class loader data thread-safely.
     // Also have to add the method to the list safely, which the cld lock
     // protects as well.
-    MutexLockerEx ml(cld->metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(cld->metaspace_lock(),  Mutex::_no_safepoint_check_flag);
     if (cld->jmethod_ids() == NULL) {
       cld->set_jmethod_ids(new JNIMethodBlock());
     }
@@ -2382,7 +2387,7 @@
 }
 
 void Method::print_touched_methods(outputStream* out) {
-  MutexLockerEx ml(Thread::current()->is_VM_thread() ? NULL : TouchedMethodLog_lock);
+  MutexLocker ml(Thread::current()->is_VM_thread() ? NULL : TouchedMethodLog_lock);
   out->print_cr("# Method::print_touched_methods version 1");
   if (_touched_method_table) {
     for (int i = 0; i < TOUCHED_METHOD_TABLE_SIZE; i++) {
--- a/src/hotspot/share/oops/methodData.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/methodData.cpp	Fri May 03 14:59:32 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
@@ -846,6 +846,86 @@
   return false;
 }
 
+#if INCLUDE_JVMCI
+
+void* FailedSpeculation::operator new(size_t size, size_t fs_size) throw() {
+  return CHeapObj<mtCompiler>::operator new(fs_size, std::nothrow);
+}
+
+FailedSpeculation::FailedSpeculation(address speculation, int speculation_len) : _data_len(speculation_len), _next(NULL) {
+  memcpy(data(), speculation, speculation_len);
+}
+
+// A heuristic check to detect nmethods that outlive a failed speculations list.
+static void guarantee_failed_speculations_alive(nmethod* nm, FailedSpeculation** failed_speculations_address) {
+  jlong head = (jlong)(address) *failed_speculations_address;
+  if ((head & 0x1) == 0x1) {
+    stringStream st;
+    if (nm != NULL) {
+      st.print("%d", nm->compile_id());
+      Method* method = nm->method();
+      st.print_raw("{");
+      if (method != NULL) {
+        method->print_name(&st);
+      } else {
+        const char* jvmci_name = nm->jvmci_name();
+        if (jvmci_name != NULL) {
+          st.print_raw(jvmci_name);
+        }
+      }
+      st.print_raw("}");
+    } else {
+      st.print("<unknown>");
+    }
+    fatal("Adding to failed speculations list that appears to have been freed. Source: %s", st.as_string());
+  }
+}
+
+bool FailedSpeculation::add_failed_speculation(nmethod* nm, FailedSpeculation** failed_speculations_address, address speculation, int speculation_len) {
+  assert(failed_speculations_address != NULL, "must be");
+  size_t fs_size = sizeof(FailedSpeculation) + speculation_len;
+  FailedSpeculation* fs = new (fs_size) FailedSpeculation(speculation, speculation_len);
+  if (fs == NULL) {
+    // no memory -> ignore failed speculation
+    return false;
+  }
+
+  guarantee(is_aligned(fs, sizeof(FailedSpeculation*)), "FailedSpeculation objects must be pointer aligned");
+  guarantee_failed_speculations_alive(nm, failed_speculations_address);
+
+  FailedSpeculation** cursor = failed_speculations_address;
+  do {
+    if (*cursor == NULL) {
+      FailedSpeculation* old_fs = Atomic::cmpxchg(fs, cursor, (FailedSpeculation*) NULL);
+      if (old_fs == NULL) {
+        // Successfully appended fs to end of the list
+        return true;
+      }
+      cursor = old_fs->next_adr();
+    } else {
+      cursor = (*cursor)->next_adr();
+    }
+  } while (true);
+}
+
+void FailedSpeculation::free_failed_speculations(FailedSpeculation** failed_speculations_address) {
+  assert(failed_speculations_address != NULL, "must be");
+  FailedSpeculation* fs = *failed_speculations_address;
+  while (fs != NULL) {
+    FailedSpeculation* next = fs->next();
+    delete fs;
+    fs = next;
+  }
+
+  // Write an unaligned value to failed_speculations_address to denote
+  // that it is no longer a valid pointer. This is allows for the check
+  // in add_failed_speculation against adding to a freed failed
+  // speculations list.
+  long* head = (long*) failed_speculations_address;
+  (*head) = (*head) | 0x1;
+}
+#endif // INCLUDE_JVMCI
+
 int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) {
 #if INCLUDE_JVMCI
   if (ProfileTraps) {
@@ -1227,6 +1307,7 @@
 
 #if INCLUDE_JVMCI
   _jvmci_ir_size = 0;
+  _failed_speculations = NULL;
 #endif
 
 #if INCLUDE_RTM_OPT
--- a/src/hotspot/share/oops/methodData.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/oops/methodData.hpp	Fri May 03 14:59:32 2019 -0400
@@ -1949,6 +1949,42 @@
 };
 
 
+#if INCLUDE_JVMCI
+// Encapsulates an encoded speculation reason. These are linked together in
+// a list that is atomically appended to during deoptimization. Entries are
+// never removed from the list.
+// @see jdk.vm.ci.hotspot.HotSpotSpeculationLog.HotSpotSpeculationEncoding
+class FailedSpeculation: public CHeapObj<mtCompiler> {
+ private:
+  // The length of HotSpotSpeculationEncoding.toByteArray(). The data itself
+  // is an array embedded at the end of this object.
+  int   _data_len;
+
+  // Next entry in a linked list.
+  FailedSpeculation* _next;
+
+  FailedSpeculation(address data, int data_len);
+
+  FailedSpeculation** next_adr() { return &_next; }
+
+  // Placement new operator for inlining the speculation data into
+  // the FailedSpeculation object.
+  void* operator new(size_t size, size_t fs_size) throw();
+
+ public:
+  char* data()         { return (char*)(((address) this) + sizeof(FailedSpeculation)); }
+  int data_len() const { return _data_len; }
+  FailedSpeculation* next() const { return _next; }
+
+  // Atomically appends a speculation from nm to the list whose head is at (*failed_speculations_address).
+  // Returns false if the FailedSpeculation object could not be allocated.
+  static bool add_failed_speculation(nmethod* nm, FailedSpeculation** failed_speculations_address, address speculation, int speculation_len);
+
+  // Frees all entries in the linked list whose head is at (*failed_speculations_address).
+  static void free_failed_speculations(FailedSpeculation** failed_speculations_address);
+};
+#endif
+
 class MethodData : public Metadata {
   friend class VMStructs;
   friend class JVMCIVMStructs;
@@ -2030,7 +2066,8 @@
 
 #if INCLUDE_JVMCI
   // Support for HotSpotMethodData.setCompiledIRSize(int)
-  int               _jvmci_ir_size;
+  int                _jvmci_ir_size;
+  FailedSpeculation* _failed_speculations;
 #endif
 
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
@@ -2191,6 +2228,12 @@
   InvocationCounter* invocation_counter()     { return &_invocation_counter; }
   InvocationCounter* backedge_counter()       { return &_backedge_counter;   }
 
+#if INCLUDE_JVMCI
+  FailedSpeculation** get_failed_speculations_address() {
+    return &_failed_speculations;
+  }
+#endif
+
 #if INCLUDE_RTM_OPT
   int rtm_state() const {
     return _rtm_state;
--- a/src/hotspot/share/opto/chaitin.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/chaitin.cpp	Fri May 03 14:59:32 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
@@ -2084,9 +2084,7 @@
 // Dump a register name into a buffer.  Be intelligent if we get called
 // before allocation is complete.
 char *PhaseChaitin::dump_register( const Node *n, char *buf  ) const {
-  if( this == NULL ) {          // Not got anything?
-    sprintf(buf,"N%d",n->_idx); // Then use Node index
-  } else if( _node_regs ) {
+  if( _node_regs ) {
     // Post allocation, use direct mappings, no LRG info available
     print_reg( get_reg_first(n), this, buf );
   } else {
--- a/src/hotspot/share/opto/ifnode.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/ifnode.cpp	Fri May 03 14:59:32 2019 -0400
@@ -633,7 +633,7 @@
     if( din4->is_Call() &&      // Handle a slow-path call on either arm
         (din4 = din4->in(0)) )
       din4 = din4->in(0);
-    if( din3 == din4 && din3->is_If() )
+    if (din3 != NULL && din3 == din4 && din3->is_If()) // Regions not degraded to a copy
       return din3;              // Skip around diamonds
   }
 
--- a/src/hotspot/share/opto/loopTransform.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/loopTransform.cpp	Fri May 03 14:59:32 2019 -0400
@@ -45,13 +45,13 @@
 // Given an IfNode, return the loop-exiting projection or NULL if both
 // arms remain in the loop.
 Node *IdealLoopTree::is_loop_exit(Node *iff) const {
-  if( iff->outcnt() != 2 ) return NULL; // Ignore partially dead tests
+  if (iff->outcnt() != 2) return NULL;  // Ignore partially dead tests
   PhaseIdealLoop *phase = _phase;
   // Test is an IfNode, has 2 projections.  If BOTH are in the loop
   // we need loop unswitching instead of peeling.
-  if( !is_member(phase->get_loop( iff->raw_out(0) )) )
+  if (!is_member(phase->get_loop(iff->raw_out(0))))
     return iff->raw_out(0);
-  if( !is_member(phase->get_loop( iff->raw_out(1) )) )
+  if (!is_member(phase->get_loop(iff->raw_out(1))))
     return iff->raw_out(1);
   return NULL;
 }
@@ -63,7 +63,7 @@
 //------------------------------record_for_igvn----------------------------
 // Put loop body on igvn work list
 void IdealLoopTree::record_for_igvn() {
-  for( uint i = 0; i < _body.size(); i++ ) {
+  for (uint i = 0; i < _body.size(); i++) {
     Node *n = _body.at(i);
     _phase->_igvn._worklist.push(n);
   }
@@ -145,7 +145,9 @@
       Node *exit = is_loop_exit(iff);
       if (exit) {
         float exit_prob = iff->_prob;
-        if (exit->Opcode() == Op_IfFalse) exit_prob = 1.0 - exit_prob;
+        if (exit->Opcode() == Op_IfFalse) {
+          exit_prob = 1.0 - exit_prob;
+        }
         if (exit_prob > PROB_MIN) {
           float exit_cnt = iff->_fcnt * exit_prob;
           return exit_cnt;
@@ -202,7 +204,7 @@
     // Now compute a loop exit count
     float loop_exit_cnt = 0.0f;
     if (_child == NULL) {
-      for( uint i = 0; i < _body.size(); i++ ) {
+      for (uint i = 0; i < _body.size(); i++) {
         Node *n = _body[i];
         loop_exit_cnt += compute_profile_trip_cnt_helper(n);
       }
@@ -342,33 +344,48 @@
 //------------------------------policy_peeling---------------------------------
 // Return TRUE or FALSE if the loop should be peeled or not.  Peel if we can
 // make some loop-invariant test (usually a null-check) happen before the loop.
-bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
-  Node *test = ((IdealLoopTree*)this)->tail();
-  int  body_size = ((IdealLoopTree*)this)->_body.size();
+bool IdealLoopTree::policy_peeling(PhaseIdealLoop *phase) const {
+  IdealLoopTree *loop = (IdealLoopTree*)this;
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
+  uint body_size = loop->_body.size();
   // Peeling does loop cloning which can result in O(N^2) node construction
-  if( body_size > 255 /* Prevent overflow for large body_size */
-      || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) {
-    return false;           // too large to safely clone
+  if (body_size > 255) {
+    return false;   // Prevent overflow for large body size
+  }
+  uint estimate = body_size * body_size;
+  if (phase->exceeding_node_budget(estimate)) {
+    return false;   // Too large to safely clone
   }
 
   // check for vectorized loops, any peeling done was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false;
-
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->trip_count() == 1) {
-    return false;
+  if (_head->is_CountedLoop()) {
+    CountedLoopNode* cl = _head->as_CountedLoop();
+    if (cl->is_unroll_only() || cl->trip_count() == 1) {
+      return false;
+    }
   }
 
-  while( test != _head ) {      // Scan till run off top of loop
-    if( test->is_If() ) {       // Test?
+  Node* test = loop->tail();
+
+  while (test != _head) {       // Scan till run off top of loop
+    if (test->is_If()) {        // Test?
       Node *ctrl = phase->get_ctrl(test->in(1));
-      if (ctrl->is_top())
+      if (ctrl->is_top()) {
         return false;           // Found dead test on live IF?  No peeling!
+      }
       // Standard IF only has one input value to check for loop invariance
-      assert(test->Opcode() == Op_If || test->Opcode() == Op_CountedLoopEnd || test->Opcode() == Op_RangeCheck, "Check this code when new subtype is added");
+      assert(test->Opcode() == Op_If ||
+             test->Opcode() == Op_CountedLoopEnd ||
+             test->Opcode() == Op_RangeCheck,
+             "Check this code when new subtype is added");
       // Condition is not a member of this loop?
-      if( !is_member(phase->get_loop(ctrl)) &&
-          is_loop_exit(test) )
-        return true;            // Found reason to peel!
+      if (!is_member(phase->get_loop(ctrl)) && is_loop_exit(test)) {
+        // Found reason to peel!
+        return phase->may_require_nodes(estimate);
+      }
     }
     // Walk up dominators to loop _head looking for test which is
     // executed on every path thru loop.
@@ -381,27 +398,27 @@
 // If we got the effect of peeling, either by actually peeling or by making
 // a pre-loop which must execute at least once, we can remove all
 // loop-invariant dominated tests in the main body.
-void PhaseIdealLoop::peeled_dom_test_elim( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::peeled_dom_test_elim(IdealLoopTree *loop, Node_List &old_new) {
   bool progress = true;
-  while( progress ) {
+  while (progress) {
     progress = false;           // Reset for next iteration
     Node *prev = loop->_head->in(LoopNode::LoopBackControl);//loop->tail();
     Node *test = prev->in(0);
-    while( test != loop->_head ) { // Scan till run off top of loop
+    while (test != loop->_head) { // Scan till run off top of loop
 
       int p_op = prev->Opcode();
-      if( (p_op == Op_IfFalse || p_op == Op_IfTrue) &&
+      if ((p_op == Op_IfFalse || p_op == Op_IfTrue) &&
           test->is_If() &&      // Test?
           !test->in(1)->is_Con() && // And not already obvious?
           // Condition is not a member of this loop?
           !loop->is_member(get_loop(get_ctrl(test->in(1))))){
         // Walk loop body looking for instances of this test
-        for( uint i = 0; i < loop->_body.size(); i++ ) {
+        for (uint i = 0; i < loop->_body.size(); i++) {
           Node *n = loop->_body.at(i);
-          if( n->is_If() && n->in(1) == test->in(1) /*&& n != loop->tail()->in(0)*/ ) {
+          if (n->is_If() && n->in(1) == test->in(1) /*&& n != loop->tail()->in(0)*/) {
             // IfNode was dominated by version in peeled loop body
             progress = true;
-            dominated_by( old_new[prev->_idx], n );
+            dominated_by(old_new[prev->_idx], n);
           }
         }
       }
@@ -409,7 +426,7 @@
       test = idom(test);
     } // End of scan tests in loop
 
-  } // End of while( progress )
+  } // End of while (progress)
 }
 
 //------------------------------do_peeling-------------------------------------
@@ -550,7 +567,7 @@
 //              v
 //             exit
 //
-void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {
 
   C->set_major_progress();
   // Peeling a 'main' loop in a pre/main/post situation obfuscates the
@@ -599,7 +616,7 @@
     Node* old = head->fast_out(j);
     if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) {
       Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
-      if (!new_exit_value )     // Backedge value is ALSO loop invariant?
+      if (!new_exit_value)     // Backedge value is ALSO loop invariant?
         // Then loop body backedge value remains the same.
         new_exit_value = old->in(LoopNode::LoopBackControl);
       _igvn.hash_delete(old);
@@ -628,8 +645,9 @@
   for (uint j3 = 0; j3 < loop->_body.size(); j3++) {
     Node *old = loop->_body.at(j3);
     Node *nnn = old_new[old->_idx];
-    if (!has_ctrl(nnn))
+    if (!has_ctrl(nnn)) {
       set_idom(nnn, idom(nnn), dd-1);
+    }
   }
 
   // Now force out all loop-invariant dominating tests.  The optimizer
@@ -644,12 +662,12 @@
 //------------------------------policy_maximally_unroll------------------------
 // Calculate exact loop trip count and return true if loop can be maximally
 // unrolled.
-bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop *phase) const {
   CountedLoopNode *cl = _head->as_CountedLoop();
   assert(cl->is_normal_loop(), "");
-  if (!cl->is_valid_counted_loop())
+  if (!cl->is_valid_counted_loop()) {
     return false; // Malformed counted loop
-
+  }
   if (!cl->has_exact_trip_count()) {
     // Trip count is not exact.
     return false;
@@ -660,31 +678,36 @@
   assert(trip_count > 1, "one iteration loop should be optimized out already");
   assert(trip_count < max_juint, "exact trip_count should be less than max_uint.");
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // Real policy: if we maximally unroll, does it get too big?
   // Allow the unrolled mess to get larger than standard loop
   // size.  After all, it will no longer be a loop.
   uint body_size    = _body.size();
   uint unroll_limit = (uint)LoopUnrollLimit * 4;
-  assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
+  assert((intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
   if (trip_count > unroll_limit || body_size > unroll_limit) {
     return false;
   }
 
-  // Fully unroll a loop with few iterations regardless next
-  // conditions since following loop optimizations will split
-  // such loop anyway (pre-main-post).
-  if (trip_count <= 3)
-    return true;
-
   // Take into account that after unroll conjoined heads and tails will fold,
   // otherwise policy_unroll() may allow more unrolling than max unrolling.
-  uint new_body_size = EMPTY_LOOP_SIZE + (body_size - EMPTY_LOOP_SIZE) * trip_count;
-  uint tst_body_size = (new_body_size - EMPTY_LOOP_SIZE) / trip_count + EMPTY_LOOP_SIZE;
-  if (body_size != tst_body_size) // Check for int overflow
+  uint new_body_size = est_loop_clone_sz(trip_count, body_size - EMPTY_LOOP_SIZE);
+
+  if (new_body_size == UINT_MAX) { // Check for bad estimate (overflow).
     return false;
+  }
+
+  // Fully unroll a loop with few iterations regardless next conditions since
+  // following loop optimizations will split such loop anyway (pre-main-post).
+  if (trip_count <= 3) {
+    return phase->may_require_nodes(new_body_size);
+  }
+
   if (new_body_size > unroll_limit ||
       // Unrolling can result in a large amount of node construction
-      new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) {
+      phase->exceeding_node_budget(new_body_size)) {
     return false;
   }
 
@@ -714,38 +737,43 @@
     } // switch
   }
 
-  return true; // Do maximally unroll
+  return phase->may_require_nodes(new_body_size);
 }
 
 
 //------------------------------policy_unroll----------------------------------
-// Return TRUE or FALSE if the loop should be unrolled or not.  Unroll if
-// the loop is a CountedLoop and the body is small enough.
+// Return TRUE or FALSE if the loop should be unrolled or not.  Unroll if the
+// loop is a CountedLoop and the body is small enough.
 bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) {
 
   CountedLoopNode *cl = _head->as_CountedLoop();
   assert(cl->is_normal_loop() || cl->is_main_loop(), "");
 
-  if (!cl->is_valid_counted_loop())
+  if (!cl->is_valid_counted_loop()) {
     return false; // Malformed counted loop
+  }
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
 
   // Protect against over-unrolling.
   // After split at least one iteration will be executed in pre-loop.
-  if (cl->trip_count() <= (uint)(cl->is_normal_loop() ? 2 : 1)) return false;
-
-  _local_loop_unroll_limit = LoopUnrollLimit;
+  if (cl->trip_count() <= (cl->is_normal_loop() ? 2u : 1u)) {
+    return false;
+  }
+  _local_loop_unroll_limit  = LoopUnrollLimit;
   _local_loop_unroll_factor = 4;
-  int future_unroll_ct = cl->unrolled_count() * 2;
+  int future_unroll_cnt = cl->unrolled_count() * 2;
   if (!cl->is_vectorized_loop()) {
-    if (future_unroll_ct > LoopMaxUnroll) return false;
+    if (future_unroll_cnt > LoopMaxUnroll) return false;
   } else {
     // obey user constraints on vector mapped loops with additional unrolling applied
     int unroll_constraint = (cl->slp_max_unroll()) ? cl->slp_max_unroll() : 1;
-    if ((future_unroll_ct / unroll_constraint) > LoopMaxUnroll) return false;
+    if ((future_unroll_cnt / unroll_constraint) > LoopMaxUnroll) return false;
   }
 
   // Check for initial stride being a small enough constant
-  if (abs(cl->stride_con()) > (1<<2)*future_unroll_ct) return false;
+  if (abs(cl->stride_con()) > (1<<2)*future_unroll_cnt) return false;
 
   // Don't unroll if the next round of unrolling would push us
   // over the expected trip count of the loop.  One is subtracted
@@ -753,8 +781,8 @@
   // executes 1 iteration.
   if (UnrollLimitForProfileCheck > 0 &&
       cl->profile_trip_cnt() != COUNT_UNKNOWN &&
-      future_unroll_ct        > UnrollLimitForProfileCheck &&
-      (float)future_unroll_ct > cl->profile_trip_cnt() - 1.0) {
+      future_unroll_cnt        > UnrollLimitForProfileCheck &&
+      (float)future_unroll_cnt > cl->profile_trip_cnt() - 1.0) {
     return false;
   }
 
@@ -763,8 +791,8 @@
   //   and rounds of "unroll,optimize" are not making significant progress
   //   Progress defined as current size less than 20% larger than previous size.
   if (UseSuperWord && cl->node_count_before_unroll() > 0 &&
-      future_unroll_ct > LoopUnrollMin &&
-      (future_unroll_ct - 1) * (100 / LoopPercentProfileLimit) > cl->profile_trip_cnt() &&
+      future_unroll_cnt > LoopUnrollMin &&
+      (future_unroll_cnt - 1) * (100 / LoopPercentProfileLimit) > cl->profile_trip_cnt() &&
       1.2 * cl->node_count_before_unroll() < (double)_body.size()) {
     return false;
   }
@@ -848,8 +876,8 @@
     if (LoopMaxUnroll > _local_loop_unroll_factor) {
       // Once policy_slp_analysis succeeds, mark the loop with the
       // maximal unroll factor so that we minimize analysis passes
-      if (future_unroll_ct >= _local_loop_unroll_factor) {
-        policy_unroll_slp_analysis(cl, phase, future_unroll_ct);
+      if (future_unroll_cnt >= _local_loop_unroll_factor) {
+        policy_unroll_slp_analysis(cl, phase, future_unroll_cnt);
       }
     }
   }
@@ -858,32 +886,40 @@
   if ((LoopMaxUnroll < slp_max_unroll_factor) && FLAG_IS_DEFAULT(LoopMaxUnroll) && UseSubwordForMaxVector) {
     LoopMaxUnroll = slp_max_unroll_factor;
   }
+
+  uint estimate = est_loop_clone_sz(2, body_size);
+
   if (cl->has_passed_slp()) {
-    if (slp_max_unroll_factor >= future_unroll_ct) return true;
-    // Normal case: loop too big
-    return false;
+    if (slp_max_unroll_factor >= future_unroll_cnt) {
+      return phase->may_require_nodes(estimate);
+    }
+    return false; // Loop too big.
   }
 
   // Check for being too big
   if (body_size > (uint)_local_loop_unroll_limit) {
-    if ((cl->is_subword_loop() || xors_in_loop >= 4) && body_size < (uint)LoopUnrollLimit * 4) {
-      return true;
+    if ((cl->is_subword_loop() || xors_in_loop >= 4) && body_size < 4u * LoopUnrollLimit) {
+      return phase->may_require_nodes(estimate);
     }
-    // Normal case: loop too big
-    return false;
+    return false; // Loop too big.
   }
 
-  if (cl->do_unroll_only()) {
+  if (cl->is_unroll_only()) {
     if (TraceSuperWordLoopUnrollAnalysis) {
-      tty->print_cr("policy_unroll passed vector loop(vlen=%d,factor = %d)\n", slp_max_unroll_factor, future_unroll_ct);
+      tty->print_cr("policy_unroll passed vector loop(vlen=%d, factor=%d)\n",
+                    slp_max_unroll_factor, future_unroll_cnt);
     }
   }
 
   // Unroll once!  (Each trip will soon do double iterations)
-  return true;
+  return phase->may_require_nodes(estimate);
 }
 
-void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_ct) {
+void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_cnt) {
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // Enable this functionality target by target as needed
   if (SuperWordLoopUnrollAnalysis) {
     if (!cl->was_slp_analyzed()) {
@@ -898,7 +934,7 @@
 
     if (cl->has_passed_slp()) {
       int slp_max_unroll_factor = cl->slp_max_unroll();
-      if (slp_max_unroll_factor >= future_unroll_ct) {
+      if (slp_max_unroll_factor >= future_unroll_cnt) {
         int new_limit = cl->node_count_before_unroll() * slp_max_unroll_factor;
         if (new_limit > LoopUnrollLimit) {
           if (TraceSuperWordLoopUnrollAnalysis) {
@@ -917,16 +953,19 @@
 // aligned in a loop (unless the VM guarantees mutual alignment).  Note that
 // if we vectorize short memory ops into longer memory ops, we may want to
 // increase alignment.
-bool IdealLoopTree::policy_align( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_align(PhaseIdealLoop *phase) const {
   return false;
 }
 
 //------------------------------policy_range_check-----------------------------
 // Return TRUE or FALSE if the loop should be range-check-eliminated.
 // Actually we do iteration-splitting, a more powerful form of RCE.
-bool IdealLoopTree::policy_range_check( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_range_check(PhaseIdealLoop *phase) const {
   if (!RangeCheckElimination) return false;
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   CountedLoopNode *cl = _head->as_CountedLoop();
   // If we unrolled with no intention of doing RCE and we later
   // changed our minds, we got no pre-loop.  Either we need to
@@ -935,7 +974,7 @@
   Node *trip_counter = cl->phi();
 
   // check for vectorized loops, some opts are no longer needed
-  if (cl->do_unroll_only()) return false;
+  if (cl->is_unroll_only()) return false;
 
   // Check loop body for tests of trip-counter plus loop-invariant vs
   // loop-invariant.
@@ -946,38 +985,45 @@
 
       // Comparing trip+off vs limit
       Node *bol = iff->in(1);
-      if (bol->req() != 2) continue; // dead constant test
+      if (bol->req() != 2) {
+        continue; // dead constant test
+      }
       if (!bol->is_Bool()) {
         assert(bol->Opcode() == Op_Conv2B, "predicate check only");
         continue;
       }
-      if (bol->as_Bool()->_test._test == BoolTest::ne)
+      if (bol->as_Bool()->_test._test == BoolTest::ne) {
         continue; // not RC
-
+      }
       Node *cmp = bol->in(1);
       Node *rc_exp = cmp->in(1);
       Node *limit = cmp->in(2);
 
       Node *limit_c = phase->get_ctrl(limit);
-      if( limit_c == phase->C->top() )
+      if (limit_c == phase->C->top()) {
         return false;           // Found dead test on live IF?  No RCE!
-      if( is_member(phase->get_loop(limit_c) ) ) {
+      }
+      if (is_member(phase->get_loop(limit_c))) {
         // Compare might have operands swapped; commute them
         rc_exp = cmp->in(2);
         limit  = cmp->in(1);
         limit_c = phase->get_ctrl(limit);
-        if( is_member(phase->get_loop(limit_c) ) )
+        if (is_member(phase->get_loop(limit_c))) {
           continue;             // Both inputs are loop varying; cannot RCE
+        }
       }
 
       if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL)) {
         continue;
       }
-      // Yeah!  Found a test like 'trip+off vs limit'
-      // Test is an IfNode, has 2 projections.  If BOTH are in the loop
-      // we need loop unswitching instead of iteration splitting.
-      if( is_loop_exit(iff) )
-        return true;            // Found reason to split iterations
+      // Found a test like 'trip+off vs  limit'.  Test is an IfNode, has two
+      // (2) projections.  If BOTH are in  the loop we need loop unswitching
+      // instead of iteration splitting.
+      if (is_loop_exit(iff)) {
+        // Found valid reason to split iterations (if there is room).
+        // NOTE: Usually a gross overestimate.
+        return phase->may_require_nodes(est_loop_clone_sz(2, _body.size()));
+      }
     } // End of is IF
   }
 
@@ -987,14 +1033,21 @@
 //------------------------------policy_peel_only-------------------------------
 // Return TRUE or FALSE if the loop should NEVER be RCE'd or aligned.  Useful
 // for unrolling loops with NO array accesses.
-bool IdealLoopTree::policy_peel_only( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_peel_only(PhaseIdealLoop *phase) const {
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // check for vectorized loops, any peeling done was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false;
-
-  for( uint i = 0; i < _body.size(); i++ )
-    if( _body[i]->is_Mem() )
+  if (_head->is_CountedLoop() && _head->as_CountedLoop()->is_unroll_only()) {
+    return false;
+  }
+
+  for (uint i = 0; i < _body.size(); i++) {
+    if (_body[i]->is_Mem()) {
       return false;
-
+    }
+  }
   // No memory accesses at all!
   return true;
 }
@@ -1002,33 +1055,31 @@
 //------------------------------clone_up_backedge_goo--------------------------
 // If Node n lives in the back_ctrl block and cannot float, we clone a private
 // version of n in preheader_ctrl block and return that, otherwise return n.
-Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones ) {
-  if( get_ctrl(n) != back_ctrl ) return n;
+Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones) {
+  if (get_ctrl(n) != back_ctrl) return n;
 
   // Only visit once
   if (visited.test_set(n->_idx)) {
     Node *x = clones.find(n->_idx);
-    if (x != NULL)
-      return x;
-    return n;
+    return (x != NULL) ? x : n;
   }
 
   Node *x = NULL;               // If required, a clone of 'n'
   // Check for 'n' being pinned in the backedge.
-  if( n->in(0) && n->in(0) == back_ctrl ) {
+  if (n->in(0) && n->in(0) == back_ctrl) {
     assert(clones.find(n->_idx) == NULL, "dead loop");
     x = n->clone();             // Clone a copy of 'n' to preheader
     clones.push(x, n->_idx);
-    x->set_req( 0, preheader_ctrl ); // Fix x's control input to preheader
+    x->set_req(0, preheader_ctrl); // Fix x's control input to preheader
   }
 
   // Recursive fixup any other input edges into x.
   // If there are no changes we can just return 'n', otherwise
   // we need to clone a private copy and change it.
-  for( uint i = 1; i < n->req(); i++ ) {
-    Node *g = clone_up_backedge_goo( back_ctrl, preheader_ctrl, n->in(i), visited, clones );
-    if( g != n->in(i) ) {
-      if( !x ) {
+  for (uint i = 1; i < n->req(); i++) {
+    Node *g = clone_up_backedge_goo(back_ctrl, preheader_ctrl, n->in(i), visited, clones);
+    if (g != n->in(i)) {
+      if (!x) {
         assert(clones.find(n->_idx) == NULL, "dead loop");
         x = n->clone();
         clones.push(x, n->_idx);
@@ -1036,11 +1087,11 @@
       x->set_req(i, g);
     }
   }
-  if( x ) {                     // x can legally float to pre-header location
-    register_new_node( x, preheader_ctrl );
+  if (x) {                     // x can legally float to pre-header location
+    register_new_node(x, preheader_ctrl);
     return x;
   } else {                      // raise n to cover LCA of uses
-    set_ctrl( n, find_non_split_ctrl(back_ctrl->in(0)) );
+    set_ctrl(n, find_non_split_ctrl(back_ctrl->in(0)));
   }
   return n;
 }
@@ -1244,7 +1295,7 @@
 // Insert pre and post loops.  If peel_only is set, the pre-loop can not have
 // more iterations added.  It acts as a 'peel' only, no lower-bound RCE, no
 // alignment.  Useful to unroll loops that do no array accesses.
-void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ) {
+void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_new, bool peel_only) {
 
 #ifndef PRODUCT
   if (TraceLoopOpts) {
@@ -1259,9 +1310,9 @@
 
   // Find common pieces of the loop being guarded with pre & post loops
   CountedLoopNode *main_head = loop->_head->as_CountedLoop();
-  assert( main_head->is_normal_loop(), "" );
+  assert(main_head->is_normal_loop(), "");
   CountedLoopEndNode *main_end = main_head->loopexit();
-  assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
+  assert(main_end->outcnt() == 2, "1 true, 1 false path only");
 
   Node *pre_header= main_head->in(LoopNode::EntryControl);
   Node *init      = main_head->init_trip();
@@ -1273,13 +1324,13 @@
 
   // Need only 1 user of 'bol' because I will be hacking the loop bounds.
   Node *bol = main_end->in(CountedLoopEndNode::TestValue);
-  if( bol->outcnt() != 1 ) {
+  if (bol->outcnt() != 1) {
     bol = bol->clone();
     register_new_node(bol,main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, bol);
   }
   // Need only 1 user of 'cmp' because I will be hacking the loop bounds.
-  if( cmp->outcnt() != 1 ) {
+  if (cmp->outcnt() != 1) {
     cmp = cmp->clone();
     register_new_node(cmp,main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(bol, 1, cmp);
@@ -1314,9 +1365,9 @@
 
   // Find the pre-loop normal exit.
   Node* pre_exit = pre_end->proj_out(false);
-  assert( pre_exit->Opcode() == Op_IfFalse, "" );
+  assert(pre_exit->Opcode() == Op_IfFalse, "");
   IfFalseNode *new_pre_exit = new IfFalseNode(pre_end);
-  _igvn.register_new_node_with_optimizer( new_pre_exit );
+  _igvn.register_new_node_with_optimizer(new_pre_exit);
   set_idom(new_pre_exit, pre_end, dd_main_head);
   set_loop(new_pre_exit, outer_loop->_parent);
 
@@ -1325,26 +1376,26 @@
   // zero-trip guard will become the minimum-trip guard when we unroll
   // the main-loop.
   Node *min_opaq = new Opaque1Node(C, limit);
-  Node *min_cmp  = new CmpINode( pre_incr, min_opaq );
-  Node *min_bol  = new BoolNode( min_cmp, b_test );
-  register_new_node( min_opaq, new_pre_exit );
-  register_new_node( min_cmp , new_pre_exit );
-  register_new_node( min_bol , new_pre_exit );
+  Node *min_cmp  = new CmpINode(pre_incr, min_opaq);
+  Node *min_bol  = new BoolNode(min_cmp, b_test);
+  register_new_node(min_opaq, new_pre_exit);
+  register_new_node(min_cmp , new_pre_exit);
+  register_new_node(min_bol , new_pre_exit);
 
   // Build the IfNode (assume the main-loop is executed always).
-  IfNode *min_iff = new IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN );
-  _igvn.register_new_node_with_optimizer( min_iff );
+  IfNode *min_iff = new IfNode(new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN);
+  _igvn.register_new_node_with_optimizer(min_iff);
   set_idom(min_iff, new_pre_exit, dd_main_head);
   set_loop(min_iff, outer_loop->_parent);
 
   // Plug in the false-path, taken if we need to skip main-loop
-  _igvn.hash_delete( pre_exit );
+  _igvn.hash_delete(pre_exit);
   pre_exit->set_req(0, min_iff);
   set_idom(pre_exit, min_iff, dd_main_head);
   set_idom(pre_exit->unique_ctrl_out(), min_iff, dd_main_head);
   // Make the true-path, must enter the main loop
-  Node *min_taken = new IfTrueNode( min_iff );
-  _igvn.register_new_node_with_optimizer( min_taken );
+  Node *min_taken = new IfTrueNode(min_iff);
+  _igvn.register_new_node_with_optimizer(min_taken);
   set_idom(min_taken, min_iff, dd_main_head);
   set_loop(min_taken, outer_loop->_parent);
   // Plug in the true path
@@ -1359,14 +1410,14 @@
   // fall-out values of the pre-loop.
   for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) {
     Node* main_phi = main_head->fast_out(i2);
-    if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) {
+    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0) {
       Node *pre_phi = old_new[main_phi->_idx];
       Node *fallpre  = clone_up_backedge_goo(pre_head->back_control(),
                                              main_head->skip_strip_mined()->in(LoopNode::EntryControl),
                                              pre_phi->in(LoopNode::LoopBackControl),
                                              visited, clones);
       _igvn.hash_delete(main_phi);
-      main_phi->set_req( LoopNode::EntryControl, fallpre );
+      main_phi->set_req(LoopNode::EntryControl, fallpre);
     }
   }
 
@@ -1381,7 +1432,7 @@
   // dependencies.
 
   // CastII for the main loop:
-  Node* castii = cast_incr_before_loop( pre_incr, min_taken, main_head );
+  Node* castii = cast_incr_before_loop(pre_incr, min_taken, main_head);
   assert(castii != NULL, "no castII inserted");
   Node* opaque_castii = new Opaque1Node(C, castii);
   register_new_node(opaque_castii, outer_main_head->in(LoopNode::EntryControl));
@@ -1390,18 +1441,18 @@
   // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
   // RCE and alignment may change this later.
   Node *cmp_end = pre_end->cmp_node();
-  assert( cmp_end->in(2) == limit, "" );
-  Node *pre_limit = new AddINode( init, stride );
+  assert(cmp_end->in(2) == limit, "");
+  Node *pre_limit = new AddINode(init, stride);
 
   // Save the original loop limit in this Opaque1 node for
   // use by range check elimination.
   Node *pre_opaq  = new Opaque1Node(C, pre_limit, limit);
 
-  register_new_node( pre_limit, pre_head->in(0) );
-  register_new_node( pre_opaq , pre_head->in(0) );
+  register_new_node(pre_limit, pre_head->in(0));
+  register_new_node(pre_opaq , pre_head->in(0));
 
   // Since no other users of pre-loop compare, I can hack limit directly
-  assert( cmp_end->outcnt() == 1, "no other users" );
+  assert(cmp_end->outcnt() == 1, "no other users");
   _igvn.hash_delete(cmp_end);
   cmp_end->set_req(2, peel_only ? pre_limit : pre_opaq);
 
@@ -1421,24 +1472,26 @@
     // Modify pre loop end condition
     Node* pre_bol = pre_end->in(CountedLoopEndNode::TestValue)->as_Bool();
     BoolNode* new_bol0 = new BoolNode(pre_bol->in(1), new_test);
-    register_new_node( new_bol0, pre_head->in(0) );
+    register_new_node(new_bol0, pre_head->in(0));
     _igvn.replace_input_of(pre_end, CountedLoopEndNode::TestValue, new_bol0);
     // Modify main loop guard condition
     assert(min_iff->in(CountedLoopEndNode::TestValue) == min_bol, "guard okay");
     BoolNode* new_bol1 = new BoolNode(min_bol->in(1), new_test);
-    register_new_node( new_bol1, new_pre_exit );
+    register_new_node(new_bol1, new_pre_exit);
     _igvn.hash_delete(min_iff);
     min_iff->set_req(CountedLoopEndNode::TestValue, new_bol1);
     // Modify main loop end condition
     BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool();
     BoolNode* new_bol2 = new BoolNode(main_bol->in(1), new_test);
-    register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) );
+    register_new_node(new_bol2, main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, new_bol2);
   }
 
   // Flag main loop
   main_head->set_main_loop();
-  if( peel_only ) main_head->set_main_no_pre_loop();
+  if (peel_only) {
+    main_head->set_main_no_pre_loop();
+  }
 
   // Subtract a trip count for the pre-loop.
   main_head->set_trip_count(main_head->trip_count() - 1);
@@ -1457,8 +1510,9 @@
 
 //------------------------------insert_vector_post_loop------------------------
 // Insert a copy of the atomic unrolled vectorized main loop as a post loop,
-// unroll_policy has already informed us that more unrolling is about to happen to
-// the main loop.  The resultant post loop will serve as a vectorized drain loop.
+// unroll_policy has  already informed  us that more  unrolling is  about to
+// happen  to the  main  loop.  The  resultant  post loop  will  serve as  a
+// vectorized drain loop.
 void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old_new) {
   if (!loop->_head->is_CountedLoop()) return;
 
@@ -1467,6 +1521,9 @@
   // only process vectorized main loops
   if (!cl->is_vectorized_loop() || !cl->is_main_loop()) return;
 
+  if (!may_require_nodes(est_loop_clone_sz(2, loop->_body.size()))) {
+    return;
+  }
   int slp_max_unroll_factor = cl->slp_max_unroll();
   int cur_unroll = cl->unrolled_count();
 
@@ -1638,7 +1695,7 @@
   // fall-out values of the main-loop.
   for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) {
     Node* main_phi = main_head->fast_out(i);
-    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() >0) {
+    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0) {
       Node *cur_phi = old_new[main_phi->_idx];
       Node *fallnew = clone_up_backedge_goo(main_head->back_control(),
                                             post_head->init_control(),
@@ -1710,7 +1767,7 @@
 
 //------------------------------do_unroll--------------------------------------
 // Unroll the loop body one step - make each trip do 2 iterations.
-void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip ) {
+void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
   assert(LoopUnrollLimit, "");
   CountedLoopNode *loop_head = loop->_head->as_CountedLoop();
   CountedLoopEndNode *loop_end = loop_head->loopexit();
@@ -1733,8 +1790,8 @@
     Node_List rpo_list;
     VectorSet visited(arena);
     visited.set(loop_head->_idx);
-    rpo( loop_head, stack, visited, rpo_list );
-    dump(loop, rpo_list.size(), rpo_list );
+    rpo(loop_head, stack, visited, rpo_list);
+    dump(loop, rpo_list.size(), rpo_list);
   }
 #endif
 
@@ -1811,7 +1868,8 @@
     // Verify that policy_unroll result is still valid.
     const TypeInt* limit_type = _igvn.type(limit)->is_int();
     assert(stride_con > 0 && ((limit_type->_hi - stride_con) < limit_type->_hi) ||
-        stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo), "sanity");
+           stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo),
+           "sanity");
 
     if (limit->is_Con()) {
       // The check in policy_unroll and the assert above guarantee
@@ -1829,8 +1887,8 @@
         // zero trip guard limit will be different from loop limit.
         assert(has_ctrl(opaq), "should have it");
         Node* opaq_ctrl = get_ctrl(opaq);
-        limit = new Opaque2Node( C, limit );
-        register_new_node( limit, opaq_ctrl );
+        limit = new Opaque2Node(C, limit);
+        register_new_node(limit, opaq_ctrl);
       }
       if ((stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo)) ||
           (stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi))) {
@@ -1871,15 +1929,16 @@
           adj_limit = new SubINode(limit, stride);
         }
         assert(old_limit != NULL && adj_limit != NULL, "");
-        register_new_node( adj_limit, ctrl ); // adjust amount
+        register_new_node(adj_limit, ctrl); // adjust amount
         Node* adj_cmp = new CmpINode(old_limit, adj_limit);
-        register_new_node( adj_cmp, ctrl );
+        register_new_node(adj_cmp, ctrl);
         Node* adj_bool = new BoolNode(adj_cmp, bt);
-        register_new_node( adj_bool, ctrl );
+        register_new_node(adj_bool, ctrl);
         new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT);
       }
       register_new_node(new_limit, ctrl);
     }
+
     assert(new_limit != NULL, "");
     // Replace in loop test.
     assert(loop_end->in(1)->in(1) == cmp, "sanity");
@@ -1929,10 +1988,10 @@
   // Make the fall-in from the original come from the fall-out of the clone.
   for (DUIterator_Fast jmax, j = loop_head->fast_outs(jmax); j < jmax; j++) {
     Node* phi = loop_head->fast_out(j);
-    if( phi->is_Phi() && phi->in(0) == loop_head && phi->outcnt() > 0 ) {
+    if (phi->is_Phi() && phi->in(0) == loop_head && phi->outcnt() > 0) {
       Node *newphi = old_new[phi->_idx];
-      _igvn.hash_delete( phi );
-      _igvn.hash_delete( newphi );
+      _igvn.hash_delete(phi);
+      _igvn.hash_delete(newphi);
 
       phi   ->set_req(LoopNode::   EntryControl, newphi->in(LoopNode::LoopBackControl));
       newphi->set_req(LoopNode::LoopBackControl, phi   ->in(LoopNode::LoopBackControl));
@@ -1940,7 +1999,7 @@
     }
   }
   Node *clone_head = old_new[loop_head->_idx];
-  _igvn.hash_delete( clone_head );
+  _igvn.hash_delete(clone_head);
   loop_head ->set_req(LoopNode::   EntryControl, clone_head->in(LoopNode::LoopBackControl));
   clone_head->set_req(LoopNode::LoopBackControl, loop_head ->in(LoopNode::LoopBackControl));
   loop_head ->set_req(LoopNode::LoopBackControl, C->top());
@@ -1951,18 +2010,19 @@
 
   // Kill the clone's backedge
   Node *newcle = old_new[loop_end->_idx];
-  _igvn.hash_delete( newcle );
+  _igvn.hash_delete(newcle);
   Node *one = _igvn.intcon(1);
   set_ctrl(one, C->root());
   newcle->set_req(1, one);
   // Force clone into same loop body
   uint max = loop->_body.size();
-  for( uint k = 0; k < max; k++ ) {
+  for (uint k = 0; k < max; k++) {
     Node *old = loop->_body.at(k);
     Node *nnn = old_new[old->_idx];
     loop->_body.push(nnn);
-    if (!has_ctrl(old))
+    if (!has_ctrl(old)) {
       set_loop(nnn, loop);
+    }
   }
 
   loop->record_for_igvn();
@@ -1974,7 +2034,7 @@
     for (uint i = 0; i < loop->_body.size(); i++) {
       loop->_body.at(i)->dump();
     }
-    if(C->clone_map().is_debug()) {
+    if (C->clone_map().is_debug()) {
       tty->print("\nCloneMap\n");
       Dict* dict = C->clone_map().dict();
       DictI i(dict);
@@ -1990,12 +2050,11 @@
     }
   }
 #endif
-
 }
 
 //------------------------------do_maximally_unroll----------------------------
 
-void PhaseIdealLoop::do_maximally_unroll( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::do_maximally_unroll(IdealLoopTree *loop, Node_List &old_new) {
   CountedLoopNode *cl = loop->_head->as_CountedLoop();
   assert(cl->has_exact_trip_count(), "trip count is not exact");
   assert(cl->trip_count() > 0, "");
@@ -2113,7 +2172,7 @@
 // the pre-loop or the post-loop until the condition holds true in the main
 // loop.  Stride, scale, offset and limit are all loop invariant.  Further,
 // stride and scale are constants (offset and limit often are).
-void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit ) {
+void PhaseIdealLoop::add_constraint(int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit) {
   // For positive stride, the pre-loop limit always uses a MAX function
   // and the main loop a MIN function.  For negative stride these are
   // reversed.
@@ -2198,7 +2257,7 @@
     set_ctrl(one, C->root());
 
     Node *plus_one = new AddINode(offset, one);
-    register_new_node( plus_one, pre_ctrl );
+    register_new_node(plus_one, pre_ctrl);
     // Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
     *pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl,
                               scale_con < -1 && stride_con > 0);
@@ -2367,7 +2426,7 @@
 
 //------------------------------do_range_check---------------------------------
 // Eliminate range-checks and other trip-counter vs loop-invariant tests.
-int PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
+int PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
 #ifndef PRODUCT
   if (PrintOpto && VerifyLoopOptimizations) {
     tty->print("Range Check Elimination ");
@@ -2377,15 +2436,16 @@
     loop->dump_head();
   }
 #endif
+
   assert(RangeCheckElimination, "");
   CountedLoopNode *cl = loop->_head->as_CountedLoop();
   // If we fail before trying to eliminate range checks, set multiversion state
   int closed_range_checks = 1;
 
   // protect against stride not being a constant
-  if (!cl->stride_is_con())
+  if (!cl->stride_is_con()) {
     return closed_range_checks;
-
+  }
   // Find the trip counter; we are iteration splitting based on it
   Node *trip_counter = cl->phi();
   // Find the main loop limit; we will trim it's iterations
@@ -2400,7 +2460,7 @@
   }
 
   // Need to find the main-loop zero-trip guard
-  Node *ctrl  = cl->skip_predicates();
+  Node *ctrl = cl->skip_predicates();
   Node *iffm = ctrl->in(0);
   Node *opqzm = iffm->in(1)->in(1)->in(2);
   assert(opqzm->in(1) == main_limit, "do not understand situation");
@@ -2418,8 +2478,9 @@
   // Occasionally it's possible for a pre-loop Opaque1 node to be
   // optimized away and then another round of loop opts attempted.
   // We can not optimize this particular loop in that case.
-  if (pre_opaq1->Opcode() != Op_Opaque1)
+  if (pre_opaq1->Opcode() != Op_Opaque1) {
     return closed_range_checks;
+  }
   Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1;
   Node *pre_limit = pre_opaq->in(1);
 
@@ -2429,9 +2490,9 @@
   // Ensure the original loop limit is available from the
   // pre-loop Opaque1 node.
   Node *orig_limit = pre_opaq->original_loop_limit();
-  if (orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP)
+  if (orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP) {
     return closed_range_checks;
-
+  }
   // Must know if its a count-up or count-down loop
 
   int stride_con = cl->stride_con();
@@ -2457,8 +2518,9 @@
 
   Node* predicate_proj = cl->skip_strip_mined()->in(LoopNode::EntryControl);
   assert(predicate_proj->is_Proj() && predicate_proj->in(0)->is_If(), "if projection only");
+
   // Check loop body for tests of trip-counter plus loop-invariant vs loop-variant.
-  for( uint i = 0; i < loop->_body.size(); i++ ) {
+  for (uint i = 0; i < loop->_body.size(); i++) {
     Node *iff = loop->_body[i];
     if (iff->Opcode() == Op_If ||
         iff->Opcode() == Op_RangeCheck) { // Test?
@@ -2466,18 +2528,18 @@
       // we need loop unswitching instead of iteration splitting.
       closed_range_checks++;
       Node *exit = loop->is_loop_exit(iff);
-      if( !exit ) continue;
+      if (!exit) continue;
       int flip = (exit->Opcode() == Op_IfTrue) ? 1 : 0;
 
       // Get boolean condition to test
       Node *i1 = iff->in(1);
-      if( !i1->is_Bool() ) continue;
+      if (!i1->is_Bool()) continue;
       BoolNode *bol = i1->as_Bool();
       BoolTest b_test = bol->_test;
       // Flip sense of test if exit condition is flipped
-      if( flip )
+      if (flip) {
         b_test = b_test.negate();
-
+      }
       // Get compare
       Node *cmp = bol->in(1);
 
@@ -2487,14 +2549,15 @@
       int scale_con= 1;        // Assume trip counter not scaled
 
       Node *limit_c = get_ctrl(limit);
-      if( loop->is_member(get_loop(limit_c) ) ) {
+      if (loop->is_member(get_loop(limit_c))) {
         // Compare might have operands swapped; commute them
         b_test = b_test.commute();
         rc_exp = cmp->in(2);
         limit  = cmp->in(1);
         limit_c = get_ctrl(limit);
-        if( loop->is_member(get_loop(limit_c) ) )
+        if (loop->is_member(get_loop(limit_c))) {
           continue;             // Both inputs are loop varying; cannot RCE
+        }
       }
       // Here we know 'limit' is loop invariant
 
@@ -2513,8 +2576,9 @@
       }
 
       Node *offset_c = get_ctrl(offset);
-      if( loop->is_member( get_loop(offset_c) ) )
+      if (loop->is_member(get_loop(offset_c))) {
         continue;               // Offset is not really loop invariant
+      }
       // Here we know 'offset' is loop invariant.
 
       // As above for the 'limit', the 'offset' maybe pinned below the
@@ -2536,10 +2600,10 @@
       // sense of the test.
 
       // Adjust pre and main loop limits to guard the correct iteration set
-      if( cmp->Opcode() == Op_CmpU ) {// Unsigned compare is really 2 tests
-        if( b_test._test == BoolTest::lt ) { // Range checks always use lt
+      if (cmp->Opcode() == Op_CmpU) { // Unsigned compare is really 2 tests
+        if (b_test._test == BoolTest::lt) { // Range checks always use lt
           // The underflow and overflow limits: 0 <= scale*I+offset < limit
-          add_constraint( stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit );
+          add_constraint(stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit);
           // (0-offset)/scale could be outside of loop iterations range.
           conditional_rc = true;
           Node* init = cl->init_trip();
@@ -2566,29 +2630,29 @@
           continue;             // In release mode, ignore it
         }
       } else {                  // Otherwise work on normal compares
-        switch( b_test._test ) {
+        switch(b_test._test) {
         case BoolTest::gt:
           // Fall into GE case
         case BoolTest::ge:
           // Convert (I*scale+offset) >= Limit to (I*(-scale)+(-offset)) <= -Limit
           scale_con = -scale_con;
-          offset = new SubINode( zero, offset );
-          register_new_node( offset, pre_ctrl );
-          limit  = new SubINode( zero, limit );
-          register_new_node( limit, pre_ctrl );
+          offset = new SubINode(zero, offset);
+          register_new_node(offset, pre_ctrl);
+          limit  = new SubINode(zero, limit);
+          register_new_node(limit, pre_ctrl);
           // Fall into LE case
         case BoolTest::le:
           if (b_test._test != BoolTest::gt) {
             // Convert X <= Y to X < Y+1
-            limit = new AddINode( limit, one );
-            register_new_node( limit, pre_ctrl );
+            limit = new AddINode(limit, one);
+            register_new_node(limit, pre_ctrl);
           }
           // Fall into LT case
         case BoolTest::lt:
           // The underflow and overflow limits: MIN_INT <= scale*I+offset < limit
           // Note: (MIN_INT+1 == -MAX_INT) is used instead of MIN_INT here
           // to avoid problem with scale == -1: MIN_INT/(-1) == MIN_INT.
-          add_constraint( stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit );
+          add_constraint(stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit);
           // ((MIN_INT+1)-offset)/scale could be outside of loop iterations range.
           // Note: negative offset is replaced with 0 but (MIN_INT+1)/scale could
           // still be outside of loop range.
@@ -2604,7 +2668,7 @@
 
       // Kill the eliminated test
       C->set_major_progress();
-      Node *kill_con = _igvn.intcon( 1-flip );
+      Node *kill_con = _igvn.intcon(1-flip);
       set_ctrl(kill_con, C->root());
       _igvn.replace_input_of(iff, 1, kill_con);
       // Find surviving projection
@@ -2624,9 +2688,7 @@
       if (limit->Opcode() == Op_LoadRange) {
         closed_range_checks--;
       }
-
     } // End of is IF
-
   }
   if (predicate_proj != cl->skip_strip_mined()->in(LoopNode::EntryControl)) {
     _igvn.replace_input_of(cl->skip_strip_mined(), LoopNode::EntryControl, predicate_proj);
@@ -2647,21 +2709,21 @@
   Node *main_cle = cl->loopexit();
   Node *main_bol = main_cle->in(1);
   // Hacking loop bounds; need private copies of exit test
-  if( main_bol->outcnt() > 1 ) {// BoolNode shared?
-    main_bol = main_bol->clone();// Clone a private BoolNode
-    register_new_node( main_bol, main_cle->in(0) );
+  if (main_bol->outcnt() > 1) {     // BoolNode shared?
+    main_bol = main_bol->clone();   // Clone a private BoolNode
+    register_new_node(main_bol, main_cle->in(0));
     _igvn.replace_input_of(main_cle, 1, main_bol);
   }
   Node *main_cmp = main_bol->in(1);
-  if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
-    main_cmp = main_cmp->clone();// Clone a private CmpNode
-    register_new_node( main_cmp, main_cle->in(0) );
+  if (main_cmp->outcnt() > 1) {     // CmpNode shared?
+    main_cmp = main_cmp->clone();   // Clone a private CmpNode
+    register_new_node(main_cmp, main_cle->in(0));
     _igvn.replace_input_of(main_bol, 1, main_cmp);
   }
   // Hack the now-private loop bounds
   _igvn.replace_input_of(main_cmp, 2, main_limit);
   // The OpaqueNode is unshared by design
-  assert( opqzm->outcnt() == 1, "cannot hack shared node" );
+  assert(opqzm->outcnt() == 1, "cannot hack shared node");
   _igvn.replace_input_of(opqzm, 1, main_limit);
 
   return closed_range_checks;
@@ -2830,64 +2892,67 @@
 //------------------------------DCE_loop_body----------------------------------
 // Remove simplistic dead code from loop body
 void IdealLoopTree::DCE_loop_body() {
-  for( uint i = 0; i < _body.size(); i++ )
-    if( _body.at(i)->outcnt() == 0 )
-      _body.map( i--, _body.pop() );
+  for (uint i = 0; i < _body.size(); i++) {
+    if (_body.at(i)->outcnt() == 0) {
+      _body.map(i, _body.pop());
+      i--; // Ensure we revisit the updated index.
+    }
+  }
 }
 
 
 //------------------------------adjust_loop_exit_prob--------------------------
 // Look for loop-exit tests with the 50/50 (or worse) guesses from the parsing stage.
 // Replace with a 1-in-10 exit guess.
-void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
+void IdealLoopTree::adjust_loop_exit_prob(PhaseIdealLoop *phase) {
   Node *test = tail();
-  while( test != _head ) {
+  while (test != _head) {
     uint top = test->Opcode();
-    if( top == Op_IfTrue || top == Op_IfFalse ) {
+    if (top == Op_IfTrue || top == Op_IfFalse) {
       int test_con = ((ProjNode*)test)->_con;
       assert(top == (uint)(test_con? Op_IfTrue: Op_IfFalse), "sanity");
       IfNode *iff = test->in(0)->as_If();
-      if( iff->outcnt() == 2 ) {        // Ignore dead tests
+      if (iff->outcnt() == 2) {         // Ignore dead tests
         Node *bol = iff->in(1);
-        if( bol && bol->req() > 1 && bol->in(1) &&
-            ((bol->in(1)->Opcode() == Op_StorePConditional ) ||
-             (bol->in(1)->Opcode() == Op_StoreIConditional ) ||
-             (bol->in(1)->Opcode() == Op_StoreLConditional ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeB ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeS ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeL ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeP ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeN ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapB ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapS ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapB ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapS ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapN )))
+        if (bol && bol->req() > 1 && bol->in(1) &&
+            ((bol->in(1)->Opcode() == Op_StorePConditional) ||
+             (bol->in(1)->Opcode() == Op_StoreIConditional) ||
+             (bol->in(1)->Opcode() == Op_StoreLConditional) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeB) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeS) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeI) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeL) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeP) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeN) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapB) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapS) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapB) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapS) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapI) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapL) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapN)))
           return;               // Allocation loops RARELY take backedge
         // Find the OTHER exit path from the IF
         Node* ex = iff->proj_out(1-test_con);
         float p = iff->_prob;
-        if( !phase->is_member( this, ex ) && iff->_fcnt == COUNT_UNKNOWN ) {
-          if( top == Op_IfTrue ) {
-            if( p < (PROB_FAIR + PROB_UNLIKELY_MAG(3))) {
+        if (!phase->is_member(this, ex) && iff->_fcnt == COUNT_UNKNOWN) {
+          if (top == Op_IfTrue) {
+            if (p < (PROB_FAIR + PROB_UNLIKELY_MAG(3))) {
               iff->_prob = PROB_STATIC_FREQUENT;
             }
           } else {
-            if( p > (PROB_FAIR - PROB_UNLIKELY_MAG(3))) {
+            if (p > (PROB_FAIR - PROB_UNLIKELY_MAG(3))) {
               iff->_prob = PROB_STATIC_INFREQUENT;
             }
           }
@@ -2949,26 +3014,28 @@
   phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1));
 }
 
-//------------------------------policy_do_remove_empty_loop--------------------
-// Micro-benchmark spamming.  Policy is to always remove empty loops.
-// The 'DO' part is to replace the trip counter with the value it will
-// have on the last iteration.  This will break the loop.
-bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
+//------------------------------do_remove_empty_loop---------------------------
+// We always attempt remove empty loops.   The approach is to replace the trip
+// counter with the value it will have on the last iteration.  This will break
+// the loop.
+bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
   // Minimum size must be empty loop
-  if (_body.size() > EMPTY_LOOP_SIZE)
+  if (_body.size() > EMPTY_LOOP_SIZE) {
     return false;
-
-  if (!_head->is_CountedLoop())
-    return false;     // Dead loop
+  }
+  if (!_head->is_CountedLoop()) {
+    return false;   // Dead loop
+  }
   CountedLoopNode *cl = _head->as_CountedLoop();
-  if (!cl->is_valid_counted_loop())
-    return false; // Malformed loop
-  if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
-    return false;             // Infinite loop
-
+  if (!cl->is_valid_counted_loop()) {
+    return false;   // Malformed loop
+  }
+  if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) {
+    return false;   // Infinite loop
+  }
   if (cl->is_pre_loop()) {
-    // If the loop we are removing is a pre-loop then the main and
-    // post loop can be removed as well
+    // If the loop we are removing is a pre-loop then the main and post loop
+    // can be removed as well.
     remove_main_post_loops(cl, phase);
   }
 
@@ -2978,11 +3045,11 @@
   for (DUIterator_Fast imax, i = cl->fast_outs(imax); i < imax; i++) {
     Node* n = cl->fast_out(i);
     if (n->Opcode() == Op_Phi) {
-      assert(iv == NULL, "Too many phis" );
+      assert(iv == NULL, "Too many phis");
       iv = n;
     }
   }
-  assert(iv == cl->phi(), "Wrong phi" );
+  assert(iv == cl->phi(), "Wrong phi");
 #endif
 
   // main and post loops have explicitly created zero trip guard
@@ -3056,26 +3123,26 @@
   }
   // Note: the final value after increment should not overflow since
   // counted loop has limit check predicate.
-  Node *final = new SubINode( exact_limit, cl->stride() );
+  Node *final = new SubINode(exact_limit, cl->stride());
   phase->register_new_node(final,cl->in(LoopNode::EntryControl));
   phase->_igvn.replace_node(phi,final);
   phase->C->set_major_progress();
   return true;
 }
 
-//------------------------------policy_do_one_iteration_loop-------------------
+//------------------------------do_one_iteration_loop--------------------------
 // Convert one iteration loop into normal code.
-bool IdealLoopTree::policy_do_one_iteration_loop( PhaseIdealLoop *phase ) {
-  if (!_head->as_Loop()->is_valid_counted_loop())
+bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) {
+  if (!_head->as_Loop()->is_valid_counted_loop()) {
     return false; // Only for counted loop
-
+  }
   CountedLoopNode *cl = _head->as_CountedLoop();
   if (!cl->has_exact_trip_count() || cl->trip_count() != 1) {
     return false;
   }
 
 #ifndef PRODUCT
-  if(TraceLoopOpts) {
+  if (TraceLoopOpts) {
     tty->print("OneIteration ");
     this->dump_head();
   }
@@ -3096,20 +3163,22 @@
 
 //=============================================================================
 //------------------------------iteration_split_impl---------------------------
-bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_new ) {
+bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_new) {
   // Compute loop trip count if possible.
   compute_trip_count(phase);
 
   // Convert one iteration loop into normal code.
-  if (policy_do_one_iteration_loop(phase))
+  if (do_one_iteration_loop(phase)) {
     return true;
-
+  }
   // Check and remove empty loops (spam micro-benchmarks)
-  if (policy_do_remove_empty_loop(phase))
+  if (do_remove_empty_loop(phase)) {
     return true;  // Here we removed an empty loop
-
-  bool should_peel = policy_peeling(phase); // Should we peel?
-
+  }
+
+  AutoNodeBudget node_budget(phase);
+
+  bool should_peel     = policy_peeling(phase);
   bool should_unswitch = policy_unswitching(phase);
 
   // Non-counted loops may be peeled; exactly 1 iteration is peeled.
@@ -3144,22 +3213,15 @@
       phase->do_unswitching(this, old_new);
       return true;
     }
-    bool should_maximally_unroll =  policy_maximally_unroll(phase);
+    bool should_maximally_unroll = policy_maximally_unroll(phase);
     if (should_maximally_unroll) {
       // Here we did some unrolling and peeling.  Eventually we will
       // completely unroll this loop and it will no longer be a loop.
-      phase->do_maximally_unroll(this,old_new);
+      phase->do_maximally_unroll(this, old_new);
       return true;
     }
   }
 
-  // Skip next optimizations if running low on nodes. Note that
-  // policy_unswitching and policy_maximally_unroll have this check.
-  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
-  if ((int)(2 * _body.size()) > nodes_left) {
-    return true;
-  }
-
   // Counted loops may be peeled, may need some iterations run up
   // front for RCE, and may want to align loop refs to a cache
   // line.  Thus we clone a full loop up front whose trip count is
@@ -3173,26 +3235,28 @@
   // unrolling), plus any needed for RCE purposes.
 
   bool should_unroll = policy_unroll(phase);
-
-  bool should_rce = policy_range_check(phase);
-
-  bool should_align = policy_align(phase);
-
-  // If not RCE'ing (iteration splitting) or Aligning, then we do not
-  // need a pre-loop.  We may still need to peel an initial iteration but
-  // we will not be needing an unknown number of pre-iterations.
+  bool should_rce    = policy_range_check(phase);
+  // TODO: Remove align -- not used.
+  bool should_align  = policy_align(phase);
+
+  // If not RCE'ing  (iteration splitting) or Aligning, then we  do not need a
+  // pre-loop.  We may still need to peel an initial iteration but we will not
+  // be needing an unknown number of pre-iterations.
   //
-  // Basically, if may_rce_align reports FALSE first time through,
-  // we will not be able to later do RCE or Aligning on this loop.
+  // Basically, if may_rce_align reports FALSE first time through, we will not
+  // be able to later do RCE or Aligning on this loop.
   bool may_rce_align = !policy_peel_only(phase) || should_rce || should_align;
 
   // If we have any of these conditions (RCE, alignment, unrolling) met, then
   // we switch to the pre-/main-/post-loop model.  This model also covers
   // peeling.
   if (should_rce || should_align || should_unroll) {
-    if (cl->is_normal_loop())  // Convert to 'pre/main/post' loops
+    if (cl->is_normal_loop()) { // Convert to 'pre/main/post' loops
+      if (!phase->may_require_nodes(est_loop_clone_sz(3, _body.size()))) {
+        return false;
+      }
       phase->insert_pre_post_loops(this,old_new, !may_rce_align);
-
+    }
     // Adjust the pre- and main-loop limits to let the pre and post loops run
     // with full checks, but the main-loop with no checks.  Remove said
     // checks from the main body.
@@ -3223,14 +3287,14 @@
       phase->do_unroll(this, old_new, true);
     }
 
-    // Adjust the pre-loop limits to align the main body
-    // iterations.
-    if (should_align)
+    // Adjust the pre-loop limits to align the main body iterations.
+    if (should_align) {
       Unimplemented();
-
+    }
   } else {                      // Else we have an unchanged counted loop
-    if (should_peel)           // Might want to peel but do nothing else
+    if (should_peel) {          // Might want to peel but do nothing else
       phase->do_peeling(this,old_new);
+    }
   }
   return true;
 }
@@ -3238,35 +3302,32 @@
 
 //=============================================================================
 //------------------------------iteration_split--------------------------------
-bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) {
+bool IdealLoopTree::iteration_split(PhaseIdealLoop* phase, Node_List &old_new) {
   // Recursively iteration split nested loops
-  if (_child && !_child->iteration_split(phase, old_new))
+  if (_child && !_child->iteration_split(phase, old_new)) {
     return false;
+  }
 
   // Clean out prior deadwood
   DCE_loop_body();
 
-
   // Look for loop-exit tests with my 50/50 guesses from the Parsing stage.
   // Replace with a 1-in-10 exit guess.
-  if (_parent /*not the root loop*/ &&
-      !_irreducible &&
-      // Also ignore the occasional dead backedge
-      !tail()->is_top()) {
+  if (!is_root() && is_loop()) {
     adjust_loop_exit_prob(phase);
   }
 
-  // Gate unrolling, RCE and peeling efforts.
-  if (!_child &&                // If not an inner loop, do not split
-      !_irreducible &&
-      _allow_optimizations &&
-      !tail()->is_top()) {     // Also ignore the occasional dead backedge
+  // Unrolling, RCE and peeling efforts, iff innermost loop.
+  if (_allow_optimizations && is_innermost()) {
     if (!_has_call) {
-        if (!iteration_split_impl(phase, old_new)) {
-          return false;
-        }
-    } else if (policy_unswitching(phase)) {
-      phase->do_unswitching(this, old_new);
+      if (!iteration_split_impl(phase, old_new)) {
+        return false;
+      }
+    } else {
+      AutoNodeBudget node_budget(phase);
+      if (policy_unswitching(phase)) {
+        phase->do_unswitching(this, old_new);
+      }
     }
   }
 
@@ -3274,8 +3335,9 @@
   // trip counter when there was no major reshaping.
   phase->reorg_offsets(this);
 
-  if (_next && !_next->iteration_split(phase, old_new))
+  if (_next && !_next->iteration_split(phase, old_new)) {
     return false;
+  }
   return true;
 }
 
@@ -3537,7 +3599,7 @@
 
 bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) {
   // Only for counted inner loops
-  if (!lpt->is_counted() || !lpt->is_inner()) {
+  if (!lpt->is_counted() || !lpt->is_innermost()) {
     return false;
   }
 
--- a/src/hotspot/share/opto/loopUnswitch.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/loopUnswitch.cpp	Fri May 03 14:59:32 2019 -0400
@@ -55,27 +55,31 @@
 // Return TRUE or FALSE if the loop should be unswitched
 // (ie. clone loop with an invariant test that does not exit the loop)
 bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
-  if( !LoopUnswitching ) {
+  if (!LoopUnswitching) {
     return false;
   }
   if (!_head->is_Loop()) {
     return false;
   }
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // check for vectorized loops, any unswitching was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) {
+  if (_head->is_CountedLoop() && _head->as_CountedLoop()->is_unroll_only()) {
     return false;
   }
 
-  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
-  if ((int)(2 * _body.size()) > nodes_left) {
-    return false; // Too speculative if running low on nodes.
-  }
   LoopNode* head = _head->as_Loop();
   if (head->unswitch_count() + 1 > head->unswitch_max()) {
     return false;
   }
-  return phase->find_unswitching_candidate(this) != NULL;
+  if (phase->find_unswitching_candidate(this) == NULL) {
+    return false;
+  }
+
+  // Too speculative if running low on nodes.
+  return phase->may_require_nodes(est_loop_clone_sz(3, _body.size()));
 }
 
 //------------------------------find_unswitching_candidate-----------------------------
--- a/src/hotspot/share/opto/loopnode.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/loopnode.cpp	Fri May 03 14:59:32 2019 -0400
@@ -42,17 +42,13 @@
 #include "opto/superword.hpp"
 
 //=============================================================================
-//------------------------------is_loop_iv-------------------------------------
-// Determine if a node is Counted loop induction variable.
-// The method is declared in node.hpp.
-const Node* Node::is_loop_iv() const {
-  if (this->is_Phi() && !this->as_Phi()->is_copy() &&
-      this->as_Phi()->region()->is_CountedLoop() &&
-      this->as_Phi()->region()->as_CountedLoop()->phi() == this) {
-    return this;
-  } else {
-    return NULL;
-  }
+//--------------------------is_cloop_ind_var-----------------------------------
+// Determine if a node is a counted loop induction variable.
+// NOTE: The method is declared in "node.hpp".
+bool Node::is_cloop_ind_var() const {
+  return (is_Phi() && !as_Phi()->is_copy() &&
+          as_Phi()->region()->is_CountedLoop() &&
+          as_Phi()->region()->as_CountedLoop()->phi() == this);
 }
 
 //=============================================================================
@@ -2942,14 +2938,15 @@
   }
 
   if (ReassociateInvariants) {
+    AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
     // Reassociate invariants and prep for split_thru_phi
     for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
       IdealLoopTree* lpt = iter.current();
       bool is_counted = lpt->is_counted();
-      if (!is_counted || !lpt->is_inner()) continue;
+      if (!is_counted || !lpt->is_innermost()) continue;
 
       // check for vectorized loops, any reassociation of invariants was already done
-      if (is_counted && lpt->_head->as_CountedLoop()->do_unroll_only()) continue;
+      if (is_counted && lpt->_head->as_CountedLoop()->is_unroll_only()) continue;
 
       lpt->reassociate_invariants(this);
 
--- a/src/hotspot/share/opto/loopnode.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/loopnode.hpp	Fri May 03 14:59:32 2019 -0400
@@ -264,7 +264,7 @@
   bool is_reduction_loop() const { return (_loop_flags&HasReductions) == HasReductions; }
   bool was_slp_analyzed () const { return (_loop_flags&WasSlpAnalyzed) == WasSlpAnalyzed; }
   bool has_passed_slp   () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; }
-  bool do_unroll_only      () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
+  bool is_unroll_only   () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
   bool is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; }
   bool has_atomic_post_loop  () const { return (_loop_flags & HasAtomicPostLoop) == HasAtomicPostLoop; }
   void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; }
@@ -370,26 +370,49 @@
 };
 
 
-inline CountedLoopEndNode *CountedLoopNode::loopexit_or_null() const {
-  Node *bc = back_control();
-  if( bc == NULL ) return NULL;
-  Node *le = bc->in(0);
-  if( le->Opcode() != Op_CountedLoopEnd )
-    return NULL;
-  return (CountedLoopEndNode*)le;
+inline CountedLoopEndNode* CountedLoopNode::loopexit_or_null() const {
+  Node* bctrl = back_control();
+  if (bctrl == NULL) return NULL;
+
+  Node* lexit = bctrl->in(0);
+  return (CountedLoopEndNode*)
+      (lexit->Opcode() == Op_CountedLoopEnd ? lexit : NULL);
 }
-inline CountedLoopEndNode *CountedLoopNode::loopexit() const {
+
+inline CountedLoopEndNode* CountedLoopNode::loopexit() const {
   CountedLoopEndNode* cle = loopexit_or_null();
   assert(cle != NULL, "loopexit is NULL");
   return cle;
 }
-inline Node *CountedLoopNode::init_trip() const { return loopexit_or_null() ? loopexit()->init_trip() : NULL; }
-inline Node *CountedLoopNode::stride() const { return loopexit_or_null() ? loopexit()->stride() : NULL; }
-inline int CountedLoopNode::stride_con() const { return loopexit_or_null() ? loopexit()->stride_con() : 0; }
-inline bool CountedLoopNode::stride_is_con() const { return loopexit_or_null() && loopexit()->stride_is_con(); }
-inline Node *CountedLoopNode::limit() const { return loopexit_or_null() ? loopexit()->limit() : NULL; }
-inline Node *CountedLoopNode::incr() const { return loopexit_or_null() ? loopexit()->incr() : NULL; }
-inline Node *CountedLoopNode::phi() const { return loopexit_or_null() ? loopexit()->phi() : NULL; }
+
+inline Node* CountedLoopNode::init_trip() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->init_trip() : NULL;
+}
+inline Node* CountedLoopNode::stride() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->stride() : NULL;
+}
+inline int CountedLoopNode::stride_con() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->stride_con() : 0;
+}
+inline bool CountedLoopNode::stride_is_con() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL && cle->stride_is_con();
+}
+inline Node* CountedLoopNode::limit() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->limit() : NULL;
+}
+inline Node* CountedLoopNode::incr() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->incr() : NULL;
+}
+inline Node* CountedLoopNode::phi() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->phi() : NULL;
+}
 
 //------------------------------LoopLimitNode-----------------------------
 // Counted Loop limit node which represents exact final iterator value:
@@ -456,9 +479,9 @@
   IdealLoopTree *_child;        // First child in loop tree
 
   // The head-tail backedge defines the loop.
-  // If tail is NULL then this loop has multiple backedges as part of the
-  // same loop.  During cleanup I'll peel off the multiple backedges; merge
-  // them at the loop bottom and flow 1 real backedge into the loop.
+  // If a loop has multiple backedges, this is addressed during cleanup where
+  // we peel off the multiple backedges,  merging all edges at the bottom and
+  // ensuring that one proper backedge flow into the loop.
   Node *_head;                  // Head of loop
   Node *_tail;                  // Tail of loop
   inline Node *tail();          // Handle lazy update of _tail field
@@ -487,7 +510,10 @@
       _safepts(NULL),
       _required_safept(NULL),
       _allow_optimizations(true)
-  { }
+  {
+    precond(_head != NULL);
+    precond(_tail != NULL);
+  }
 
   // Is 'l' a member of 'this'?
   bool is_member(const IdealLoopTree *l) const; // Test for nested membership
@@ -558,10 +584,10 @@
   bool policy_unswitching( PhaseIdealLoop *phase ) const;
 
   // Micro-benchmark spamming.  Remove empty loops.
-  bool policy_do_remove_empty_loop( PhaseIdealLoop *phase );
+  bool do_remove_empty_loop( PhaseIdealLoop *phase );
 
   // Convert one iteration loop into normal code.
-  bool policy_do_one_iteration_loop( PhaseIdealLoop *phase );
+  bool do_one_iteration_loop( PhaseIdealLoop *phase );
 
   // Return TRUE or FALSE if the loop should be peeled or not.  Peel if we can
   // make some loop-invariant test (usually a null-check) happen before the
@@ -615,9 +641,11 @@
   // Put loop body on igvn work list
   void record_for_igvn();
 
-  bool is_loop()    { return !_irreducible && _tail && !_tail->is_top(); }
-  bool is_inner()   { return is_loop() && _child == NULL; }
-  bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); }
+  bool is_root() { return _parent == NULL; }
+  // A proper/reducible loop w/o any (occasional) dead back-edge.
+  bool is_loop() { return !_irreducible && !tail()->is_top(); }
+  bool is_counted()   { return is_loop() && _head->is_CountedLoop(); }
+  bool is_innermost() { return is_loop() && _child == NULL; }
 
   void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase);
 
@@ -630,13 +658,14 @@
 };
 
 // -----------------------------PhaseIdealLoop---------------------------------
-// Computes the mapping from Nodes to IdealLoopTrees.  Organizes IdealLoopTrees into a
-// loop tree.  Drives the loop-based transformations on the ideal graph.
+// Computes the mapping from Nodes to IdealLoopTrees. Organizes IdealLoopTrees
+// into a loop tree. Drives the loop-based transformations on the ideal graph.
 class PhaseIdealLoop : public PhaseTransform {
   friend class IdealLoopTree;
   friend class SuperWord;
   friend class CountedLoopReserveKit;
   friend class ShenandoahBarrierC2Support;
+  friend class AutoNodeBudget;
 
   // Pre-computed def-use info
   PhaseIterGVN &_igvn;
@@ -731,8 +760,7 @@
   }
   Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag );
 
-  // Helper function for directing control inputs away from CFG split
-  // points.
+  // Helper function for directing control inputs away from CFG split points.
   Node *find_non_split_ctrl( Node *ctrl ) const {
     if (ctrl != NULL) {
       if (ctrl->is_MultiBranch()) {
@@ -883,7 +911,8 @@
     _igvn(igvn),
     _verify_me(NULL),
     _verify_only(true),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(LoopOptsVerify);
   }
 
@@ -899,7 +928,8 @@
     _igvn(igvn),
     _verify_me(NULL),
     _verify_only(false),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(mode);
   }
 
@@ -909,7 +939,8 @@
     _igvn(igvn),
     _verify_me(verify_me),
     _verify_only(false),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(LoopOptsVerify);
   }
 
@@ -1320,8 +1351,54 @@
     return C->live_nodes() > threshold;
   }
 
+  // A simplistic node request tracking mechanism, where
+  //   = UINT_MAX   Request not valid or made final.
+  //   < UINT_MAX   Nodes currently requested (estimate).
+  uint _nodes_required;
+
+  bool exceeding_node_budget(uint required = 0) {
+    assert(C->live_nodes() < C->max_node_limit(), "sanity");
+    uint available = C->max_node_limit() - C->live_nodes();
+    return available < required + _nodes_required;
+  }
+
+  uint require_nodes(uint require) {
+    precond(require > 0);
+    _nodes_required += MAX2(100u, require); // Keep requests at minimum 100.
+    return _nodes_required;
+  }
+
+  bool may_require_nodes(uint require) {
+    return !exceeding_node_budget(require) && require_nodes(require) > 0;
+  }
+
+  void require_nodes_begin() {
+    assert(_nodes_required == UINT_MAX, "Bad state (begin).");
+    _nodes_required = 0;
+  }
+
+  // Final check  that the requested nodes  did not exceed the  limit and that
+  // the request  was reasonably  correct with  respect to  the number  of new
+  // nodes introduced by any transform since the last 'begin'.
+  void require_nodes_final_check(uint live_at_begin) {
+    uint required = _nodes_required;
+    require_nodes_final();
+    uint delta = C->live_nodes() - live_at_begin;
+    assert(delta <= 2 * required, "Bad node estimate (actual: %d, request: %d)",
+           delta, required);
+  }
+
+  void require_nodes_final() {
+    assert(_nodes_required < UINT_MAX, "Bad state (final).");
+    assert(!exceeding_node_budget(), "Too many NODES required!");
+    _nodes_required = UINT_MAX;
+  }
+
   bool _created_loop_node;
+
 public:
+  uint nodes_required() const { return _nodes_required; }
+
   void set_created_loop_node() { _created_loop_node = true; }
   bool created_loop_node()     { return _created_loop_node; }
   void register_new_node( Node *n, Node *blk );
@@ -1347,6 +1424,62 @@
   void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const;
 };
 
+
+class AutoNodeBudget : public StackObj
+{
+public:
+  enum budget_check_t { BUDGET_CHECK, NO_BUDGET_CHECK };
+
+  AutoNodeBudget(PhaseIdealLoop* phase, budget_check_t chk = BUDGET_CHECK)
+    : _phase(phase),
+      _check_at_final(chk == BUDGET_CHECK),
+      _nodes_at_begin(0)
+  {
+    precond(_phase != NULL);
+
+    _nodes_at_begin = _phase->C->live_nodes();
+    _phase->require_nodes_begin();
+  }
+
+  ~AutoNodeBudget() {
+    if (_check_at_final) {
+#ifndef PRODUCT
+      if (TraceLoopOpts) {
+        uint request = _phase->nodes_required();
+
+        if (request > 0) {
+          uint delta = _phase->C->live_nodes() - _nodes_at_begin;
+
+          if (request < delta) {
+            tty->print_cr("Exceeding node budget: %d < %d", request, delta);
+          }
+        }
+      }
+#endif
+      _phase->require_nodes_final_check(_nodes_at_begin);
+    } else {
+      _phase->require_nodes_final();
+    }
+  }
+
+private:
+  PhaseIdealLoop* _phase;
+  bool _check_at_final;
+  uint _nodes_at_begin;
+};
+
+// The Estimated Loop Clone Size: CloneFactor * (BodySize + BC) + CC, where BC
+// and CC are totally ad-hoc/magic "body" and "clone" constants, respectively,
+// used to ensure that node usage estimates made are on the safe side, for the
+// most part.
+static inline uint est_loop_clone_sz(uint fact, uint size) {
+  uint const bc = 31;
+  uint const cc = 41;
+  uint estimate = fact * (size + bc) + cc;
+  return (estimate - cc) / fact == size + bc ? estimate : UINT_MAX;
+}
+
+
 // This kit may be used for making of a reserved copy of a loop before this loop
 //  goes under non-reversible changes.
 //
@@ -1410,14 +1543,11 @@
 };// class CountedLoopReserveKit
 
 inline Node* IdealLoopTree::tail() {
-// Handle lazy update of _tail field
-  Node *n = _tail;
-  //while( !n->in(0) )  // Skip dead CFG nodes
-    //n = n->in(1);
-  if (n->in(0) == NULL)
-    n = _phase->get_ctrl(n);
-  _tail = n;
-  return n;
+  // Handle lazy update of _tail field.
+  if (_tail->in(0) == NULL) {
+    _tail = _phase->get_ctrl(_tail);
+  }
+  return _tail;
 }
 
 
--- a/src/hotspot/share/opto/loopopts.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/loopopts.cpp	Fri May 03 14:59:32 2019 -0400
@@ -2662,7 +2662,7 @@
     assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
     get_loop(use_c)->_body.push(n_clone);
     _igvn.register_new_node_with_optimizer(n_clone);
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx);
     }
@@ -2700,7 +2700,7 @@
     set_ctrl(n_clone, get_ctrl(n));
     sink_list.push(n_clone);
     not_peel <<= n_clone->_idx;  // add n_clone to not_peel set.
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx);
     }
@@ -3046,7 +3046,7 @@
         opc == Op_CatchProj ||
         opc == Op_Jump      ||
         opc == Op_JumpProj) {
-#if !defined(PRODUCT)
+#ifndef PRODUCT
       if (TracePartialPeeling) {
         tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
       }
@@ -3102,7 +3102,7 @@
     return false;
   }
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TraceLoopOpts) {
     tty->print("PartialPeel  ");
     loop->dump_head();
@@ -3131,6 +3131,10 @@
   Node_List worklist(area);
   Node_List sink_list(area);
 
+  if (!may_require_nodes(est_loop_clone_sz(2, loop->_body.size()))) {
+    return false;
+  }
+
   // Set of cfg nodes to peel are those that are executable from
   // the head through last_peel.
   assert(worklist.size() == 0, "should be empty");
@@ -3179,7 +3183,7 @@
     if (use->is_Phi()) old_phi_cnt++;
   }
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) {
     tty->print_cr("\npeeled list");
   }
@@ -3190,7 +3194,7 @@
   uint cloned_for_outside_use = 0;
   for (i = 0; i < peel_list.size();) {
     Node* n = peel_list.at(i);
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) n->dump();
 #endif
     bool incr = true;
@@ -3212,7 +3216,7 @@
             not_peel <<= n->_idx; // add n to not_peel set.
             peel_list.remove(i);
             incr = false;
-#if !defined(PRODUCT)
+#ifndef PRODUCT
             if (TracePartialPeeling) {
               tty->print_cr("sink to not_peeled region: %d newbb: %d",
                             n->_idx, get_ctrl(n)->_idx);
@@ -3231,7 +3235,7 @@
   }
 
   if (new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta) {
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("\nToo many new phis: %d  old %d new cmpi: %c",
                     new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F');
@@ -3389,7 +3393,7 @@
   C->set_major_progress();
   loop->record_for_igvn();
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) {
     tty->print_cr("\nafter partial peel one iteration");
     Node_List wl(area);
@@ -3429,10 +3433,10 @@
   Node *exit = cle->proj_out(false);
   Node *phi = cl->phi();
 
-  // Check for the special case of folks using the pre-incremented
-  // trip-counter on the fall-out path (forces the pre-incremented
-  // and post-incremented trip counter to be live at the same time).
-  // Fix this by adjusting to use the post-increment trip counter.
+  // Check for the special case when using the pre-incremented trip-counter on
+  // the fall-out  path (forces the pre-incremented  and post-incremented trip
+  // counter to be live  at the same time).  Fix this by  adjusting to use the
+  // post-increment trip counter.
 
   bool progress = true;
   while (progress) {
--- a/src/hotspot/share/opto/memnode.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/memnode.cpp	Fri May 03 14:59:32 2019 -0400
@@ -3549,9 +3549,6 @@
 // within the initialized memory.
 intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) {
   const int FAIL = 0;
-  if (st->is_unaligned_access()) {
-    return FAIL;
-  }
   if (st->req() != MemNode::ValueIn + 1)
     return FAIL;                // an inscrutable StoreNode (card mark?)
   Node* ctl = st->in(MemNode::Control);
@@ -3567,6 +3564,10 @@
     return FAIL;                // inscrutable address
   if (alloc != allocation())
     return FAIL;                // wrong allocation!  (store needs to float up)
+  int size_in_bytes = st->memory_size();
+  if ((size_in_bytes != 0) && (offset % size_in_bytes) != 0) {
+    return FAIL;                // mismatched access
+  }
   Node* val = st->in(MemNode::ValueIn);
   int complexity_count = 0;
   if (!detect_init_independence(val, complexity_count))
--- a/src/hotspot/share/opto/node.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/node.hpp	Fri May 03 14:59:32 2019 -0400
@@ -1007,9 +1007,9 @@
   // value, if it appears (by local graph inspection) to be computed by a simple conditional.
   bool is_iteratively_computed();
 
-  // Determine if a node is Counted loop induction variable.
-  // The method is defined in loopnode.cpp.
-  const Node* is_loop_iv() const;
+  // Determine if a node is a counted loop induction variable.
+  // NOTE: The method is defined in "loopnode.cpp".
+  bool is_cloop_ind_var() const;
 
   // Return a node with opcode "opc" and same inputs as "this" if one can
   // be found; Otherwise return NULL;
--- a/src/hotspot/share/opto/parse1.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/parse1.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1028,6 +1028,8 @@
     // transform each slice of the original memphi:
     mms.set_memory(_gvn.transform(mms.memory()));
   }
+  // Clean up input MergeMems created by transforming the slices
+  _gvn.transform(_exits.merged_memory());
 
   if (tf()->range()->cnt() > TypeFunc::Parms) {
     const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
--- a/src/hotspot/share/opto/subnode.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/subnode.cpp	Fri May 03 14:59:32 2019 -0400
@@ -114,31 +114,37 @@
 }
 
 //=============================================================================
+//------------------------------Helper function--------------------------------
 
-//------------------------------Helper function--------------------------------
-static bool ok_to_convert(Node* inc, Node* iv) {
-    // Do not collapse (x+c0)-y if "+" is a loop increment, because the
-    // "-" is loop invariant and collapsing extends the live-range of "x"
-    // to overlap with the "+", forcing another register to be used in
-    // the loop.
-    // This test will be clearer with '&&' (apply DeMorgan's rule)
-    // but I like the early cutouts that happen here.
-    const PhiNode *phi;
-    if( ( !inc->in(1)->is_Phi() ||
-          !(phi=inc->in(1)->as_Phi()) ||
-          phi->is_copy() ||
-          !phi->region()->is_CountedLoop() ||
-          inc != phi->region()->as_CountedLoop()->incr() )
-       &&
-        // Do not collapse (x+c0)-iv if "iv" is a loop induction variable,
-        // because "x" maybe invariant.
-        ( !iv->is_loop_iv() )
-      ) {
-      return true;
-    } else {
-      return false;
-    }
+static bool is_cloop_increment(Node* inc) {
+  precond(inc->Opcode() == Op_AddI || inc->Opcode() == Op_AddL);
+
+  if (!inc->in(1)->is_Phi()) {
+    return false;
+  }
+  const PhiNode* phi = inc->in(1)->as_Phi();
+
+  if (phi->is_copy() || !phi->region()->is_CountedLoop()) {
+    return false;
+  }
+
+  return inc == phi->region()->as_CountedLoop()->incr();
 }
+
+// Given the expression '(x + C) - v', or
+//                      'v - (x + C)', we examine nodes '+' and 'v':
+//
+//  1. Do not convert if '+' is a counted-loop increment, because the '-' is
+//     loop invariant and converting extends the live-range of 'x' to overlap
+//     with the '+', forcing another register to be used in the loop.
+//
+//  2. Do not convert if 'v' is a counted-loop induction variable, because
+//     'x' might be invariant.
+//
+static bool ok_to_convert(Node* inc, Node* var) {
+  return !(is_cloop_increment(inc) || var->is_cloop_ind_var());
+}
+
 //------------------------------Ideal------------------------------------------
 Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
   Node *in1 = in(1);
--- a/src/hotspot/share/opto/superword.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/opto/superword.cpp	Fri May 03 14:59:32 2019 -0400
@@ -145,7 +145,7 @@
   // Skip any loops already optimized by slp
   if (cl->is_vectorized_loop()) return;
 
-  if (cl->do_unroll_only()) return;
+  if (cl->is_unroll_only()) return;
 
   if (cl->is_main_loop()) {
     // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit))))
--- a/src/hotspot/share/prims/jni.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jni.cpp	Fri May 03 14:59:32 2019 -0400
@@ -88,10 +88,6 @@
 #include "utilities/histogram.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/vmError.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 
 static jint CurrentVersion = JNI_VERSION_10;
 
@@ -1318,14 +1314,15 @@
     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
   }
 
+  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // Throw a NoSuchMethodError exception if we have an instance of a
   // primitive java.lang.Class
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
   }
 
-  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
-
   // Make sure class is linked and initialized before handing id's out to
   // Method*s.
   klass->initialize(CHECK_NULL);
@@ -1346,7 +1343,8 @@
     }
   }
   if (m == NULL || (m->is_static() != is_static)) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
   }
   return m->jmethod_id();
 }
@@ -2014,22 +2012,26 @@
   jfieldID ret = 0;
   DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret);
 
+  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // The class should have been loaded (we have an instance of the class
   // passed in) so the field and signature should already be in the symbol
   // table.  If they're not there, the field doesn't exist.
   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
   if (fieldname == NULL || signame == NULL) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
   }
-  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // Make sure class is initialized before handing id's out to fields
   k->initialize(CHECK_NULL);
 
   fieldDescriptor fd;
   if (!k->is_instance_klass() ||
       !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
   }
 
   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
--- a/src/hotspot/share/prims/jvm.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvm.cpp	Fri May 03 14:59:32 2019 -0400
@@ -508,12 +508,7 @@
 
 JVM_ENTRY_NO_ENV(jlong, JVM_FreeMemory(void))
   JVMWrapper("JVM_FreeMemory");
-  CollectedHeap* ch = Universe::heap();
-  size_t n;
-  {
-     MutexLocker x(Heap_lock);
-     n = ch->capacity() - ch->used();
-  }
+  size_t n = Universe::heap()->unused();
   return convert_size_t_to_jlong(n);
 JVM_END
 
@@ -2868,7 +2863,7 @@
   if (is_alive) {
     // jthread refers to a live JavaThread.
     {
-      MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);
       if (receiver->is_external_suspend()) {
         // Don't allow nested external suspend requests. We can't return
         // an error from this interface so just ignore the problem.
@@ -3173,7 +3168,7 @@
 JVM_ENTRY(jobject, JVM_GetAndClearReferencePendingList(JNIEnv* env))
   JVMWrapper("JVM_GetAndClearReferencePendingList");
 
-  MonitorLockerEx ml(Heap_lock);
+  MonitorLocker ml(Heap_lock);
   oop ref = Universe::reference_pending_list();
   if (ref != NULL) {
     Universe::set_reference_pending_list(NULL);
@@ -3183,13 +3178,13 @@
 
 JVM_ENTRY(jboolean, JVM_HasReferencePendingList(JNIEnv* env))
   JVMWrapper("JVM_HasReferencePendingList");
-  MonitorLockerEx ml(Heap_lock);
+  MonitorLocker ml(Heap_lock);
   return Universe::has_reference_pending_list();
 JVM_END
 
 JVM_ENTRY(void, JVM_WaitForReferencePendingList(JNIEnv* env))
   JVMWrapper("JVM_WaitForReferencePendingList");
-  MonitorLockerEx ml(Heap_lock);
+  MonitorLocker ml(Heap_lock);
   while (!Universe::has_reference_pending_list()) {
     ml.wait();
   }
--- a/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	Fri May 03 14:59:32 2019 -0400
@@ -203,7 +203,7 @@
   // there isn't any safe way to iterate over regular CodeBlobs since
   // they can be freed at any point.
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     collector.collect();
   }
 
@@ -225,7 +225,7 @@
   // may be changing while this is happening which is ok since newly
   // created nmethod will notify normally and nmethods which are freed
   // can be safely skipped.
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   // Iterate over non-profiled and profiled nmethods
   NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
   while(iter.next()) {
@@ -234,7 +234,7 @@
     nmethodLocker nml(current);
 
     // Don't hold the lock over the notify or jmethodID creation
-    MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexUnlocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     current->get_and_cache_jmethod_id();
     JvmtiExport::post_compiled_method_load(env, current);
   }
--- a/src/hotspot/share/prims/jvmtiEnv.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp	Fri May 03 14:59:32 2019 -0400
@@ -943,7 +943,7 @@
   }
 
   {
-    MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
     if (java_thread->is_external_suspend()) {
       // don't allow nested external suspend requests.
       return (JVMTI_ERROR_THREAD_SUSPENDED);
@@ -983,7 +983,7 @@
     }
 
     {
-      MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
       if (java_thread->is_external_suspend()) {
         // don't allow nested external suspend requests.
         results[i] = JVMTI_ERROR_THREAD_SUSPENDED;
--- a/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri May 03 14:59:32 2019 -0400
@@ -32,6 +32,7 @@
 #include "oops/oopHandle.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/frame.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vmOperations.hpp"
 #include "utilities/growableArray.hpp"
@@ -98,7 +99,7 @@
   const void *_env_local_storage;     // per env agent allocated data.
   jvmtiEventCallbacks _event_callbacks;
   jvmtiExtEventCallbacks _ext_event_callbacks;
-  JvmtiTagMap* _tag_map;
+  JvmtiTagMap* volatile _tag_map;
   JvmtiEnvEventEnable _env_event_enable;
   jvmtiCapabilities _current_capabilities;
   jvmtiCapabilities _prohibited_capabilities;
@@ -253,6 +254,13 @@
     return _tag_map;
   }
 
+  JvmtiTagMap* tag_map_acquire() {
+    return OrderAccess::load_acquire(&_tag_map);
+  }
+
+  void release_set_tag_map(JvmtiTagMap* tag_map) {
+    OrderAccess::release_store(&_tag_map, tag_map);
+  }
 
   // return true if event is enabled globally or for any thread
   // True only if there is a callback for it.
--- a/src/hotspot/share/prims/jvmtiEventController.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiEventController.cpp	Fri May 03 14:59:32 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
@@ -997,21 +997,21 @@
 
 void
 JvmtiEventController::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
-  MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
+  MutexLocker mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
   JvmtiEventControllerPrivate::set_frame_pop(ets, fpop);
 }
 
 
 void
 JvmtiEventController::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
-  MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
+  MutexLocker mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
   JvmtiEventControllerPrivate::clear_frame_pop(ets, fpop);
 }
 
 
 void
 JvmtiEventController::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
-  MutexLockerEx mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
+  MutexLocker mu(SafepointSynchronize::is_at_safepoint() ? NULL : JvmtiThreadState_lock);
   JvmtiEventControllerPrivate::clear_to_frame_pop(ets, fpop);
 }
 
--- a/src/hotspot/share/prims/jvmtiExport.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiExport.cpp	Fri May 03 14:59:32 2019 -0400
@@ -2239,7 +2239,7 @@
     // It may not be safe to post the event from this thread.  Defer all
     // postings to the service thread so that it can perform them in a safe
     // context and in-order.
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     JvmtiDeferredEvent event = JvmtiDeferredEvent::dynamic_code_generated_event(
         name, code_begin, code_end);
     JvmtiDeferredEventQueue::enqueue(event);
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri May 03 14:59:32 2019 -0400
@@ -90,14 +90,14 @@
 // If any of the classes are being redefined, wait
 // Parallel constant pool merging leads to indeterminate constant pools.
 void VM_RedefineClasses::lock_classes() {
-  MutexLocker ml(RedefineClasses_lock);
+  MonitorLocker ml(RedefineClasses_lock);
   bool has_redefined;
   do {
     has_redefined = false;
     // Go through classes each time until none are being redefined.
     for (int i = 0; i < _class_count; i++) {
       if (get_ik(_class_defs[i].klass)->is_being_redefined()) {
-        RedefineClasses_lock->wait();
+        ml.wait();
         has_redefined = true;
         break;  // for loop
       }
@@ -106,17 +106,17 @@
   for (int i = 0; i < _class_count; i++) {
     get_ik(_class_defs[i].klass)->set_is_being_redefined(true);
   }
-  RedefineClasses_lock->notify_all();
+  ml.notify_all();
 }
 
 void VM_RedefineClasses::unlock_classes() {
-  MutexLocker ml(RedefineClasses_lock);
+  MonitorLocker ml(RedefineClasses_lock);
   for (int i = 0; i < _class_count; i++) {
     assert(get_ik(_class_defs[i].klass)->is_being_redefined(),
            "should be being redefined to get here");
     get_ik(_class_defs[i].klass)->set_is_being_redefined(false);
   }
-  RedefineClasses_lock->notify_all();
+  ml.notify_all();
 }
 
 bool VM_RedefineClasses::doit_prologue() {
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -62,6 +62,9 @@
 #if INCLUDE_ZGC
 #include "gc/z/zGlobals.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 // JvmtiTagHashmapEntry
 //
@@ -442,7 +445,7 @@
   _hashmap = new JvmtiTagHashmap();
 
   // finally add us to the environment
-  ((JvmtiEnvBase *)env)->set_tag_map(this);
+  ((JvmtiEnvBase *)env)->release_set_tag_map(this);
 }
 
 
@@ -511,7 +514,7 @@
 // returns the tag map for the given environments. If the tag map
 // doesn't exist then it is created.
 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
-  JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
+  JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map_acquire();
   if (tag_map == NULL) {
     MutexLocker mu(JvmtiThreadState_lock);
     tag_map = ((JvmtiEnvBase*)env)->tag_map();
@@ -3034,6 +3037,17 @@
   // exceptions) will be visible.
   blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
   Universe::oops_do(&blk);
+  if (blk.stopped()) {
+    return false;
+  }
+
+#if INCLUDE_JVMCI
+  blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
+  JVMCI::oops_do(&blk);
+  if (blk.stopped()) {
+    return false;
+  }
+#endif
 
   return true;
 }
@@ -3304,7 +3318,7 @@
   if (JvmtiEnv::environments_might_exist()) {
     JvmtiEnvIterator it;
     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
-      JvmtiTagMap* tag_map = env->tag_map();
+      JvmtiTagMap* tag_map = env->tag_map_acquire();
       if (tag_map != NULL && !tag_map->is_empty()) {
         tag_map->do_weak_oops(is_alive, f);
       }
--- a/src/hotspot/share/prims/methodHandles.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/methodHandles.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1098,7 +1098,7 @@
   CallSiteDepChange changes(call_site, target);
   {
     NoSafepointVerifier nsv;
-    MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
     oop context = java_lang_invoke_CallSite::context_no_keepalive(call_site());
     DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
@@ -1497,7 +1497,7 @@
     int marked = 0;
     {
       NoSafepointVerifier nsv;
-      MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
       marked = deps.remove_all_dependents();
     }
--- a/src/hotspot/share/prims/nativeLookup.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/nativeLookup.hpp	Fri May 03 14:59:32 2019 -0400
@@ -33,11 +33,6 @@
 
 class NativeLookup : AllStatic {
  private:
-  // JNI name computation
-  static char* pure_jni_name(const methodHandle& method);
-  static char* long_jni_name(const methodHandle& method);
-  static char* critical_jni_name(const methodHandle& method);
-
   // Style specific lookup
   static address lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS);
   static address lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style);
@@ -45,6 +40,11 @@
   static address lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS);
   static address lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS);
  public:
+  // JNI name computation
+  static char* pure_jni_name(const methodHandle& method);
+  static char* long_jni_name(const methodHandle& method);
+  static char* critical_jni_name(const methodHandle& method);
+
   // Lookup native function. May throw UnsatisfiedLinkError.
   static address lookup(const methodHandle& method, bool& in_base_library, TRAPS);
   static address lookup_critical_entry(const methodHandle& method);
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri May 03 14:59:32 2019 -0400
@@ -60,7 +60,6 @@
  public:
   static uintx get_hash(WeakHandle<vm_resolved_method_table_data> const& value,
                         bool* is_dead) {
-    EXCEPTION_MARK;
     oop val_oop = value.peek();
     if (val_oop == NULL) {
       *is_dead = true;
@@ -176,8 +175,8 @@
   LogTarget(Debug, membername, table) log;
   if (log.is_enabled()) {
     ResourceMark rm;
-    log_debug(membername, table) ("ResolvedMethod entry added for %s",
-                                  method->name_and_sig_as_C_string());
+    log.print("ResolvedMethod entry added for %s",
+              method->name_and_sig_as_C_string());
   }
 }
 
@@ -198,8 +197,6 @@
       return wh.resolve();
     }
   }
-
-  return rmethod_name();
 }
 
 void ResolvedMethodTable::item_added() {
@@ -251,7 +248,7 @@
 }
 
 void ResolvedMethodTable::trigger_concurrent_work() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   _has_work = true;
   Service_lock->notify_all();
 }
--- a/src/hotspot/share/prims/unsafe.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/unsafe.cpp	Fri May 03 14:59:32 2019 -0400
@@ -949,27 +949,16 @@
     (void) tlh.cv_internal_thread_to_JavaThread(jthread, &thr, &java_thread);
     if (java_thread != NULL) {
       // This is a valid oop.
-      jlong lp = java_lang_Thread::park_event(java_thread);
-      if (lp != 0) {
-        // This cast is OK even though the jlong might have been read
-        // non-atomically on 32bit systems, since there, one word will
-        // always be zero anyway and the value set is always the same
-        p = (Parker*)addr_from_java(lp);
-      } else {
-        // Not cached in the java.lang.Thread oop yet (could be an
-        // older version of library).
-        if (thr != NULL) {
-          // The JavaThread is alive.
-          p = thr->parker();
-          if (p != NULL) {
-            // Cache the Parker in the java.lang.Thread oop for next time.
-            java_lang_Thread::set_park_event(java_thread, addr_to_java(p));
-          }
-        }
+      if (thr != NULL) {
+        // The JavaThread is alive.
+        p = thr->parker();
       }
     }
   } // ThreadsListHandle is destroyed here.
 
+  // 'p' points to type-stable-memory if non-NULL. If the target
+  // thread terminates before we get here the new user of this
+  // Parker will get a 'spurious' unpark - which is perfectly valid.
   if (p != NULL) {
     HOTSPOT_THREAD_UNPARK((uintptr_t) p);
     p->unpark();
--- a/src/hotspot/share/prims/whitebox.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp	Fri May 03 14:59:32 2019 -0400
@@ -34,6 +34,7 @@
 #include "compiler/methodMatcher.hpp"
 #include "compiler/directivesParser.hpp"
 #include "gc/shared/gcConfig.hpp"
+#include "gc/shared/genArguments.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/heapShared.inline.hpp"
@@ -79,6 +80,7 @@
 #include "prims/cdsoffsets.hpp"
 #endif // INCLUDE_CDS
 #if INCLUDE_G1GC
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1ConcurrentMark.hpp"
 #include "gc/g1/g1ConcurrentMarkThread.hpp"
@@ -222,11 +224,13 @@
 WB_END
 
 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
-  CollectorPolicy * p = Universe::heap()->collector_policy();
-  tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
-    SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
-    p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
-    p->space_alignment(), p->heap_alignment());
+  tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " "
+                "Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
+                MinHeapSize,
+                InitialHeapSize,
+                MaxHeapSize,
+                SpaceAlignment,
+                HeapAlignment);
 }
 WB_END
 
@@ -381,13 +385,11 @@
 WB_END
 
 WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
-  size_t alignment = Universe::heap()->collector_policy()->space_alignment();
-  return (jlong)alignment;
+  return (jlong)SpaceAlignment;
 WB_END
 
 WB_ENTRY(jlong, WB_GetHeapAlignment(JNIEnv* env, jobject o))
-  size_t alignment = Universe::heap()->collector_policy()->heap_alignment();
-  return (jlong)alignment;
+  return (jlong)HeapAlignment;
 WB_END
 
 WB_ENTRY(jboolean, WB_SupportsConcurrentGCPhaseControl(JNIEnv* env, jobject o))
@@ -513,7 +515,7 @@
       uint end_region = HeterogeneousHeapRegionManager::manager()->end_index_of_dram();
       return (jlong)(g1h->base() + (end_region + 1) * HeapRegion::GrainBytes - 1);
     } else {
-      return (jlong)g1h->base() + g1h->collector_policy()->max_heap_byte_size();
+      return (jlong)g1h->base() + G1Arguments::heap_reserved_size_bytes();
     }
   }
 #endif // INCLUDE_G1GC
@@ -596,7 +598,7 @@
 
 WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
   if (UseParallelGC) {
-    return ParallelScavengeHeap::heap()->generation_alignment();
+    return GenAlignment;
   }
   THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
 WB_END
@@ -817,7 +819,7 @@
 WB_END
 
 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   CodeCache::mark_all_nmethods_for_deoptimization();
   VM_Deoptimize op;
   VMThread::execute(&op);
@@ -827,7 +829,7 @@
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   int result = 0;
   CHECK_JNI_EXCEPTION_(env, result);
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   if (is_osr) {
     result += mh->mark_osr_nmethods();
@@ -846,7 +848,7 @@
 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   CompiledMethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
   if (code == NULL) {
@@ -861,7 +863,7 @@
   }
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   if (is_osr) {
     return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
@@ -873,7 +875,7 @@
 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   return mh->queued_for_compilation();
 WB_END
@@ -982,7 +984,7 @@
 
   // Compile method and check result
   nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, THREAD);
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   bool is_queued = mh->queued_for_compilation();
   if ((!is_blocking && is_queued) || nm != NULL) {
     return true;
@@ -1082,7 +1084,7 @@
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION(env);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
-  MutexLockerEx mu(Compile_lock);
+  MutexLocker mu(Compile_lock);
   MethodData* mdo = mh->method_data();
   MethodCounters* mcs = mh->method_counters();
 
@@ -1093,7 +1095,7 @@
     for (int i = 0; i < arg_count; i++) {
       mdo->set_arg_modified(i, 0);
     }
-    MutexLockerEx mu(mdo->extra_data_lock());
+    MutexLocker mu(mdo->extra_data_lock());
     mdo->clean_method_data(/*always_clean*/true);
   }
 
@@ -1342,7 +1344,7 @@
 WB_END
 
 WB_ENTRY(void, WB_UnlockCompilation(JNIEnv* env, jobject o))
-  MonitorLockerEx mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker mo(Compilation_lock, Mutex::_no_safepoint_check_flag);
   WhiteBox::compilation_locked = false;
   mo.notify_all();
 WB_END
@@ -1502,7 +1504,7 @@
     full_size += align_up(size - full_size, oopSize);
   }
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
     if (blob != NULL) {
       ::new (blob) BufferBlob("WB::DummyBlob", full_size);
@@ -1532,7 +1534,7 @@
   ResourceMark rm;
   GrowableArray<CodeBlobStub*> blobs;
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeHeap* heap = WhiteBox::get_code_heap(blob_type);
     if (heap == NULL) {
       return NULL;
@@ -1718,8 +1720,11 @@
   Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
                                            Monitor::_safepoint_check_always :
                                            Monitor::_safepoint_check_never;
-  MutexLockerEx ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
-                   attemptedNoSafepointValue == JNI_TRUE);
+  Monitor::SafepointCheckFlag sfpt_check_attempted = attemptedNoSafepointValue ?
+                                           Monitor::_no_safepoint_check_flag :
+                                           Monitor::_safepoint_check_flag;
+  MutexLocker ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required),
+                 sfpt_check_attempted);
 WB_END
 
 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
--- a/src/hotspot/share/runtime/arguments.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,6 @@
 #include "classfile/moduleEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
-#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcConfig.hpp"
 #include "logging/log.hpp"
@@ -57,9 +56,6 @@
 #include "utilities/defaultStream.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stringUtils.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 #if INCLUDE_JFR
 #include "jfr/jfr.hpp"
 #endif
@@ -81,7 +77,6 @@
 SystemProperty* Arguments::_system_properties   = NULL;
 const char*  Arguments::_gc_log_filename        = NULL;
 size_t Arguments::_conservative_max_heap_alignment = 0;
-size_t Arguments::_min_heap_size                = 0;
 Arguments::Mode Arguments::_mode                = _mixed;
 bool   Arguments::_java_compiler                = false;
 bool   Arguments::_xdebug_mode                  = false;
@@ -565,6 +560,7 @@
   { "ProfilerNumberOfStubMethods",   JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) },
   { "ProfilerNumberOfRuntimeStubNodes", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) },
   { "UseImplicitStableValues",       JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) },
+  { "NeedsDeoptSuspend",             JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) },
 
 #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
   // These entries will generate build errors.  Their purpose is to test the macros.
@@ -1675,13 +1671,12 @@
 void Arguments::set_conservative_max_heap_alignment() {
   // The conservative maximum required alignment for the heap is the maximum of
   // the alignments imposed by several sources: any requirements from the heap
-  // itself, the collector policy and the maximum page size we may run the VM
-  // with.
+  // itself and the maximum page size we may run the VM with.
   size_t heap_alignment = GCConfig::arguments()->conservative_max_heap_alignment();
   _conservative_max_heap_alignment = MAX4(heap_alignment,
                                           (size_t)os::vm_allocation_granularity(),
                                           os::max_page_size(),
-                                          CollectorPolicy::compute_heap_alignment());
+                                          GCArguments::compute_heap_alignment());
 }
 
 jint Arguments::set_ergonomics_flags() {
@@ -1794,7 +1789,7 @@
 
   // If the minimum or initial heap_size have not been set or requested to be set
   // ergonomically, set them accordingly.
-  if (InitialHeapSize == 0 || min_heap_size() == 0) {
+  if (InitialHeapSize == 0 || MinHeapSize == 0) {
     julong reasonable_minimum = (julong)(OldSize + NewSize);
 
     reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);
@@ -1804,7 +1799,7 @@
     if (InitialHeapSize == 0) {
       julong reasonable_initial = (julong)((phys_mem * InitialRAMPercentage) / 100);
 
-      reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)min_heap_size());
+      reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)MinHeapSize);
       reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
 
       reasonable_initial = limit_by_allocatable_memory(reasonable_initial);
@@ -1814,9 +1809,9 @@
     }
     // If the minimum heap size has not been set (via -Xms),
     // synchronize with InitialHeapSize to avoid errors with the default value.
-    if (min_heap_size() == 0) {
-      set_min_heap_size(MIN2((size_t)reasonable_minimum, InitialHeapSize));
-      log_trace(gc, heap)("  Minimum heap size " SIZE_FORMAT, min_heap_size());
+    if (MinHeapSize == 0) {
+      MinHeapSize = MIN2((size_t)reasonable_minimum, InitialHeapSize);
+      log_trace(gc, heap)("  Minimum heap size " SIZE_FORMAT, MinHeapSize);
     }
   }
 }
@@ -1858,7 +1853,7 @@
       return JNI_EINVAL;
     }
     // Currently the minimum size and the initial heap sizes are the same.
-    set_min_heap_size(initHeapSize);
+    MinHeapSize = initHeapSize;
   }
   if (FLAG_IS_DEFAULT(NewSize)) {
     // Make the young generation 3/8ths of the total heap.
@@ -2558,7 +2553,7 @@
         describe_range_error(errcode);
         return JNI_EINVAL;
       }
-      set_min_heap_size((size_t)long_initial_heap_size);
+      MinHeapSize = (size_t)long_initial_heap_size;
       // Currently the minimum size and the initial heap sizes are the same.
       // Can be overridden with -XX:InitialHeapSize.
       if (FLAG_SET_CMDLINE(size_t, InitialHeapSize, (size_t)long_initial_heap_size) != JVMFlag::SUCCESS) {
--- a/src/hotspot/share/runtime/arguments.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/arguments.hpp	Fri May 03 14:59:32 2019 -0400
@@ -333,8 +333,6 @@
   // Value of the conservative maximum heap alignment needed
   static size_t  _conservative_max_heap_alignment;
 
-  static size_t  _min_heap_size;
-
   // -Xrun arguments
   static AgentLibraryList _libraryList;
   static void add_init_library(const char* name, char* options);
@@ -548,10 +546,6 @@
   // -Dsun.java.launcher.pid
   static int sun_java_launcher_pid()        { return _sun_java_launcher_pid; }
 
-  // -Xms
-  static size_t min_heap_size()             { return _min_heap_size; }
-  static void  set_min_heap_size(size_t v)  { _min_heap_size = v;  }
-
   // -Xrun
   static AgentLibrary* libraries()          { return _libraryList.first(); }
   static bool init_libraries_at_startup()   { return !_libraryList.is_empty(); }
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Fri May 03 14:59:32 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
@@ -499,6 +499,7 @@
   JavaThread* _requesting_thread;
   BiasedLocking::Condition _status_code;
   traceid _biased_locker_id;
+  uint64_t _safepoint_id;
 
 public:
   VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
@@ -506,14 +507,16 @@
     , _objs(NULL)
     , _requesting_thread(requesting_thread)
     , _status_code(BiasedLocking::NOT_BIASED)
-    , _biased_locker_id(0) {}
+    , _biased_locker_id(0)
+    , _safepoint_id(0) {}
 
   VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
     : _obj(NULL)
     , _objs(objs)
     , _requesting_thread(requesting_thread)
     , _status_code(BiasedLocking::NOT_BIASED)
-    , _biased_locker_id(0) {}
+    , _biased_locker_id(0)
+    , _safepoint_id(0) {}
 
   virtual VMOp_Type type() const { return VMOp_RevokeBias; }
 
@@ -545,6 +548,7 @@
       if (biased_locker != NULL) {
         _biased_locker_id = JFR_THREAD_ID(biased_locker);
       }
+      _safepoint_id = SafepointSynchronize::safepoint_counter();
       clean_up_cached_monitor_info();
       return;
     } else {
@@ -560,6 +564,10 @@
   traceid biased_locker() const {
     return _biased_locker_id;
   }
+
+  uint64_t safepoint_id() const {
+    return _safepoint_id;
+  }
 };
 
 
@@ -581,17 +589,15 @@
 
   virtual void doit() {
     _status_code = bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
+    _safepoint_id = SafepointSynchronize::safepoint_counter();
     clean_up_cached_monitor_info();
   }
+
+  bool is_bulk_rebias() const {
+    return _bulk_rebias;
+  }
 };
 
-template <typename E>
-static void set_safepoint_id(E* event) {
-  assert(event != NULL, "invariant");
-  // Subtract 1 to match the id of events committed inside the safepoint
-  event->set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
-}
-
 static void post_self_revocation_event(EventBiasedLockSelfRevocation* event, Klass* k) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
@@ -600,24 +606,25 @@
   event->commit();
 }
 
-static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* revoke) {
+static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* op) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
-  assert(revoke != NULL, "invariant");
+  assert(op != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   event->set_lockClass(k);
-  set_safepoint_id(event);
-  event->set_previousOwner(revoke->biased_locker());
+  event->set_safepointId(op->safepoint_id());
+  event->set_previousOwner(op->biased_locker());
   event->commit();
 }
 
-static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, bool disabled_bias) {
+static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, VM_BulkRevokeBias* op) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
+  assert(op != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   event->set_revokedClass(k);
-  event->set_disableBiasing(disabled_bias);
-  set_safepoint_id(event);
+  event->set_disableBiasing(!op->is_bulk_rebias());
+  event->set_safepointId(op->safepoint_id());
   event->commit();
 }
 
@@ -729,7 +736,7 @@
                                 attempt_rebias);
   VMThread::execute(&bulk_revoke);
   if (event.should_commit()) {
-    post_class_revocation_event(&event, obj->klass(), heuristics != HR_BULK_REBIAS);
+    post_class_revocation_event(&event, obj->klass(), &bulk_revoke);
   }
   return bulk_revoke.status_code();
 }
--- a/src/hotspot/share/runtime/deoptimization.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Fri May 03 14:59:32 2019 -0400
@@ -63,11 +63,6 @@
 #include "utilities/preserveException.hpp"
 #include "utilities/xmlstream.hpp"
 
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#endif
-
 
 bool DeoptimizationMarker::_is_active = false;
 
@@ -1520,33 +1515,11 @@
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
 #if INCLUDE_JVMCI
-    long speculation = thread->pending_failed_speculation();
-    if (nm->is_compiled_by_jvmci()) {
-      if (speculation != 0) {
-        oop speculation_log = nm->as_nmethod()->speculation_log();
-        if (speculation_log != NULL) {
-          if (TraceDeoptimization || TraceUncollectedSpeculations) {
-            if (HotSpotSpeculationLog::lastFailed(speculation_log) != 0) {
-              tty->print_cr("A speculation that was not collected by the compiler is being overwritten");
-            }
-          }
-          if (TraceDeoptimization) {
-            tty->print_cr("Saving speculation to speculation log");
-          }
-          HotSpotSpeculationLog::set_lastFailed(speculation_log, speculation);
-        } else {
-          if (TraceDeoptimization) {
-            tty->print_cr("Speculation present but no speculation log");
-          }
-        }
-        thread->set_pending_failed_speculation(0);
-      } else {
-        if (TraceDeoptimization) {
-          tty->print_cr("No speculation");
-        }
-      }
+    jlong           speculation = thread->pending_failed_speculation();
+    if (nm->is_compiled_by_jvmci() && nm->is_nmethod()) { // Exclude AOTed methods
+      nm->as_nmethod()->update_speculation(thread);
     } else {
-      assert(speculation == 0, "There should not be a speculation for method compiled by non-JVMCI compilers");
+      assert(speculation == 0, "There should not be a speculation for methods compiled by non-JVMCI compilers");
     }
 
     if (trap_bci == SynchronizationEntryBCI) {
@@ -1595,6 +1568,11 @@
         xtty->begin_head("uncommon_trap thread='" UINTX_FORMAT "' %s",
                          os::current_thread_id(),
                          format_trap_request(buf, sizeof(buf), trap_request));
+#if INCLUDE_JVMCI
+        if (speculation != 0) {
+          xtty->print(" speculation='" JLONG_FORMAT "'", speculation);
+        }
+#endif
         nm->log_identity(xtty);
       }
       Symbol* class_name = NULL;
@@ -1640,7 +1618,7 @@
         tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
 #if INCLUDE_JVMCI
         if (nm->is_nmethod()) {
-          char* installed_code_name = nm->as_nmethod()->jvmci_installed_code_name(buf, sizeof(buf));
+          const char* installed_code_name = nm->as_nmethod()->jvmci_name();
           if (installed_code_name != NULL) {
             tty->print(" (JVMCI: installed code name=%s) ", installed_code_name);
           }
--- a/src/hotspot/share/runtime/frame.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/frame.cpp	Fri May 03 14:59:32 2019 -0400
@@ -271,64 +271,11 @@
 }
 
 void frame::deoptimize(JavaThread* thread) {
+  assert(thread->frame_anchor()->has_last_Java_frame() &&
+         thread->frame_anchor()->walkable(), "must be");
   // Schedule deoptimization of an nmethod activation with this frame.
   assert(_cb != NULL && _cb->is_compiled(), "must be");
 
-  // This is a fix for register window patching race
-  if (NeedsDeoptSuspend && Thread::current() != thread) {
-    assert(SafepointSynchronize::is_at_safepoint(),
-           "patching other threads for deopt may only occur at a safepoint");
-
-    // It is possible especially with DeoptimizeALot/DeoptimizeRandom that
-    // we could see the frame again and ask for it to be deoptimized since
-    // it might move for a long time. That is harmless and we just ignore it.
-    if (id() == thread->must_deopt_id()) {
-      assert(thread->is_deopt_suspend(), "lost suspension");
-      return;
-    }
-
-    // We are at a safepoint so the target thread can only be
-    // in 4 states:
-    //     blocked - no problem
-    //     blocked_trans - no problem (i.e. could have woken up from blocked
-    //                                 during a safepoint).
-    //     native - register window pc patching race
-    //     native_trans - momentary state
-    //
-    // We could just wait out a thread in native_trans to block.
-    // Then we'd have all the issues that the safepoint code has as to
-    // whether to spin or block. It isn't worth it. Just treat it like
-    // native and be done with it.
-    //
-    // Examine the state of the thread at the start of safepoint since
-    // threads that were in native at the start of the safepoint could
-    // come to a halt during the safepoint, changing the current value
-    // of the safepoint_state.
-    JavaThreadState state = thread->safepoint_state()->orig_thread_state();
-    if (state == _thread_in_native || state == _thread_in_native_trans) {
-      // Since we are at a safepoint the target thread will stop itself
-      // before it can return to java as long as we remain at the safepoint.
-      // Therefore we can put an additional request for the thread to stop
-      // no matter what no (like a suspend). This will cause the thread
-      // to notice it needs to do the deopt on its own once it leaves native.
-      //
-      // The only reason we must do this is because on machine with register
-      // windows we have a race with patching the return address and the
-      // window coming live as the thread returns to the Java code (but still
-      // in native mode) and then blocks. It is only this top most frame
-      // that is at risk. So in truth we could add an additional check to
-      // see if this frame is one that is at risk.
-      RegisterMap map(thread, false);
-      frame at_risk =  thread->last_frame().sender(&map);
-      if (id() == at_risk.id()) {
-        thread->set_must_deopt_id(id());
-        thread->set_deopt_suspend();
-        return;
-      }
-    }
-  } // NeedsDeoptSuspend
-
-
   // If the call site is a MethodHandle call site use the MH deopt
   // handler.
   CompiledMethod* cm = (CompiledMethod*) _cb;
@@ -682,7 +629,7 @@
 #if INCLUDE_JVMCI
         if (cm->is_nmethod()) {
           nmethod* nm = cm->as_nmethod();
-          char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
+          const char* jvmciName = nm->jvmci_name();
           if (jvmciName != NULL) {
             st->print(" (%s)", jvmciName);
           }
--- a/src/hotspot/share/runtime/globals.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/globals.hpp	Fri May 03 14:59:32 2019 -0400
@@ -324,9 +324,6 @@
           "Maximum number of pages to include in the page scan procedure")  \
           range(0, max_uintx)                                               \
                                                                             \
-  product_pd(bool, NeedsDeoptSuspend,                                       \
-          "True for register window machines (sparc/ia64)")                 \
-                                                                            \
   product(intx, UseSSE, 99,                                                 \
           "Highest supported SSE instructions set on x86/x64")              \
           range(0, 99)                                                      \
@@ -545,10 +542,10 @@
           "Number of ring buffer event logs")                               \
           range(1, NOT_LP64(1*K) LP64_ONLY(1*M))                            \
                                                                             \
-  product(bool, BytecodeVerificationRemote, true,                           \
+  diagnostic(bool, BytecodeVerificationRemote, true,                        \
           "Enable the Java bytecode verifier for remote classes")           \
                                                                             \
-  product(bool, BytecodeVerificationLocal, false,                           \
+  diagnostic(bool, BytecodeVerificationLocal, false,                        \
           "Enable the Java bytecode verifier for local classes")            \
                                                                             \
   develop(bool, ForceFloatExceptions, trueInDebug,                          \
@@ -979,8 +976,8 @@
           "Verify bytecodes after RedefineClasses constant pool merging")   \
                                                                             \
   product(bool, AllowRedefinitionToAddDeleteMethods, false,                 \
-          "Allow redefinition to add and delete private static or "         \
-          "final methods for compatibility with old releases")              \
+          "(Deprecated) Allow redefinition to add and delete private "      \
+          "static or final methods for compatibility with old releases")    \
                                                                             \
   develop(bool, TraceBytecodes, false,                                      \
           "Trace bytecode execution")                                       \
--- a/src/hotspot/share/runtime/handshake.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/handshake.cpp	Fri May 03 14:59:32 2019 -0400
@@ -137,7 +137,7 @@
       // There is an assumption in the code that the Threads_lock should be
       // locked during certain phases.
       {
-        MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+        MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
         _target->handshake_process_by_vmthread();
       }
     } while (!poll_for_completed_thread());
@@ -186,7 +186,7 @@
           // There is an assumption in the code that the Threads_lock should
           // be locked during certain phases.
           jtiwh.rewind();
-          MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+          MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
           for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) {
             // A new thread on the ThreadsList will not have an operation,
             // hence it is skipped in handshake_process_by_vmthread.
--- a/src/hotspot/share/runtime/init.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/init.cpp	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,9 @@
 #include "classfile/symbolTable.hpp"
 #include "code/icBuffer.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 #include "interpreter/bytecodes.hpp"
 #include "logging/log.hpp"
 #include "logging/logTag.hpp"
@@ -140,6 +143,11 @@
   if (!compileBroker_init()) {
     return JNI_EINVAL;
   }
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    JVMCI::initialize_globals();
+  }
+#endif
 
   if (!universe_post_init()) {
     return JNI_ERR;
@@ -191,15 +199,15 @@
 }
 
 void wait_init_completed() {
-  MonitorLockerEx ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
   while (!_init_completed) {
-    ml.wait(Monitor::_no_safepoint_check_flag);
+    ml.wait();
   }
 }
 
 void set_init_completed() {
   assert(Universe::is_fully_initialized(), "Should have completed initialization");
-  MonitorLockerEx ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
   OrderAccess::release_store(&_init_completed, true);
   ml.notify_all();
 }
--- a/src/hotspot/share/runtime/java.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/java.cpp	Fri May 03 14:59:32 2019 -0400
@@ -36,8 +36,7 @@
 #include "jfr/jfrEvents.hpp"
 #include "jfr/support/jfrThreadId.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
@@ -302,7 +301,7 @@
   }
 
   if (PrintCodeCache) {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print();
   }
 
@@ -315,7 +314,7 @@
   }
 
   if (PrintCodeCache2) {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print_internals();
   }
 
@@ -370,7 +369,7 @@
   }
 
   if (PrintCodeCache) {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print();
   }
 
@@ -419,14 +418,14 @@
   // A CAS or OSMutex would work just fine but then we need to manipulate
   // thread state for Safepoint. Here we use Monitor wait() and notify_all()
   // for synchronization.
-  { MutexLocker ml(BeforeExit_lock);
+  { MonitorLocker ml(BeforeExit_lock);
     switch (_before_exit_status) {
     case BEFORE_EXIT_NOT_RUN:
       _before_exit_status = BEFORE_EXIT_RUNNING;
       break;
     case BEFORE_EXIT_RUNNING:
       while (_before_exit_status == BEFORE_EXIT_RUNNING) {
-        BeforeExit_lock->wait();
+        ml.wait();
       }
       assert(_before_exit_status == BEFORE_EXIT_DONE, "invalid state");
       return;
@@ -439,15 +438,7 @@
   }
 
 #if INCLUDE_JVMCI
-  // We are not using CATCH here because we want the exit to continue normally.
-  Thread* THREAD = thread;
-  JVMCIRuntime::shutdown(THREAD);
-  if (HAS_PENDING_EXCEPTION) {
-    HandleMark hm(THREAD);
-    Handle exception(THREAD, PENDING_EXCEPTION);
-    CLEAR_PENDING_EXCEPTION;
-    java_lang_Throwable::java_printStackTrace(exception, THREAD);
-  }
+  JVMCI::shutdown();
 #endif
 
   // Hang forever on exit if we're reporting an error.
--- a/src/hotspot/share/runtime/javaCalls.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/javaCalls.cpp	Fri May 03 14:59:32 2019 -0400
@@ -44,10 +44,6 @@
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 
 // -----------------------------------------------------
 // Implementation of JavaCallWrapper
--- a/src/hotspot/share/runtime/jniHandles.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/jniHandles.cpp	Fri May 03 14:59:32 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
@@ -371,8 +371,8 @@
     // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
     // - another would hold Threads_lock (jni_AttachCurrentThread) and then
     //   JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
-    MutexLockerEx ml(JNIHandleBlockFreeList_lock,
-                     Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(JNIHandleBlockFreeList_lock,
+                   Mutex::_no_safepoint_check_flag);
     if (_block_free_list == NULL) {
       // Allocate new block
       block = new JNIHandleBlock();
@@ -427,8 +427,8 @@
     // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
     // - another would hold Threads_lock (jni_AttachCurrentThread) and then
     //   JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
-    MutexLockerEx ml(JNIHandleBlockFreeList_lock,
-                     Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(JNIHandleBlockFreeList_lock,
+                   Mutex::_no_safepoint_check_flag);
     while (block != NULL) {
       block->zap();
       JNIHandleBlock* next = block->_next;
--- a/src/hotspot/share/runtime/mutex.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/mutex.cpp	Fri May 03 14:59:32 2019 -0400
@@ -32,11 +32,19 @@
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
 
+#ifdef ASSERT
+void Monitor::check_safepoint_state(Thread* thread, bool do_safepoint_check) {
+  // If the JavaThread checks for safepoint, verify that the lock wasn't created with safepoint_check_never.
+  SafepointCheckRequired not_allowed = do_safepoint_check ?  Monitor::_safepoint_check_never :
+                                                             Monitor::_safepoint_check_always;
+  assert(!thread->is_Java_thread() || _safepoint_check_required != not_allowed,
+         "This lock should %s have a safepoint check for Java threads: %s",
+         _safepoint_check_required ? "always" : "never", name());
+}
+#endif // ASSERT
 
 void Monitor::lock(Thread * self) {
-  // Ensure that the Monitor requires/allows safepoint checks.
-  assert(_safepoint_check_required != Monitor::_safepoint_check_never,
-         "This lock should never have a safepoint check: %s", name());
+  check_safepoint_state(self, true);
 
 #ifdef CHECK_UNHANDLED_OOPS
   // Clear unhandled oops in JavaThreads so we get a crash right away.
@@ -91,9 +99,7 @@
 // in the wrong way this can lead to a deadlock with the safepoint code.
 
 void Monitor::lock_without_safepoint_check(Thread * self) {
-  // Ensure that the Monitor does not require safepoint checks.
-  assert(_safepoint_check_required != Monitor::_safepoint_check_always,
-         "This lock should always have a safepoint check: %s", name());
+  check_safepoint_state(self, false);
   assert(_owner != self, "invariant");
   _lock.lock();
   assert_owner(NULL);
@@ -140,27 +146,9 @@
   _lock.notify_all();
 }
 
-bool Monitor::wait(bool no_safepoint_check, long timeout,
-                   bool as_suspend_equivalent) {
-  // Make sure safepoint checking is used properly.
-  assert(!(_safepoint_check_required == Monitor::_safepoint_check_never && no_safepoint_check == false),
-         "This lock should never have a safepoint check: %s", name());
-  assert(!(_safepoint_check_required == Monitor::_safepoint_check_always && no_safepoint_check == true),
-         "This lock should always have a safepoint check: %s", name());
-
-  // timeout is in milliseconds - with zero meaning never timeout
-  assert(timeout >= 0, "negative timeout");
-
-  Thread * const self = Thread::current();
-  assert_owner(self);
-
-  // as_suspend_equivalent logically implies !no_safepoint_check
-  guarantee(!as_suspend_equivalent || !no_safepoint_check, "invariant");
-  // !no_safepoint_check logically implies java_thread
-  guarantee(no_safepoint_check || self->is_Java_thread(), "invariant");
-
 #ifdef ASSERT
-  Monitor * least = get_least_ranked_lock_besides_this(self->owned_locks());
+void Monitor::assert_wait_lock_state(Thread* self) {
+  Monitor* least = get_least_ranked_lock_besides_this(self->owned_locks());
   assert(least != this, "Specification of get_least_... call above");
   if (least != NULL && least->rank() <= special) {
     ::tty->print("Attempting to wait on monitor %s/%d while holding"
@@ -168,60 +156,85 @@
                name(), rank(), least->name(), least->rank());
     assert(false, "Shouldn't block(wait) while holding a lock of rank special");
   }
+}
 #endif // ASSERT
 
+bool Monitor::wait_without_safepoint_check(long timeout) {
+  Thread* const self = Thread::current();
+  check_safepoint_state(self, false);
+
+  // timeout is in milliseconds - with zero meaning never timeout
+  assert(timeout >= 0, "negative timeout");
+
+  assert_owner(self);
+  assert_wait_lock_state(self);
+
+  // conceptually set the owner to NULL in anticipation of
+  // abdicating the lock in wait
+  set_owner(NULL);
+  int wait_status = _lock.wait(timeout);
+  set_owner(self);
+  return wait_status != 0;          // return true IFF timeout
+}
+
+bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
+  Thread* const self = Thread::current();
+  check_safepoint_state(self, true);
+
+  // timeout is in milliseconds - with zero meaning never timeout
+  assert(timeout >= 0, "negative timeout");
+
+  assert_owner(self);
+
+  // Safepoint checking logically implies java_thread
+  guarantee(self->is_Java_thread(), "invariant");
+  assert_wait_lock_state(self);
+
 #ifdef CHECK_UNHANDLED_OOPS
   // Clear unhandled oops in JavaThreads so we get a crash right away.
-  if (self->is_Java_thread() && !no_safepoint_check) {
-    self->clear_unhandled_oops();
-  }
+  self->clear_unhandled_oops();
 #endif // CHECK_UNHANDLED_OOPS
 
   int wait_status;
   // conceptually set the owner to NULL in anticipation of
   // abdicating the lock in wait
   set_owner(NULL);
-  if (no_safepoint_check) {
+  JavaThread *jt = (JavaThread *)self;
+  Monitor* in_flight_monitor = NULL;
+
+  {
+    ThreadBlockInVMWithDeadlockCheck tbivmdc(jt, &in_flight_monitor);
+    OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */);
+    if (as_suspend_equivalent) {
+      jt->set_suspend_equivalent();
+      // cleared by handle_special_suspend_equivalent_condition() or
+      // java_suspend_self()
+    }
+
     wait_status = _lock.wait(timeout);
+    in_flight_monitor = this;  // save for ~ThreadBlockInVMWithDeadlockCheck
+
+    // were we externally suspended while we were waiting?
+    if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) {
+      // Our event wait has finished and we own the lock, but
+      // while we were waiting another thread suspended us. We don't
+      // want to hold the lock while suspended because that
+      // would surprise the thread that suspended us.
+      _lock.unlock();
+      jt->java_suspend_self();
+      _lock.lock();
+    }
+  }
+
+  if (in_flight_monitor != NULL) {
+    // Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
+    assert_owner(NULL);
+    // Conceptually reestablish ownership of the lock.
     set_owner(self);
   } else {
-    assert(self->is_Java_thread(), "invariant");
-    JavaThread *jt = (JavaThread *)self;
-    Monitor* in_flight_monitor = NULL;
-
-    {
-      ThreadBlockInVMWithDeadlockCheck tbivmdc(jt, &in_flight_monitor);
-      OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */);
-      if (as_suspend_equivalent) {
-        jt->set_suspend_equivalent();
-        // cleared by handle_special_suspend_equivalent_condition() or
-        // java_suspend_self()
-      }
-
-      wait_status = _lock.wait(timeout);
-      in_flight_monitor = this;  // save for ~ThreadBlockInVMWithDeadlockCheck
+    lock(self);
+  }
 
-      // were we externally suspended while we were waiting?
-      if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) {
-        // Our event wait has finished and we own the lock, but
-        // while we were waiting another thread suspended us. We don't
-        // want to hold the lock while suspended because that
-        // would surprise the thread that suspended us.
-        _lock.unlock();
-        jt->java_suspend_self();
-        _lock.lock();
-      }
-    }
-
-    if (in_flight_monitor != NULL) {
-      // Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
-      assert_owner(NULL);
-      // Conceptually reestablish ownership of the lock.
-      set_owner(self);
-    } else {
-      lock(self);
-    }
-  }
   return wait_status != 0;          // return true IFF timeout
 }
 
@@ -262,6 +275,12 @@
   ClearMonitor(this);
 }
 
+
+// Only Threads_lock, Heap_lock and SR_lock may be safepoint_check_sometimes.
+bool is_sometimes_ok(const char* name) {
+  return (strcmp(name, "Threads_lock") == 0 || strcmp(name, "Heap_lock") == 0 || strcmp(name, "SR_lock") == 0);
+}
+
 Monitor::Monitor(int Rank, const char * name, bool allow_vm_block,
                  SafepointCheckRequired safepoint_check_required) {
   assert(os::mutex_init_done(), "Too early!");
@@ -270,6 +289,9 @@
   _allow_vm_block  = allow_vm_block;
   _rank            = Rank;
   NOT_PRODUCT(_safepoint_check_required = safepoint_check_required;)
+
+  assert(_safepoint_check_required != Monitor::_safepoint_check_sometimes || is_sometimes_ok(name),
+         "Lock has _safepoint_check_sometimes %s", name);
 #endif
 }
 
@@ -280,6 +302,9 @@
   _allow_vm_block   = allow_vm_block;
   _rank             = Rank;
   NOT_PRODUCT(_safepoint_check_required = safepoint_check_required;)
+
+  assert(_safepoint_check_required != Monitor::_safepoint_check_sometimes || is_sometimes_ok(name),
+         "Lock has _safepoint_check_sometimes %s", name);
 #endif
 }
 
--- a/src/hotspot/share/runtime/mutex.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/mutex.hpp	Fri May 03 14:59:32 2019 -0400
@@ -92,32 +92,49 @@
   void set_owner_implementation(Thread* owner)                        PRODUCT_RETURN;
   void check_prelock_state     (Thread* thread, bool safepoint_check) PRODUCT_RETURN;
   void check_block_state       (Thread* thread)                       PRODUCT_RETURN;
+  void check_safepoint_state   (Thread* thread, bool safepoint_check) NOT_DEBUG_RETURN;
   void assert_owner            (Thread* expected)                     NOT_DEBUG_RETURN;
+  void assert_wait_lock_state  (Thread* self)                         NOT_DEBUG_RETURN;
 
  public:
   enum {
-    _no_safepoint_check_flag    = true,
     _allow_vm_block_flag        = true,
     _as_suspend_equivalent_flag = true
   };
 
-  // Locks can be acquired with or without safepoint check.
-  // Monitor::lock and Monitor::lock_without_safepoint_check
-  // checks these flags when acquiring a lock to ensure
-  // consistent checking for each lock.
-  // A few existing locks will sometimes have a safepoint check and
-  // sometimes not, but these locks are set up in such a way to avoid deadlocks.
-  // Note: monitors that may be shared between JavaThreads and the VMThread
-  // should never encounter a safepoint check whilst they are held, else a
-  // deadlock with the VMThread can occur.
+  // Locks can be acquired with or without a safepoint check. NonJavaThreads do not follow
+  // the safepoint protocol when acquiring locks.
+
+  // Each lock can be acquired by only JavaThreads, only NonJavaThreads, or shared between
+  // Java and NonJavaThreads. When the lock is initialized with _safepoint_check_always,
+  // that means that whenever the lock is acquired by a JavaThread, it will verify that
+  // it is done with a safepoint check. In corollary, when the lock is initialized with
+  // _safepoint_check_never, that means that whenever the lock is acquired by a JavaThread
+  // it will verify that it is done without a safepoint check.
+
+
+  // There are a couple of existing locks that will sometimes have a safepoint check and
+  // sometimes not when acquired by a JavaThread, but these locks are set up carefully
+  // to avoid deadlocks. TODO: Fix these locks and remove _safepoint_check_sometimes.
+
+  // TODO: Locks that are shared between JavaThreads and NonJavaThreads
+  // should never encounter a safepoint check while they are held, or else a
+  // deadlock can occur. We should check this by noting which
+  // locks are shared, and walk held locks during safepoint checking.
+
+  enum SafepointCheckFlag {
+    _safepoint_check_flag,
+    _no_safepoint_check_flag
+  };
+
   enum SafepointCheckRequired {
     _safepoint_check_never,       // Monitors with this value will cause errors
-                                  // when acquired with a safepoint check.
-    _safepoint_check_sometimes,   // Certain locks are called sometimes with and
-                                  // sometimes without safepoint checks. These
+                                  // when acquired by a JavaThread with a safepoint check.
+    _safepoint_check_sometimes,   // A couple of special locks are acquired by JavaThreads sometimes
+                                  // with and sometimes without safepoint checks. These
                                   // locks will not produce errors when locked.
-    _safepoint_check_always       // Causes error if locked without a safepoint
-                                  // check.
+    _safepoint_check_always       // Monitors with this value will cause errors
+                                  // when acquired by a JavaThread without a safepoint check.
   };
 
   NOT_PRODUCT(SafepointCheckRequired _safepoint_check_required;)
@@ -135,9 +152,9 @@
   // Defaults are to make safepoint checks, wait time is forever (i.e.,
   // zero), and not a suspend-equivalent condition. Returns true if wait
   // times out; otherwise returns false.
-  bool wait(bool no_safepoint_check = !_no_safepoint_check_flag,
-            long timeout = 0,
+  bool wait(long timeout = 0,
             bool as_suspend_equivalent = !_as_suspend_equivalent_flag);
+  bool wait_without_safepoint_check(long timeout = 0);
   void notify();
   void notify_all();
 
@@ -154,7 +171,7 @@
   // Lock without safepoint check. Should ONLY be used by safepoint code and other code
   // that is guaranteed not to block while running inside the VM.
   void lock_without_safepoint_check();
-  void lock_without_safepoint_check (Thread * Self) ;
+  void lock_without_safepoint_check(Thread* self);
 
   // Current owner - not not MT-safe. Can only be used to guarantee that
   // the current running thread owns the lock
@@ -220,21 +237,19 @@
 // An even better alternative is to simply eliminate Mutex:: and use Monitor:: instead.
 // After all, monitors are sufficient for Java-level synchronization.   At one point in time
 // there may have been some benefit to having distinct mutexes and monitors, but that time
-// has past.
+// has passed.
 //
 
 class Mutex : public Monitor {      // degenerate Monitor
  public:
    Mutex(int rank, const char *name, bool allow_vm_block = false,
          SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
-  // default destructor
+   // default destructor
  private:
-   void notify ()    { ShouldNotReachHere(); }
-   void notify_all() { ShouldNotReachHere(); }
-   bool wait (bool no_safepoint_check, long timeout, bool as_suspend_equivalent) {
-     ShouldNotReachHere() ;
-     return false ;
-   }
+   void notify();
+   void notify_all();
+   bool wait(long timeout, bool as_suspend_equivalent);
+   bool wait_without_safepoint_check(long timeout);
 };
 
 class PaddedMutex : public Mutex {
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Fri May 03 14:59:32 2019 -0400
@@ -157,6 +157,13 @@
 Mutex*   CDSClassFileStream_lock      = NULL;
 #endif
 
+#if INCLUDE_JVMCI
+Monitor* JVMCI_lock                   = NULL;
+Mutex*   JVMCIGlobalAlloc_lock        = NULL;
+Mutex*   JVMCIGlobalActive_lock       = NULL;
+#endif
+
+
 #define MAX_NUM_MUTEX 128
 static Monitor * _mutex_array[MAX_NUM_MUTEX];
 static int _num_mutex;
@@ -216,9 +223,7 @@
   def(ResolvedMethodTableWeakAlloc_lock    , PaddedMutex  , vmweak,      true,  Monitor::_safepoint_check_never);
   def(ResolvedMethodTableWeakActive_lock   , PaddedMutex  , vmweak-1,    true,  Monitor::_safepoint_check_never);
 
-  if (UseConcMarkSweepGC || UseG1GC) {
-    def(FullGCCount_lock           , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);      // in support of ExplicitGCInvokesConcurrent
-  }
+  def(FullGCCount_lock             , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);      // in support of ExplicitGCInvokesConcurrent
   if (UseG1GC) {
     def(SATB_Q_CBL_mon             , PaddedMonitor, access,      true,  Monitor::_safepoint_check_never);
 
@@ -243,53 +248,53 @@
     def(StringDedupQueue_lock      , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);
     def(StringDedupTable_lock      , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
   }
-  def(ParGCRareEvent_lock          , PaddedMutex  , leaf     ,   true,  Monitor::_safepoint_check_sometimes);
+  def(ParGCRareEvent_lock          , PaddedMutex  , leaf     ,   true,  Monitor::_safepoint_check_always);
   def(DerivedPointerTableGC_lock   , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
-  def(CGCPhaseManager_lock         , PaddedMonitor, leaf,        false, Monitor::_safepoint_check_sometimes);
+  def(CGCPhaseManager_lock         , PaddedMonitor, leaf,        false, Monitor::_safepoint_check_always);
   def(CodeCache_lock               , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);
   def(RawMonitor_lock              , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);
-  def(OopMapCacheAlloc_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for oop_map_cache allocation.
+  def(OopMapCacheAlloc_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always); // used for oop_map_cache allocation.
 
   def(MetaspaceExpand_lock         , PaddedMutex  , leaf-1,      true,  Monitor::_safepoint_check_never);
   def(ClassLoaderDataGraph_lock    , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
 
   def(Patching_lock                , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);      // used for safepointing and code patching.
   def(Service_lock                 , PaddedMonitor, special,     true,  Monitor::_safepoint_check_never);      // used for service thread operations
-  def(JmethodIdCreation_lock       , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for creating jmethodIDs.
+  def(JmethodIdCreation_lock       , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always); // used for creating jmethodIDs.
 
-  def(SystemDictionary_lock        , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_always);     // lookups done by VM thread
+  def(SystemDictionary_lock        , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_always);
   def(ProtectionDomainSet_lock     , PaddedMutex  , leaf-1,      true,  Monitor::_safepoint_check_never);
-  def(SharedDictionary_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // lookups done by VM thread
+  def(SharedDictionary_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);
   def(Module_lock                  , PaddedMutex  , leaf+2,      true,  Monitor::_safepoint_check_always);
   def(InlineCacheBuffer_lock       , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
   def(VMStatistic_lock             , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always);
-  def(ExpandHeap_lock              , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // Used during compilation by VM thread
+  def(ExpandHeap_lock              , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always); // Used during compilation by VM thread
   def(JNIHandleBlockFreeList_lock  , PaddedMutex  , leaf-1,      true,  Monitor::_safepoint_check_never);      // handles are used by VM thread
   def(SignatureHandlerLibrary_lock , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always);
   def(SymbolArena_lock             , PaddedMutex  , leaf+2,      true,  Monitor::_safepoint_check_never);
-  def(ProfilePrint_lock            , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always);     // serial profile printing
-  def(ExceptionCache_lock          , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always);     // serial profile printing
+  def(ProfilePrint_lock            , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always); // serial profile printing
+  def(ExceptionCache_lock          , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always); // serial profile printing
   def(OsrList_lock                 , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
   def(Debug1_lock                  , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
 #ifndef PRODUCT
-  def(FullGCALot_lock              , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always);     // a lock to make FullGCALot MT safe
+  def(FullGCALot_lock              , PaddedMutex  , leaf,        false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe
 #endif
   def(BeforeExit_lock              , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_always);
-  def(PerfDataMemAlloc_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for allocating PerfData memory for performance data
-  def(PerfDataManager_lock         , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for synchronized access to PerfDataManager resources
+  def(PerfDataMemAlloc_lock        , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always); // used for allocating PerfData memory for performance data
+  def(PerfDataManager_lock         , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_always); // used for synchronized access to PerfDataManager resources
 
   // CMS_modUnionTable_lock                   leaf
   // CMS_bitMap_lock                          leaf 1
   // CMS_freeList_lock                        leaf 2
 
-  def(Threads_lock                 , PaddedMonitor, barrier,     true,  Monitor::_safepoint_check_sometimes);
+  def(Threads_lock                 , PaddedMonitor, barrier,     true,  Monitor::_safepoint_check_sometimes);  // Used for safepoint protocol.
   def(NonJavaThreadsList_lock      , PaddedMutex,   leaf,        true,  Monitor::_safepoint_check_never);
   def(NonJavaThreadsListSync_lock  , PaddedMutex,   leaf,        true,  Monitor::_safepoint_check_never);
 
-  def(VMOperationQueue_lock        , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_sometimes);  // VM_thread allowed to block on these
-  def(VMOperationRequest_lock      , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_sometimes);
+  def(VMOperationQueue_lock        , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_never);  // VM_thread allowed to block on these
+  def(VMOperationRequest_lock      , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);
   def(RetData_lock                 , PaddedMutex  , nonleaf,     false, Monitor::_safepoint_check_always);
-  def(Terminator_lock              , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_sometimes);
+  def(Terminator_lock              , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);
   def(InitCompleted_lock           , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);
   def(VtableStubs_lock             , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
   def(Notify_lock                  , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);
@@ -297,11 +302,11 @@
   def(JNIGlobalActive_lock         , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
   def(JNIWeakAlloc_lock            , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
   def(JNIWeakActive_lock           , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
-  def(JNICritical_lock             , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);     // used for JNI critical regions
+  def(JNICritical_lock             , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always); // used for JNI critical regions
   def(AdapterHandlerLibrary_lock   , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
 
-  def(Heap_lock                    , PaddedMonitor, nonleaf+1,   false, Monitor::_safepoint_check_sometimes);
-  def(JfieldIdCreation_lock        , PaddedMutex  , nonleaf+1,   true,  Monitor::_safepoint_check_always);     // jfieldID, Used in VM_Operation
+  def(Heap_lock                    , PaddedMonitor, nonleaf+1,   false, Monitor::_safepoint_check_sometimes);  // Doesn't safepoint check during termination.
+  def(JfieldIdCreation_lock        , PaddedMutex  , nonleaf+1,   true,  Monitor::_safepoint_check_always); // jfieldID, Used in VM_Operation
 
   def(CompiledIC_lock              , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_never);      // locks VtableStubs_lock, InlineCacheBuffer_lock
   def(CompileTaskAlloc_lock        , PaddedMutex  , nonleaf+2,   true,  Monitor::_safepoint_check_always);
@@ -309,8 +314,8 @@
   def(DirectivesStack_lock         , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);
   def(MultiArray_lock              , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);
 
-  def(JvmtiThreadState_lock        , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // Used by JvmtiThreadState/JvmtiEventController
-  def(Management_lock              , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // used for JVM management
+  def(JvmtiThreadState_lock        , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController
+  def(Management_lock              , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always); // used for JVM management
 
   def(Compile_lock                 , PaddedMutex  , nonleaf+3,   true,  Monitor::_safepoint_check_always);
   def(MethodData_lock              , PaddedMutex  , nonleaf+3,   false, Monitor::_safepoint_check_always);
@@ -320,7 +325,7 @@
   def(Debug2_lock                  , PaddedMutex  , nonleaf+4,   true,  Monitor::_safepoint_check_never);
   def(Debug3_lock                  , PaddedMutex  , nonleaf+4,   true,  Monitor::_safepoint_check_never);
   def(CompileThread_lock           , PaddedMonitor, nonleaf+5,   false, Monitor::_safepoint_check_always);
-  def(PeriodicTask_lock            , PaddedMonitor, nonleaf+5,   true,  Monitor::_safepoint_check_sometimes);
+  def(PeriodicTask_lock            , PaddedMonitor, nonleaf+5,   true,  Monitor::_safepoint_check_always);
   def(RedefineClasses_lock         , PaddedMonitor, nonleaf+5,   true,  Monitor::_safepoint_check_always);
 
   if (WhiteBoxAPI) {
@@ -331,7 +336,7 @@
   def(JfrMsg_lock                  , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_always);
   def(JfrBuffer_lock               , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
   def(JfrStream_lock               , PaddedMutex  , leaf+1,      true,  Monitor::_safepoint_check_never);      // ensure to rank lower than 'safepoint'
-  def(JfrStacktrace_lock           , PaddedMutex  , special,     true,  Monitor::_safepoint_check_sometimes);
+  def(JfrStacktrace_lock           , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);
   def(JfrThreadSampler_lock        , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);
 #endif
 
@@ -340,8 +345,7 @@
 #endif
 
   def(CodeHeapStateAnalytics_lock  , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
-
-  def(NMethodSweeperStats_lock     , PaddedMutex  , special,     true,  Monitor::_safepoint_check_sometimes);
+  def(NMethodSweeperStats_lock     , PaddedMutex  , special,     true,  Monitor::_safepoint_check_never);
   def(ThreadsSMRDelete_lock        , PaddedMonitor, special,     false, Monitor::_safepoint_check_never);
   def(SharedDecoder_lock           , PaddedMutex  , native,      false, Monitor::_safepoint_check_never);
   def(DCmdFactory_lock             , PaddedMutex  , leaf,        true,  Monitor::_safepoint_check_never);
@@ -351,6 +355,12 @@
 #if INCLUDE_CDS && INCLUDE_JVMTI
   def(CDSClassFileStream_lock      , PaddedMutex  , max_nonleaf, false, Monitor::_safepoint_check_always);
 #endif
+
+#if INCLUDE_JVMCI
+  def(JVMCI_lock                   , PaddedMonitor, nonleaf+2,   true,  Monitor::_safepoint_check_always);
+  def(JVMCIGlobalAlloc_lock        , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
+  def(JVMCIGlobalActive_lock       , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
+#endif
 }
 
 GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Fri May 03 14:59:32 2019 -0400
@@ -62,7 +62,7 @@
 extern Mutex*   SymbolArena_lock;                // a lock on the symbol table arena
 extern Monitor* StringDedupQueue_lock;           // a lock on the string deduplication queue
 extern Mutex*   StringDedupTable_lock;           // a lock on the string deduplication table
-extern Monitor* CodeCache_lock;                  // a lock on the CodeCache, rank is special, use MutexLockerEx
+extern Monitor* CodeCache_lock;                  // a lock on the CodeCache, rank is special
 extern Mutex*   MethodData_lock;                 // a lock on installation of method data
 extern Mutex*   TouchedMethodLog_lock;           // a lock on allocation of LogExecutedMethods info
 extern Mutex*   RetData_lock;                    // a lock on installation of RetData inside method data
@@ -155,6 +155,12 @@
 extern Monitor* CodeHeapStateAnalytics_lock;     // lock print functions against concurrent analyze functions.
                                                  // Only used locally in PrintCodeCacheLayout processing.
 
+#if INCLUDE_JVMCI
+extern Monitor* JVMCI_lock;                      // Monitor to control initialization of JVMCI
+extern Mutex*   JVMCIGlobalAlloc_lock;           // JVMCI global storage allocate list lock
+extern Mutex*   JVMCIGlobalActive_lock;          // JVMCI global storage active list lock
+#endif
+
 // A MutexLocker provides mutual exclusion with respect to a given mutex
 // for the scope which contains the locker.  The lock is an OS lock, not
 // an object lock, and the two do not interoperate.  Do not use Mutex-based
@@ -175,31 +181,6 @@
 
 char *lock_name(Mutex *mutex);
 
-class MutexLocker: StackObj {
- private:
-  Monitor * _mutex;
- public:
-  MutexLocker(Monitor * mutex) {
-    assert(mutex->rank() != Mutex::special,
-      "Special ranked mutex should only use MutexLockerEx");
-    _mutex = mutex;
-    _mutex->lock();
-  }
-
-  // Overloaded constructor passing current thread
-  MutexLocker(Monitor * mutex, Thread *thread) {
-    assert(mutex->rank() != Mutex::special,
-      "Special ranked mutex should only use MutexLockerEx");
-    _mutex = mutex;
-    _mutex->lock(thread);
-  }
-
-  ~MutexLocker() {
-    _mutex->unlock();
-  }
-
-};
-
 // for debugging: check that we're already owning this lock (or are at a safepoint)
 #ifdef ASSERT
 void assert_locked_or_safepoint(const Monitor * lock);
@@ -211,84 +192,86 @@
 #define assert_lock_strong(lock)
 #endif
 
-// A MutexLockerEx behaves like a MutexLocker when its constructor is
-// called with a Mutex.  Unlike a MutexLocker, its constructor can also be
-// called with NULL, in which case the MutexLockerEx is a no-op.  There
-// is also a corresponding MutexUnlockerEx.  We want to keep the
-// basic MutexLocker as fast as possible.  MutexLockerEx can also lock
-// without safepoint check.
-
-class MutexLockerEx: public StackObj {
+class MutexLocker: public StackObj {
+ protected:
+  Monitor* _mutex;
  private:
-  Monitor * _mutex;
  public:
-  MutexLockerEx(Monitor * mutex, bool no_safepoint_check = !Mutex::_no_safepoint_check_flag) {
-    _mutex = mutex;
+  MutexLocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
+    _mutex(mutex) {
+    bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
     if (_mutex != NULL) {
-      assert(mutex->rank() > Mutex::special || no_safepoint_check,
-        "Mutexes with rank special or lower should not do safepoint checks");
-      if (no_safepoint_check)
+      assert(_mutex->rank() > Mutex::special || no_safepoint_check,
+             "Mutexes with rank special or lower should not do safepoint checks");
+      if (no_safepoint_check) {
         _mutex->lock_without_safepoint_check();
-      else
+      } else {
         _mutex->lock();
+      }
     }
   }
 
-  ~MutexLockerEx() {
+  MutexLocker(Monitor* mutex, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
+    _mutex(mutex) {
+    bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
     if (_mutex != NULL) {
+      assert(_mutex->rank() > Mutex::special || no_safepoint_check,
+             "Mutexes with rank special or lower should not do safepoint checks");
+      if (no_safepoint_check) {
+        _mutex->lock_without_safepoint_check(thread);
+      } else {
+        _mutex->lock(thread);
+      }
+    }
+  }
+
+  ~MutexLocker() {
+    if (_mutex != NULL) {
+      assert_lock_strong(_mutex);
       _mutex->unlock();
     }
   }
 };
 
-// A MonitorLockerEx is like a MutexLockerEx above, except it takes
-// a possibly null Monitor, and allows wait/notify as well which are
-// delegated to the underlying Monitor.
+// A MonitorLocker is like a MutexLocker above, except it allows
+// wait/notify as well which are delegated to the underlying Monitor.
+// It also disallows NULL.
 
-class MonitorLockerEx: public MutexLockerEx {
- private:
-  Monitor * _monitor;
+class MonitorLocker: public MutexLocker {
+  Mutex::SafepointCheckFlag _flag;
  public:
-  MonitorLockerEx(Monitor* monitor,
-                  bool no_safepoint_check = !Mutex::_no_safepoint_check_flag):
-    MutexLockerEx(monitor, no_safepoint_check),
-    _monitor(monitor) {
+  MonitorLocker(Monitor* monitor, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
+    MutexLocker(monitor, flag), _flag(flag) {
     // Superclass constructor did locking
+    assert(_mutex != NULL, "NULL monitor not allowed");
   }
 
-  ~MonitorLockerEx() {
-    #ifdef ASSERT
-      if (_monitor != NULL) {
-        assert_lock_strong(_monitor);
-      }
-    #endif  // ASSERT
-    // Superclass destructor will do unlocking
+  MonitorLocker(Monitor* monitor, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
+    MutexLocker(monitor, thread, flag), _flag(flag)  {
+    // Superclass constructor did locking
+    assert(_mutex != NULL, "NULL monitor not allowed");
   }
 
-  bool wait(bool no_safepoint_check = !Mutex::_no_safepoint_check_flag,
-            long timeout = 0,
+  bool wait(long timeout = 0,
             bool as_suspend_equivalent = !Mutex::_as_suspend_equivalent_flag) {
-    if (_monitor != NULL) {
-      return _monitor->wait(no_safepoint_check, timeout, as_suspend_equivalent);
+    if (_flag == Mutex::_safepoint_check_flag) {
+      return _mutex->wait(timeout, as_suspend_equivalent);
+    } else {
+      return _mutex->wait_without_safepoint_check(timeout);
     }
     return false;
   }
 
   void notify_all() {
-    if (_monitor != NULL) {
-      _monitor->notify_all();
-    }
+    _mutex->notify_all();
   }
 
   void notify() {
-    if (_monitor != NULL) {
-      _monitor->notify();
-    }
+    _mutex->notify();
   }
 };
 
 
-
 // A GCMutexLocker is usually initialized with a mutex that is
 // automatically acquired in order to do GC.  The function that
 // synchronizes using a GCMutexLocker may be called both during and between
@@ -297,50 +280,30 @@
 
 class GCMutexLocker: public StackObj {
 private:
-  Monitor * _mutex;
+  Monitor* _mutex;
   bool _locked;
 public:
-  GCMutexLocker(Monitor * mutex);
+  GCMutexLocker(Monitor* mutex);
   ~GCMutexLocker() { if (_locked) _mutex->unlock(); }
 };
 
-
-
 // A MutexUnlocker temporarily exits a previously
 // entered mutex for the scope which contains the unlocker.
 
 class MutexUnlocker: StackObj {
  private:
-  Monitor * _mutex;
+  Monitor* _mutex;
+  bool _no_safepoint_check;
 
  public:
-  MutexUnlocker(Monitor * mutex) {
-    _mutex = mutex;
+  MutexUnlocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
+    _mutex(mutex),
+    _no_safepoint_check(flag) {
     _mutex->unlock();
   }
 
   ~MutexUnlocker() {
-    _mutex->lock();
-  }
-};
-
-// A MutexUnlockerEx temporarily exits a previously
-// entered mutex for the scope which contains the unlocker.
-
-class MutexUnlockerEx: StackObj {
- private:
-  Monitor * _mutex;
-  bool _no_safepoint_check;
-
- public:
-  MutexUnlockerEx(Monitor * mutex, bool no_safepoint_check = !Mutex::_no_safepoint_check_flag) {
-    _mutex = mutex;
-    _no_safepoint_check = no_safepoint_check;
-    _mutex->unlock();
-  }
-
-  ~MutexUnlockerEx() {
-    if (_no_safepoint_check == Mutex::_no_safepoint_check_flag) {
+    if (_no_safepoint_check) {
       _mutex->lock_without_safepoint_check();
     } else {
       _mutex->lock();
--- a/src/hotspot/share/runtime/objectMonitor.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.cpp	Fri May 03 14:59:32 2019 -0400
@@ -276,9 +276,13 @@
   // Note that if we acquire the monitor from an initial spin
   // we forgo posting JVMTI events and firing DTRACE probes.
   if (TrySpin(Self) > 0) {
-    assert(_owner == Self, "invariant");
-    assert(_recursions == 0, "invariant");
-    assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
+    assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner));
+    assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT,
+           _recursions);
+    assert(((oop)object())->mark() == markOopDesc::encode(this),
+           "object mark must match encoded this: mark=" INTPTR_FORMAT
+           ", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()),
+           p2i(markOopDesc::encode(this)));
     Self->_Stalled = 0;
     return;
   }
@@ -290,11 +294,11 @@
   assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
   assert(jt->thread_state() != _thread_blocked, "invariant");
   assert(this->object() != NULL, "invariant");
-  assert(_count >= 0, "invariant");
+  assert(_contentions >= 0, "invariant");
 
   // Prevent deflation at STW-time.  See deflate_idle_monitors() and is_busy().
   // Ensure the object-monitor relationship remains stable while there's contention.
-  Atomic::inc(&_count);
+  Atomic::inc(&_contentions);
 
   JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
   EventJavaMonitorEnter event;
@@ -355,8 +359,8 @@
     // acquire it.
   }
 
-  Atomic::dec(&_count);
-  assert(_count >= 0, "invariant");
+  Atomic::dec(&_contentions);
+  assert(_contentions >= 0, "invariant");
   Self->_Stalled = 0;
 
   // Must either set _recursions = 0 or ASSERT _recursions == 0.
@@ -809,7 +813,7 @@
 // There's one exception to the claim above, however.  EnterI() can call
 // exit() to drop a lock if the acquirer has been externally suspended.
 // In that case exit() is called with _thread_state as _thread_blocked,
-// but the monitor's _count field is > 0, which inhibits reclamation.
+// but the monitor's _contentions field is > 0, which inhibits reclamation.
 //
 // 1-0 exit
 // ~~~~~~~~
--- a/src/hotspot/share/runtime/objectMonitor.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.hpp	Fri May 03 14:59:32 2019 -0400
@@ -163,9 +163,9 @@
   volatile int _Spinner;            // for exit->spinner handoff optimization
   volatile int _SpinDuration;
 
-  volatile jint  _count;            // reference count to prevent reclamation/deflation
-                                    // at stop-the-world time. See ObjectSynchronizer::deflate_monitor().
-                                    // _count is approximately |_WaitSet| + |_EntryList|
+  volatile jint  _contentions;      // Number of active contentions in enter(). It is used by is_busy()
+                                    // along with other fields to determine if an ObjectMonitor can be
+                                    // deflated. See ObjectSynchronizer::deflate_monitor().
  protected:
   ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
   volatile jint  _waiters;          // number of waiting threads
@@ -207,7 +207,6 @@
   static int header_offset_in_bytes()      { return offset_of(ObjectMonitor, _header); }
   static int object_offset_in_bytes()      { return offset_of(ObjectMonitor, _object); }
   static int owner_offset_in_bytes()       { return offset_of(ObjectMonitor, _owner); }
-  static int count_offset_in_bytes()       { return offset_of(ObjectMonitor, _count); }
   static int recursions_offset_in_bytes()  { return offset_of(ObjectMonitor, _recursions); }
   static int cxq_offset_in_bytes()         { return offset_of(ObjectMonitor, _cxq); }
   static int succ_offset_in_bytes()        { return offset_of(ObjectMonitor, _succ); }
@@ -232,10 +231,8 @@
   void      set_header(markOop hdr);
 
   intptr_t is_busy() const {
-    // TODO-FIXME: merge _count and _waiters.
     // TODO-FIXME: assert _owner == null implies _recursions = 0
-    // TODO-FIXME: assert _WaitSet != null implies _count > 0
-    return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList);
+    return _contentions|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList);
   }
 
   intptr_t  is_entered(Thread* current) const;
@@ -245,8 +242,6 @@
 
   jint      waiters() const;
 
-  jint      count() const;
-  void      set_count(jint count);
   jint      contentions() const;
   intptr_t  recursions() const                                         { return _recursions; }
 
@@ -263,14 +258,14 @@
   ~ObjectMonitor() {
     // TODO: Add asserts ...
     // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
-    // _count == 0 _EntryList  == NULL etc
+    // _contentions == 0 _EntryList  == NULL etc
   }
 
  private:
   void Recycle() {
     // TODO: add stronger asserts ...
     // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
-    // _count == 0 EntryList  == NULL
+    // _contentions == 0 EntryList  == NULL
     // _recursions == 0 _WaitSet == NULL
     assert(((is_busy()|_recursions) == 0), "freeing inuse monitor");
     _succ          = NULL;
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -45,10 +45,6 @@
   _header = hdr;
 }
 
-inline jint ObjectMonitor::count() const {
-  return _count;
-}
-
 inline jint ObjectMonitor::waiters() const {
   return _waiters;
 }
@@ -58,12 +54,12 @@
 }
 
 inline void ObjectMonitor::clear() {
-  assert(_header != NULL, "Fatal logic error in ObjectMonitor header!");
-  assert(_count == 0, "Fatal logic error in ObjectMonitor count!");
-  assert(_waiters == 0, "Fatal logic error in ObjectMonitor waiters!");
-  assert(_recursions == 0, "Fatal logic error in ObjectMonitor recursions!");
-  assert(_object != NULL, "Fatal logic error in ObjectMonitor object!");
-  assert(_owner == NULL, "Fatal logic error in ObjectMonitor owner!");
+  assert(_header != NULL, "must be non-NULL");
+  assert(_contentions == 0, "must be 0: contentions=%d", _contentions);
+  assert(_waiters == 0, "must be 0: waiters=%d", _waiters);
+  assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT, _recursions);
+  assert(_object != NULL, "must be non-NULL");
+  assert(_owner == NULL, "must be NULL: owner=" INTPTR_FORMAT, p2i(_owner));
 
   _header = NULL;
   _object = NULL;
@@ -96,10 +92,10 @@
 
 // return number of threads contending for this monitor
 inline jint ObjectMonitor::contentions() const {
-  return _count;
+  return _contentions;
 }
 
-// Do NOT set _count = 0. There is a race such that _count could
+// Do NOT set _contentions = 0. There is a race such that _contentions could
 // be set while inflating prior to setting _owner
 // Just use Atomic::inc/dec and assert 0 when monitor put on free list
 inline void ObjectMonitor::set_owner(void* owner) {
--- a/src/hotspot/share/runtime/os.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/os.cpp	Fri May 03 14:59:32 2019 -0400
@@ -858,7 +858,7 @@
 
 void os::start_thread(Thread* thread) {
   // guard suspend/resume
-  MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
   OSThread* osthread = thread->osthread();
   osthread->set_state(RUNNABLE);
   pd_start_thread(thread);
--- a/src/hotspot/share/runtime/safepoint.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/safepoint.cpp	Fri May 03 14:59:32 2019 -0400
@@ -186,16 +186,14 @@
 }
 #endif // ASSERT
 
-static void back_off(int iteration) {
-  // iteration will be 1 the first time we enter this spin back-off.
-  // naked_short_nanosleep takes tenths of micros which means that
-  // number of nanoseconds is irrelevant if it's below that. We do
-  // 20 1 ns sleeps with a total cost of ~1 ms, then we do 1 ms sleeps.
-  jlong sleep_ns = 1;
-  if (iteration > 20) {
-    sleep_ns = NANOUNITS / MILLIUNITS;  // 1 ms
+static void back_off(int64_t start_time) {
+  // We start with fine-grained nanosleeping until a millisecond has
+  // passed, at which point we resort to plain naked_short_sleep.
+  if (os::javaTimeNanos() - start_time < NANOSECS_PER_MILLISEC) {
+    os::naked_short_nanosleep(10 * (NANOUNITS / MICROUNITS));
+  } else {
+    os::naked_short_sleep(1);
   }
-  os::naked_short_nanosleep(sleep_ns);
 }
 
 int SafepointSynchronize::synchronize_threads(jlong safepoint_limit_time, int nof_threads, int* initial_running)
@@ -229,9 +227,16 @@
 
   *initial_running = still_running;
 
-  int iterations = 1; // The first iteration is above.
+  // If there is no thread still running, we are already done.
+  if (still_running <= 0) {
+    assert(tss_head == NULL, "Must be empty");
+    return 1;
+  }
 
-  while (still_running > 0) {
+  int iterations = 1; // The first iteration is above.
+  int64_t start_time = os::javaTimeNanos();
+
+  do {
     // Check if this has taken too long:
     if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
       print_safepoint_timeout();
@@ -264,11 +269,11 @@
     DEBUG_ONLY(assert_list_is_valid(tss_head, still_running);)
 
     if (still_running > 0) {
-      back_off(iterations);
+      back_off(start_time);
     }
 
     iterations++;
-  }
+  } while (still_running > 0);
 
   assert(tss_head == NULL, "Must be empty");
 
--- a/src/hotspot/share/runtime/serviceThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/serviceThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -138,7 +138,7 @@
 
       ThreadBlockInVM tbivm(jt);
 
-      MonitorLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+      MonitorLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
       // Process all available work on each (outer) iteration, rather than
       // only the first recognized bit of work, to avoid frequently true early
       // tests from potentially starving later work.  Hence the use of
@@ -157,7 +157,7 @@
 
              == 0) {
         // Wait until notified that there is some work to do.
-        ml.wait(Mutex::_no_safepoint_check_flag);
+        ml.wait();
       }
 
       if (has_jvmti_events) {
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Fri May 03 14:59:32 2019 -0400
@@ -2256,7 +2256,7 @@
 
  public:
   MethodArityHistogram() {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     _max_arity = _max_size = 0;
     for (int i = 0; i < MAX_ARITY; i++) _arity_histogram[i] = _size_histogram[i] = 0;
     CodeCache::nmethods_do(add_method_to_histogram);
--- a/src/hotspot/share/runtime/sweeper.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/sweeper.cpp	Fri May 03 14:59:32 2019 -0400
@@ -322,7 +322,7 @@
     if (ThreadLocalHandshakes) {
       CodeBlobClosure* code_cl;
       {
-        MutexLockerEx ccl(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+        MutexLocker ccl(CodeCache_lock, Mutex::_no_safepoint_check_flag);
         code_cl = prepare_mark_active_nmethods();
       }
       if (code_cl != NULL) {
@@ -341,9 +341,9 @@
   while (true) {
     {
       ThreadBlockInVM tbivm(JavaThread::current());
-      MutexLockerEx waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      MonitorLocker waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       const long wait_time = 60*60*24 * 1000;
-      timeout = CodeCache_lock->wait(Mutex::_no_safepoint_check_flag, wait_time);
+      timeout = waiter.wait(wait_time);
     }
     if (!timeout) {
       possibly_sweep();
@@ -369,7 +369,7 @@
   */
 void NMethodSweeper::force_sweep() {
   ThreadBlockInVM tbivm(JavaThread::current());
-  MutexLockerEx waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   // Request forced sweep
   _force_sweep = true;
   while (_force_sweep) {
@@ -377,7 +377,7 @@
     // In case a sweep currently takes place we timeout and try again because
     // we want to enforce a full sweep.
     CodeCache_lock->notify();
-    CodeCache_lock->wait(Mutex::_no_safepoint_check_flag, 1000);
+    waiter.wait(1000);
   }
 }
 
@@ -390,7 +390,7 @@
     if (PrintMethodFlushing && Verbose) {
       tty->print_cr("### Sweep at %d out of %d, yielding to safepoint", _seen, CodeCache::nmethod_count());
     }
-    MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexUnlocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
     ThreadBlockInVM tbivm(thread);
     thread->java_suspend_self();
@@ -475,7 +475,7 @@
   if (forced) {
     // Notify requester that forced sweep finished
     assert(_force_sweep, "Should be a forced sweep");
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     _force_sweep = false;
     CodeCache_lock->notify();
   }
@@ -519,7 +519,7 @@
 
   int freed_memory = 0;
   {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
     while (!_current.end()) {
       swept_count++;
@@ -531,7 +531,7 @@
 
       // Now ready to process nmethod and give up CodeCache_lock
       {
-        MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+        MutexUnlocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
         // Save information before potentially flushing the nmethod
         // Only flushing nmethods so size only matters for them.
         int size = nm->is_nmethod() ? ((nmethod*)nm)->total_size() : 0;
@@ -576,7 +576,7 @@
   const Ticks sweep_end_counter = Ticks::now();
   const Tickspan sweep_time = sweep_end_counter - sweep_start_counter;
   {
-    MutexLockerEx mu(NMethodSweeperStats_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(NMethodSweeperStats_lock, Mutex::_no_safepoint_check_flag);
     _total_time_sweeping  += sweep_time;
     _total_time_this_sweep += sweep_time;
     _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
--- a/src/hotspot/share/runtime/synchronizer.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/synchronizer.cpp	Fri May 03 14:59:32 2019 -0400
@@ -735,7 +735,7 @@
   } else if (mark->has_monitor()) {
     monitor = mark->monitor();
     temp = monitor->header();
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     hash = temp->hash();
     if (hash != 0) {
       return hash;
@@ -743,39 +743,38 @@
     // Skip to the following code to reduce code size
   } else if (Self->is_lock_owned((address)mark->locker())) {
     temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     hash = temp->hash();              // by current thread, check if the displaced
     if (hash != 0) {                  // header contains hash code
       return hash;
     }
     // WARNING:
-    //   The displaced header is strictly immutable.
-    // It can NOT be changed in ANY cases. So we have
-    // to inflate the header into heavyweight monitor
-    // even the current thread owns the lock. The reason
-    // is the BasicLock (stack slot) will be asynchronously
-    // read by other threads during the inflate() function.
-    // Any change to stack may not propagate to other threads
-    // correctly.
+    // The displaced header in the BasicLock on a thread's stack
+    // is strictly immutable. It CANNOT be changed in ANY cases.
+    // So we have to inflate the stack lock into an ObjectMonitor
+    // even if the current thread owns the lock. The BasicLock on
+    // a thread's stack can be asynchronously read by other threads
+    // during an inflate() call so any change to that stack memory
+    // may not propagate to other threads correctly.
   }
 
   // Inflate the monitor to set hash code
   monitor = inflate(Self, obj, inflate_cause_hash_code);
   // Load displaced header and check it has hash code
   mark = monitor->header();
-  assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)mark));
+  assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
   hash = mark->hash();
   if (hash == 0) {
     hash = get_next_hash(Self, obj);
     temp = mark->copy_set_hash(hash); // merge hash code into header
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     test = Atomic::cmpxchg(temp, monitor->header_addr(), mark);
     if (test != mark) {
-      // The only update to the header in the monitor (outside GC)
-      // is install the hash code. If someone add new usage of
-      // displaced header, please update this code
+      // The only update to the ObjectMonitor's header/dmw field
+      // is to merge in the hash code. If someone adds a new usage
+      // of the header/dmw field, please update this code.
       hash = test->hash();
-      assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)test));
+      assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(test));
       assert(hash != 0, "Trivial unexpected object/monitor header usage.");
     }
   }
@@ -1334,7 +1333,7 @@
     if (mark->has_monitor()) {
       ObjectMonitor * inf = mark->monitor();
       markOop dmw = inf->header();
-      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)dmw));
+      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
       assert(oopDesc::equals((oop) inf->object(), object), "invariant");
       assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
       return inf;
@@ -1398,7 +1397,7 @@
       // Consider what happens when a thread unlocks a stack-locked object.
       // It attempts to use CAS to swing the displaced header value from the
       // on-stack basiclock back into the object header.  Recall also that the
-      // header value (hashcode, etc) can reside in (a) the object header, or
+      // header value (hash code, etc) can reside in (a) the object header, or
       // (b) a displaced header associated with the stack-lock, or (c) a displaced
       // header in an objectMonitor.  The inflate() routine must copy the header
       // value from the basiclock on the owner's stack to the objectMonitor, all
@@ -1419,7 +1418,9 @@
       // object is in the mark.  Furthermore the owner can't complete
       // an unlock on the object, either.
       markOop dmw = mark->displaced_mark_helper();
-      assert(dmw->is_neutral(), "invariant");
+      // Catch if the object's header is not neutral (not locked and
+      // not marked is what we care about here).
+      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
 
       // Setup monitor fields to proper values -- prepare the monitor
       m->set_header(dmw);
@@ -1463,7 +1464,9 @@
     // An inflateTry() method that we could call from fast_enter() and slow_enter()
     // would be useful.
 
-    assert(mark->is_neutral(), "invariant");
+    // Catch if the object's header is not neutral (not locked and
+    // not marked is what we care about here).
+    assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
     ObjectMonitor * m = omAlloc(Self);
     // prepare m for installation - set monitor to initial state
     m->Recycle();
@@ -1503,7 +1506,7 @@
 }
 
 
-// We create a list of in-use monitors for each thread.
+// We maintain a list of in-use monitors for each thread.
 //
 // deflate_thread_local_monitors() scans a single thread's in-use list, while
 // deflate_idle_monitors() scans only a global list of in-use monitors which
@@ -1512,7 +1515,7 @@
 // These operations are called at all safepoints, immediately after mutators
 // are stopped, but before any objects have moved. Collectively they traverse
 // the population of in-use monitors, deflating where possible. The scavenged
-// monitors are returned to the monitor free list.
+// monitors are returned to the global monitor free list.
 //
 // Beware that we scavenge at *every* stop-the-world point. Having a large
 // number of monitors in-use could negatively impact performance. We also want
@@ -1521,7 +1524,7 @@
 //
 // Perversely, the heap size -- and thus the STW safepoint rate --
 // typically drives the scavenge rate.  Large heaps can mean infrequent GC,
-// which in turn can mean large(r) numbers of objectmonitors in circulation.
+// which in turn can mean large(r) numbers of ObjectMonitors in circulation.
 // This is an unfortunate aspect of this design.
 
 // Deflate a single monitor if not in-use
@@ -1531,9 +1534,15 @@
                                          ObjectMonitor** freeTailp) {
   bool deflated;
   // Normal case ... The monitor is associated with obj.
-  guarantee(obj->mark() == markOopDesc::encode(mid), "invariant");
-  guarantee(mid == obj->mark()->monitor(), "invariant");
-  guarantee(mid->header()->is_neutral(), "invariant");
+  const markOop mark = obj->mark();
+  guarantee(mark == markOopDesc::encode(mid), "should match: mark="
+            INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, p2i(mark),
+            p2i(markOopDesc::encode(mid)));
+  // Make sure that mark->monitor() and markOopDesc::encode() agree:
+  guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
+            ", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid));
+  const markOop dmw = mid->header();
+  guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
 
   if (mid->is_busy()) {
     deflated = false;
@@ -1544,16 +1553,17 @@
     if (log_is_enabled(Trace, monitorinflation)) {
       ResourceMark rm;
       log_trace(monitorinflation)("deflate_monitor: "
-                                  "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'",
-                                  p2i(obj), p2i(obj->mark()),
-                                  obj->klass()->external_name());
+                                  "object=" INTPTR_FORMAT ", mark="
+                                  INTPTR_FORMAT ", type='%s'", p2i(obj),
+                                  p2i(mark), obj->klass()->external_name());
     }
 
     // Restore the header back to obj
-    obj->release_set_mark(mid->header());
+    obj->release_set_mark(dmw);
     mid->clear();
 
-    assert(mid->object() == NULL, "invariant");
+    assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT,
+           p2i(mid->object()));
 
     // Move the object to the working free list defined by freeHeadp, freeTailp
     if (*freeHeadp == NULL) *freeHeadp = mid;
@@ -2022,13 +2032,12 @@
       out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
                     ": in-use per-thread monitor's object does not think "
                     "it has a monitor: obj=" INTPTR_FORMAT ", mark="
-                    INTPTR_FORMAT,  p2i(jt), p2i(n), p2i((address)obj),
-                    p2i((address)mark));
+                    INTPTR_FORMAT,  p2i(jt), p2i(n), p2i(obj), p2i(mark));
     } else {
       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
                     "monitor's object does not think it has a monitor: obj="
                     INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
-                    p2i((address)obj), p2i((address)mark));
+                    p2i(obj), p2i(mark));
     }
     *error_cnt_p = *error_cnt_p + 1;
   }
@@ -2039,14 +2048,12 @@
                     ": in-use per-thread monitor's object does not refer "
                     "to the same monitor: obj=" INTPTR_FORMAT ", mark="
                     INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt),
-                    p2i(n), p2i((address)obj), p2i((address)mark),
-                    p2i((address)obj_mon));
+                    p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
     } else {
       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
                     "monitor's object does not refer to the same monitor: obj="
                     INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon="
-                    INTPTR_FORMAT, p2i(n), p2i((address)obj),
-                    p2i((address)mark), p2i((address)obj_mon));
+                    INTPTR_FORMAT, p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
     }
     *error_cnt_p = *error_cnt_p + 1;
   }
@@ -2105,7 +2112,7 @@
 
   if (gOmInUseCount > 0) {
     out->print_cr("In-use global monitor info:");
-    out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)");
+    out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
     out->print_cr("%18s  %s  %18s  %18s",
                   "monitor", "BHL", "object", "object type");
     out->print_cr("==================  ===  ==================  ==================");
@@ -2124,7 +2131,7 @@
   }
 
   out->print_cr("In-use per-thread monitor info:");
-  out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)");
+  out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
   out->print_cr("%18s  %18s  %s  %18s  %18s",
                 "jt", "monitor", "BHL", "object", "object type");
   out->print_cr("==================  ==================  ===  ==================  ==================");
--- a/src/hotspot/share/runtime/task.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/task.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
 
   // The WatcherThread does not participate in the safepoint protocol
   // for the PeriodicTask_lock because it is not a JavaThread.
-  MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
   int orig_num_tasks = _num_tasks;
 
   for(int index = 0; index < _num_tasks; index++) {
@@ -84,8 +84,7 @@
   // not already own the PeriodicTask_lock. Otherwise, we don't try to
   // enter it again because VM internal Mutexes do not support recursion.
   //
-  MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? NULL
-                                                      : PeriodicTask_lock);
+  MutexLocker ml(PeriodicTask_lock->owned_by_self() ? NULL : PeriodicTask_lock);
 
   if (_num_tasks == PeriodicTask::max_tasks) {
     fatal("Overflow in PeriodicTask table");
@@ -107,8 +106,7 @@
   // not already own the PeriodicTask_lock. Otherwise, we don't try to
   // enter it again because VM internal Mutexes do not support recursion.
   //
-  MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? NULL
-                                                      : PeriodicTask_lock);
+  MutexLocker ml(PeriodicTask_lock->owned_by_self() ? NULL : PeriodicTask_lock);
 
   int index;
   for(index = 0; index < _num_tasks && _tasks[index] != this; index++)
--- a/src/hotspot/share/runtime/thread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/thread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -117,9 +117,8 @@
 #include "utilities/singleWriterSynchronizer.hpp"
 #include "utilities/vmError.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#include "logging/logHandle.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #endif
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
@@ -718,7 +717,11 @@
         // temporarily drops SR_lock while doing wait with safepoint check
         // (if we're a JavaThread - the WatcherThread can also call this)
         // and increase delay with each retry
-        SR_lock()->wait(!Thread::current()->is_Java_thread(), i * delay);
+        if (Thread::current()->is_Java_thread()) {
+          SR_lock()->wait(i * delay);
+        } else {
+          SR_lock()->wait_without_safepoint_check(i * delay);
+        }
 
         // check the actual thread state instead of what we saved above
         if (thread_state() != _thread_in_native_trans) {
@@ -759,7 +762,7 @@
   reset_bits = *bits;
 
   {
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     is_suspended = is_ext_suspend_completed(true /* called_by_wait */,
                                             delay, bits);
     pending = is_external_suspend();
@@ -790,10 +793,12 @@
     // safepoint requests from the VMThread
 
     {
-      MutexLocker ml(SR_lock());
+      Thread* t = Thread::current();
+      MonitorLocker ml(SR_lock(),
+                       t->is_Java_thread() ? Mutex::_safepoint_check_flag : Mutex::_no_safepoint_check_flag);
       // wait with safepoint check (if we're a JavaThread - the WatcherThread
       // can also call this)  and increase delay with each retry
-      SR_lock()->wait(!Thread::current()->is_Java_thread(), i * delay);
+      ml.wait(i * delay);
 
       is_suspended = is_ext_suspend_completed(true /* called_by_wait */,
                                               delay, bits);
@@ -1289,7 +1294,7 @@
 NonJavaThread::~NonJavaThread() { }
 
 void NonJavaThread::add_to_the_list() {
-  MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
   // Initialize BarrierSet-related data before adding to list.
   BarrierSet::barrier_set()->on_thread_attach(this);
   OrderAccess::release_store(&_next, _the_list._head);
@@ -1298,7 +1303,7 @@
 
 void NonJavaThread::remove_from_the_list() {
   {
-    MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
     // Cleanup BarrierSet-related data before removing from list.
     BarrierSet::barrier_set()->on_thread_detach(this);
     NonJavaThread* volatile* p = &_the_list._head;
@@ -1312,7 +1317,7 @@
   // Wait for any in-progress iterators.  Concurrent synchronize is not
   // allowed, so do it while holding a dedicated lock.  Outside and distinct
   // from NJTList_lock in case an iteration attempts to lock it.
-  MutexLockerEx ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag);
   _the_list._protect.synchronize();
   _next = NULL;                 // Safe to drop the link now.
 }
@@ -1397,7 +1402,7 @@
 int WatcherThread::sleep() const {
   // The WatcherThread does not participate in the safepoint protocol
   // for the PeriodicTask_lock because it is not a JavaThread.
-  MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
 
   if (_should_terminate) {
     // check for termination before we do any housekeeping or wait
@@ -1417,8 +1422,7 @@
   jlong time_before_loop = os::javaTimeNanos();
 
   while (true) {
-    bool timedout = PeriodicTask_lock->wait(Mutex::_no_safepoint_check_flag,
-                                            remaining);
+    bool timedout = ml.wait(remaining);
     jlong now = os::javaTimeNanos();
 
     if (remaining == 0) {
@@ -1506,7 +1510,7 @@
 
   // Signal that it is terminated
   {
-    MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
     _watcher_thread = NULL;
     Terminator_lock->notify_all();
   }
@@ -1541,13 +1545,12 @@
     }
   }
 
-  MutexLocker mu(Terminator_lock);
+  MonitorLocker mu(Terminator_lock);
 
   while (watcher_thread() != NULL) {
     // This wait should make safepoint checks, wait without a timeout,
     // and wait as a suspend-equivalent condition.
-    Terminator_lock->wait(!Mutex::_no_safepoint_check_flag, 0,
-                          Mutex::_as_suspend_equivalent_flag);
+    mu.wait(0, Mutex::_as_suspend_equivalent_flag);
   }
 }
 
@@ -1572,16 +1575,17 @@
   return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
 }
 
-void JavaThread::collect_counters(typeArrayOop array) {
+void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
   if (JVMCICounterSize > 0) {
     JavaThreadIteratorWithHandle jtiwh;
-    for (int i = 0; i < array->length(); i++) {
-      array->long_at_put(i, _jvmci_old_thread_counters[i]);
+    int len = jvmci_env->get_length(array);
+    for (int i = 0; i < len; i++) {
+      jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
     }
     for (; JavaThread *tp = jtiwh.next(); ) {
       if (jvmci_counters_include(tp)) {
-        for (int i = 0; i < array->length(); i++) {
-          array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]);
+        for (int i = 0; i < len; i++) {
+          jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
         }
       }
     }
@@ -1624,7 +1628,6 @@
   _pending_deoptimization = -1;
   _pending_failed_speculation = 0;
   _pending_transfer_to_interpreter = false;
-  _adjusting_comp_level = false;
   _in_retryable_allocation = false;
   _jvmci._alternate_call_target = NULL;
   assert(_jvmci._implicit_exception_pc == NULL, "must be");
@@ -1990,7 +1993,7 @@
     // in order to not surprise the thread that made the suspend request.
     while (true) {
       {
-        MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+        MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
         if (!is_external_suspend()) {
           set_terminated(_thread_exiting);
           ThreadService::current_thread_exiting(this, is_daemon(threadObj()));
@@ -2359,7 +2362,7 @@
     return;
   }
 
-  { MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+  { MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     if (!is_external_suspend()) {
       // a racing resume has cancelled us; bail out now
       return;
@@ -2418,7 +2421,7 @@
          (is_Java_thread() && !((JavaThread*)this)->has_last_Java_frame()),
          "must have walkable stack");
 
-  MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
 
   assert(!this->is_ext_suspended(),
          "a thread trying to self-suspend should not already be suspended");
@@ -2446,7 +2449,7 @@
 
     // _ext_suspended flag is cleared by java_resume()
     while (is_ext_suspended()) {
-      this->SR_lock()->wait(Mutex::_no_safepoint_check_flag);
+      ml.wait();
     }
   }
   return ret;
@@ -2520,21 +2523,6 @@
     SafepointMechanism::block_if_requested(curJT);
   }
 
-  if (thread->is_deopt_suspend()) {
-    thread->clear_deopt_suspend();
-    RegisterMap map(thread, false);
-    frame f = thread->last_frame();
-    while (f.id() != thread->must_deopt_id() && ! f.is_first_frame()) {
-      f = f.sender(&map);
-    }
-    if (f.id() == thread->must_deopt_id()) {
-      thread->clear_must_deopt_id();
-      f.deoptimize(thread);
-    } else {
-      fatal("missed deoptimization!");
-    }
-  }
-
   JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(thread);)
 }
 
@@ -2588,7 +2576,7 @@
     return;
   }
 
-  MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
 
   clear_external_suspend();
 
@@ -3853,10 +3841,10 @@
     // Wait for the VM thread to become ready, and VMThread::run to initialize
     // Monitors can have spurious returns, must always check another state flag
     {
-      MutexLocker ml(Notify_lock);
+      MonitorLocker ml(Notify_lock);
       os::start_thread(vmthread);
       while (vmthread->active_handles() == NULL) {
-        Notify_lock->wait();
+        ml.wait();
       }
     }
   }
@@ -3934,10 +3922,8 @@
   bool force_JVMCI_intialization = false;
   if (EnableJVMCI) {
     // Initialize JVMCI eagerly when it is explicitly requested.
-    // Or when JVMCIPrintProperties is enabled.
-    // The JVMCI Java initialization code will read this flag and
-    // do the printing if it's set.
-    force_JVMCI_intialization = EagerJVMCI || JVMCIPrintProperties;
+    // Or when JVMCILibDumpJNIConfig or JVMCIPrintProperties is enabled.
+    force_JVMCI_intialization = EagerJVMCI || JVMCIPrintProperties || JVMCILibDumpJNIConfig;
 
     if (!force_JVMCI_intialization) {
       // 8145270: Force initialization of JVMCI runtime otherwise requests for blocking
@@ -3986,7 +3972,7 @@
 
 #if INCLUDE_JVMCI
   if (force_JVMCI_intialization) {
-    JVMCIRuntime::force_initialization(CHECK_JNI_ERR);
+    JVMCI::initialize_compiler(CHECK_JNI_ERR);
     CompileBroker::compilation_init_phase2();
   }
 #endif
@@ -4286,7 +4272,7 @@
     JavaValue result(T_VOID);
     JavaCalls::call_static(&result,
                            shutdown_klass,
-                           vmSymbols::shutdown_method_name(),
+                           vmSymbols::shutdown_name(),
                            vmSymbols::void_method_signature(),
                            THREAD);
   }
@@ -4334,12 +4320,11 @@
   _vm_complete = false;
 #endif
   // Wait until we are the last non-daemon thread to execute
-  { MutexLocker nu(Threads_lock);
+  { MonitorLocker nu(Threads_lock);
     while (Threads::number_of_non_daemon_threads() > 1)
       // This wait should make safepoint checks, wait without a timeout,
       // and wait as a suspend-equivalent condition.
-      Threads_lock->wait(!Mutex::_no_safepoint_check_flag, 0,
-                         Mutex::_as_suspend_equivalent_flag);
+      nu.wait(0, Mutex::_as_suspend_equivalent_flag);
   }
 
   EventShutdown e;
@@ -4370,7 +4355,7 @@
     // queue until after the vm thread is dead. After this point,
     // we'll never emerge out of the safepoint before the VM exits.
 
-    MutexLockerEx ml(Heap_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Heap_lock, Mutex::_no_safepoint_check_flag);
 
     VMThread::wait_for_vm_thread_exit();
     assert(SafepointSynchronize::is_at_safepoint(), "VM thread should exit at Safepoint");
@@ -4475,7 +4460,7 @@
 
   // Extra scope needed for Thread_lock, so we can check
   // that we do not remove thread without safepoint code notice
-  { MutexLocker ml(Threads_lock);
+  { MonitorLocker ml(Threads_lock);
 
     assert(ThreadsSMRSupport::get_java_thread_list()->includes(p), "p must be present");
 
@@ -4503,7 +4488,7 @@
       // Only one thread left, do a notify on the Threads_lock so a thread waiting
       // on destroy_vm will wake up.
       if (number_of_non_daemon_threads() == 1) {
-        Threads_lock->notify_all();
+        ml.notify_all();
       }
     }
     ThreadService::remove_thread(p, is_daemon);
--- a/src/hotspot/share/runtime/thread.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/thread.hpp	Fri May 03 14:59:32 2019 -0400
@@ -88,6 +88,9 @@
 class ICRefillVerifier;
 class IdealGraphPrinter;
 
+class JVMCIEnv;
+class JVMCIPrimitiveArray;
+
 class Metadata;
 class ResourceArea;
 
@@ -286,7 +289,6 @@
 
     _external_suspend       = 0x20000000U, // thread is asked to self suspend
     _ext_suspended          = 0x40000000U, // thread has self-suspended
-    _deopt_suspend          = 0x10000000U, // thread needs to self suspend for deopt
 
     _has_async_exception    = 0x00000001U, // there is a pending async exception
     _critical_native_unlock = 0x00000002U, // Must call back to unlock JNI critical lock
@@ -1127,16 +1129,13 @@
   // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter
   bool      _pending_transfer_to_interpreter;
 
-  // Guard for re-entrant call to JVMCIRuntime::adjust_comp_level
-  bool      _adjusting_comp_level;
-
   // True if in a runtime call from compiled code that will deoptimize
   // and re-execute a failed heap allocation in the interpreter.
   bool      _in_retryable_allocation;
 
   // An id of a speculation that JVMCI compiled code can use to further describe and
   // uniquely identify the  speculative optimization guarded by the uncommon trap
-  long       _pending_failed_speculation;
+  jlong     _pending_failed_speculation;
 
   // These fields are mutually exclusive in terms of live ranges.
   union {
@@ -1153,7 +1152,7 @@
 
  public:
   static jlong* _jvmci_old_thread_counters;
-  static void collect_counters(typeArrayOop array);
+  static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
  private:
 #endif // INCLUDE_JVMCI
 
@@ -1383,7 +1382,7 @@
 
   bool is_ext_suspend_completed(bool called_by_wait, int delay, uint32_t *bits);
   bool is_ext_suspend_completed_with_lock(uint32_t *bits) {
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     // Warning: is_ext_suspend_completed() may temporarily drop the
     // SR_lock to allow the thread to reach a stable thread state if
     // it is currently in a transient thread state.
@@ -1405,17 +1404,13 @@
   inline void set_external_suspend();
   inline void clear_external_suspend();
 
-  inline void set_deopt_suspend();
-  inline void clear_deopt_suspend();
-  bool is_deopt_suspend()         { return (_suspend_flags & _deopt_suspend) != 0; }
-
   bool is_external_suspend() const {
     return (_suspend_flags & _external_suspend) != 0;
   }
   // Whenever a thread transitions from native to vm/java it must suspend
   // if external|deopt suspend is present.
   bool is_suspend_after_native() const {
-    return (_suspend_flags & (_external_suspend | _deopt_suspend JFR_ONLY(| _trace_flag))) != 0;
+    return (_suspend_flags & (_external_suspend JFR_ONLY(| _trace_flag))) != 0;
   }
 
   // external suspend request is completed
@@ -1424,7 +1419,7 @@
   }
 
   bool is_external_suspend_with_lock() const {
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     return is_external_suspend();
   }
 
@@ -1433,7 +1428,7 @@
   bool handle_special_suspend_equivalent_condition() {
     assert(is_suspend_equivalent(),
            "should only be called in a suspend equivalence condition");
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     bool ret = is_external_suspend();
     if (!ret) {
       // not about to self-suspend so clear suspend equivalence
@@ -1450,7 +1445,7 @@
 
   // utility methods to see if we are doing some kind of suspension
   bool is_being_ext_suspended() const            {
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     return is_ext_suspended() || is_external_suspend();
   }
 
@@ -1540,13 +1535,11 @@
 
 #if INCLUDE_JVMCI
   int  pending_deoptimization() const             { return _pending_deoptimization; }
-  long pending_failed_speculation() const         { return _pending_failed_speculation; }
-  bool adjusting_comp_level() const               { return _adjusting_comp_level; }
-  void set_adjusting_comp_level(bool b)           { _adjusting_comp_level = b; }
+  jlong pending_failed_speculation() const        { return _pending_failed_speculation; }
   bool has_pending_monitorenter() const           { return _pending_monitorenter; }
   void set_pending_monitorenter(bool b)           { _pending_monitorenter = b; }
   void set_pending_deoptimization(int reason)     { _pending_deoptimization = reason; }
-  void set_pending_failed_speculation(long failed_speculation) { _pending_failed_speculation = failed_speculation; }
+  void set_pending_failed_speculation(jlong failed_speculation) { _pending_failed_speculation = failed_speculation; }
   void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; }
   void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == NULL, "must be"); _jvmci._alternate_call_target = a; }
   void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == NULL, "must be"); _jvmci._implicit_exception_pc = a; }
--- a/src/hotspot/share/runtime/thread.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/thread.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -108,13 +108,6 @@
   clear_suspend_flag(_external_suspend);
 }
 
-inline void JavaThread::set_deopt_suspend() {
-  set_suspend_flag(_deopt_suspend);
-}
-inline void JavaThread::clear_deopt_suspend() {
-  clear_suspend_flag(_deopt_suspend);
-}
-
 inline void JavaThread::set_pending_async_exception(oop e) {
   _pending_async_exception = e;
   _special_runtime_exit_condition = _async_exception;
--- a/src/hotspot/share/runtime/threadHeapSampler.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/threadHeapSampler.cpp	Fri May 03 14:59:32 2019 -0400
@@ -121,11 +121,6 @@
   }
 
   pick_next_geometric_sample();
-
-  // Try to correct sample size by removing extra space from last allocation.
-  if (overflowed_bytes > 0 && _bytes_until_sample > overflowed_bytes) {
-    _bytes_until_sample -= overflowed_bytes;
-  }
 }
 
 void ThreadHeapSampler::check_for_sampling(oop obj, size_t allocation_size, size_t bytes_since_allocation) {
--- a/src/hotspot/share/runtime/threadSMR.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/threadSMR.cpp	Fri May 03 14:59:32 2019 -0400
@@ -899,7 +899,7 @@
   // safepoint which means this thread can't take too long to get to
   // a safepoint because of being blocked on delete_lock.
   //
-  MonitorLockerEx ml(ThreadsSMRSupport::delete_lock(), Monitor::_no_safepoint_check_flag);
+  MonitorLocker ml(ThreadsSMRSupport::delete_lock(), Monitor::_no_safepoint_check_flag);
   if (ThreadsSMRSupport::delete_notify()) {
     // Notify any exiting JavaThreads that are waiting in smr_delete()
     // that we've released a ThreadsList.
@@ -944,8 +944,8 @@
     {
       // No safepoint check because this JavaThread is not on the
       // Threads list.
-      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      // Cannot use a MonitorLockerEx helper here because we have
+      MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+      // Cannot use a MonitorLocker helper here because we have
       // to drop the Threads_lock first if we wait.
       ThreadsSMRSupport::delete_lock()->lock_without_safepoint_check();
       // Set the delete_notify flag after we grab delete_lock
@@ -985,8 +985,7 @@
     // Wait for a release_stable_list() call before we check again. No
     // safepoint check, no timeout, and not as suspend equivalent flag
     // because this JavaThread is not on the Threads list.
-    ThreadsSMRSupport::delete_lock()->wait(Mutex::_no_safepoint_check_flag, 0,
-                                     !Mutex::_as_suspend_equivalent_flag);
+    ThreadsSMRSupport::delete_lock()->wait_without_safepoint_check();
     if (EnableThreadSMRStatistics) {
       _delete_lock_wait_cnt--;
     }
@@ -1078,7 +1077,7 @@
   // block during error reporting or a nested error could leave the
   // Threads_lock held. The classic no win scenario.
   //
-  MutexLockerEx ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock);
+  MutexLocker ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock);
 
   st->print_cr("Threads class SMR info:");
   st->print_cr("_java_thread_list=" INTPTR_FORMAT ", length=%u, "
--- a/src/hotspot/share/runtime/threadSMR.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/threadSMR.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -82,7 +82,7 @@
 }
 
 inline bool ThreadsSMRSupport::is_a_protected_JavaThread_with_lock(JavaThread *thread) {
-  MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
+  MutexLocker ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
   return is_a_protected_JavaThread(thread);
 }
 
--- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -34,7 +34,7 @@
 #include "code/scopeDesc.hpp"
 #include "oops/method.inline.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 
 #ifdef TIERED
@@ -91,6 +91,21 @@
   return false;
 }
 
+bool TieredThresholdPolicy::should_compile_at_level_simple(Method* method) {
+  if (TieredThresholdPolicy::is_trivial(method)) {
+    return true;
+  }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    AbstractCompiler* comp = CompileBroker::compiler(CompLevel_full_optimization);
+    if (comp != NULL && comp->is_jvmci() && ((JVMCICompiler*) comp)->force_comp_at_level_simple(method)) {
+      return true;
+    }
+  }
+#endif
+  return false;
+}
+
 CompLevel TieredThresholdPolicy::comp_level(Method* method) {
   CompiledMethod *nm = method->code();
   if (nm != NULL && nm->is_in_use()) {
@@ -613,7 +628,7 @@
 
 // Determine is a method is mature.
 bool TieredThresholdPolicy::is_mature(Method* method) {
-  if (is_trivial(method)) return true;
+  if (should_compile_at_level_simple(method)) return true;
   MethodData* mdo = method->method_data();
   if (mdo != NULL) {
     int i = mdo->invocation_count();
@@ -709,7 +724,7 @@
   int i = method->invocation_count();
   int b = method->backedge_count();
 
-  if (is_trivial(method)) {
+  if (should_compile_at_level_simple(method)) {
     next_level = CompLevel_simple;
   } else {
     switch(cur_level) {
@@ -825,11 +840,6 @@
   } else {
     next_level = MAX2(osr_level, next_level);
   }
-#if INCLUDE_JVMCI
-  if (UseJVMCICompiler) {
-    next_level = JVMCIRuntime::adjust_comp_level(method, false, next_level, thread);
-  }
-#endif
   return next_level;
 }
 
@@ -844,11 +854,6 @@
       return osr_level;
     }
   }
-#if INCLUDE_JVMCI
-  if (UseJVMCICompiler) {
-    next_level = JVMCIRuntime::adjust_comp_level(method, true, next_level, thread);
-  }
-#endif
   return next_level;
 }
 
--- a/src/hotspot/share/runtime/tieredThresholdPolicy.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.hpp	Fri May 03 14:59:32 2019 -0400
@@ -231,7 +231,9 @@
   virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread);
   // Simple methods are as good being compiled with C1 as C2.
   // This function tells if it's such a function.
-  inline bool is_trivial(Method* method);
+  inline static bool is_trivial(Method* method);
+  // Force method to be compiled at CompLevel_simple?
+  inline static bool should_compile_at_level_simple(Method* method);
 
   // Predicate helpers are used by .*_predicate() methods as well as others.
   // They check the given counter values, multiplied by the scale against the thresholds.
--- a/src/hotspot/share/runtime/vmOperations.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/vmOperations.cpp	Fri May 03 14:59:32 2019 -0400
@@ -435,7 +435,20 @@
       if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
         num_active++;
         if (thr->is_Compiler_thread()) {
+#if INCLUDE_JVMCI
+          CompilerThread* ct = (CompilerThread*) thr;
+          if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) {
+            num_active_compiler_thread++;
+          } else {
+            // When using a compiler in a JVMCI shared library, it's possible
+            // for one compiler thread to grab a lock in the shared library,
+            // enter HotSpot and go to sleep on the shutdown safepoint. Another
+            // JVMCI shared library compiler thread can then attempt to grab the
+            // lock and thus never make progress.
+          }
+#else
           num_active_compiler_thread++;
+#endif
         }
       }
     }
@@ -450,8 +463,8 @@
 
     attempts++;
 
-    MutexLockerEx ml(&timer, Mutex::_no_safepoint_check_flag);
-    timer.wait(Mutex::_no_safepoint_check_flag, 10);
+    MonitorLocker ml(&timer, Mutex::_no_safepoint_check_flag);
+    ml.wait(10);
   }
 }
 
--- a/src/hotspot/share/runtime/vmStructs.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Fri May 03 14:59:32 2019 -0400
@@ -896,7 +896,7 @@
   volatile_nonstatic_field(ObjectMonitor,      _header,                                       markOop)                               \
   unchecked_nonstatic_field(ObjectMonitor,     _object,                                       sizeof(void *)) /* NOTE: no type */    \
   unchecked_nonstatic_field(ObjectMonitor,     _owner,                                        sizeof(void *)) /* NOTE: no type */    \
-  volatile_nonstatic_field(ObjectMonitor,      _count,                                        jint)                                  \
+  volatile_nonstatic_field(ObjectMonitor,      _contentions,                                  jint)                                  \
   volatile_nonstatic_field(ObjectMonitor,      _waiters,                                      jint)                                  \
   volatile_nonstatic_field(ObjectMonitor,      _recursions,                                   intptr_t)                              \
   nonstatic_field(ObjectMonitor,               FreeNext,                                      ObjectMonitor*)                        \
@@ -2095,6 +2095,8 @@
   declare_constant(JVM_CONSTANT_MethodType)                               \
   declare_constant(JVM_CONSTANT_Dynamic)                                  \
   declare_constant(JVM_CONSTANT_InvokeDynamic)                            \
+  declare_constant(JVM_CONSTANT_Module)                                   \
+  declare_constant(JVM_CONSTANT_Package)                                  \
   declare_constant(JVM_CONSTANT_ExternalMax)                              \
                                                                           \
   declare_constant(JVM_CONSTANT_Invalid)                                  \
--- a/src/hotspot/share/runtime/vmThread.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri May 03 14:59:32 2019 -0400
@@ -342,9 +342,9 @@
     // but before it actually drops the lock and waits, the notification below
     // may get lost and we will have a hang. To avoid this, we need to use
     // Mutex::lock_without_safepoint_check().
-    MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
     _terminated = true;
-    _terminate_lock->notify();
+    ml.notify();
   }
 
   // We are now racing with the VM termination being carried out in
@@ -359,7 +359,7 @@
 void VMThread::wait_for_vm_thread_exit() {
   assert(Thread::current()->is_Java_thread(), "Should be a JavaThread");
   assert(((JavaThread*)Thread::current())->is_terminated(), "Should be terminated");
-  { MutexLockerEx mu(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
+  { MutexLocker mu(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
     _should_terminate = true;
     VMOperationQueue_lock->notify();
   }
@@ -373,9 +373,9 @@
   // Note: it should be OK to use Terminator_lock here. But this is called
   // at a very delicate time (VM shutdown) and we are operating in non- VM
   // thread at Safepoint. It's safer to not share lock with other threads.
-  { MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
+  { MonitorLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
     while(!VMThread::is_terminated()) {
-        _terminate_lock->wait(Mutex::_no_safepoint_check_flag);
+      ml.wait();
     }
   }
 }
@@ -476,7 +476,7 @@
     // Wait for VM operation
     //
     // use no_safepoint_check to get lock without attempting to "sneak"
-    { MutexLockerEx mu_queue(VMOperationQueue_lock,
+    { MonitorLocker mu_queue(VMOperationQueue_lock,
                              Mutex::_no_safepoint_check_flag);
 
       // Look for new operation
@@ -494,8 +494,7 @@
       while (!should_terminate() && _cur_vm_operation == NULL) {
         // wait with a timeout to guarantee safepoints at regular intervals
         bool timedout =
-          VMOperationQueue_lock->wait(Mutex::_no_safepoint_check_flag,
-                                      GuaranteedSafepointInterval);
+          mu_queue.wait(GuaranteedSafepointInterval);
 
         // Support for self destruction
         if ((SelfDestructTimer != 0) && !VMError::is_error_reported() &&
@@ -507,7 +506,7 @@
         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);
+          MutexUnlocker 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
@@ -584,8 +583,8 @@
           // the lock.
           if (_vm_queue->peek_at_safepoint_priority()) {
             // must hold lock while draining queue
-            MutexLockerEx mu_queue(VMOperationQueue_lock,
-                                     Mutex::_no_safepoint_check_flag);
+            MutexLocker mu_queue(VMOperationQueue_lock,
+                                 Mutex::_no_safepoint_check_flag);
             safepoint_ops = _vm_queue->drain_at_safepoint_priority();
           } else {
             safepoint_ops = NULL;
@@ -624,10 +623,8 @@
     }
 
     //
-    //  Notify (potential) waiting Java thread(s) - lock without safepoint
-    //  check so that sneaking is not possible
-    { MutexLockerEx mu(VMOperationRequest_lock,
-                       Mutex::_no_safepoint_check_flag);
+    //  Notify (potential) waiting Java thread(s)
+    { MutexLocker mu(VMOperationRequest_lock, Mutex::_no_safepoint_check_flag);
       VMOperationRequest_lock->notify_all();
     }
 
@@ -719,9 +716,10 @@
     if (!concurrent) {
       // Wait for completion of request (non-concurrent)
       // Note: only a JavaThread triggers the safepoint check when locking
-      MutexLocker mu(VMOperationRequest_lock);
+      MonitorLocker ml(VMOperationRequest_lock,
+                       t->is_Java_thread() ? Mutex::_safepoint_check_flag : Mutex::_no_safepoint_check_flag);
       while(t->vm_operation_completed_count() < ticket) {
-        VMOperationRequest_lock->wait(!t->is_Java_thread());
+        ml.wait();
       }
     }
 
--- a/src/hotspot/share/services/diagnosticFramework.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/diagnosticFramework.cpp	Fri May 03 14:59:32 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
@@ -437,7 +437,7 @@
 }
 
 void DCmdFactory::push_jmx_notification_request() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   _has_pending_jmx_notification = true;
   Service_lock->notify_all();
 }
@@ -455,7 +455,7 @@
   HandleMark hm(THREAD);
   bool notif = false;
   {
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     notif = _has_pending_jmx_notification;
     _has_pending_jmx_notification = false;
   }
@@ -494,7 +494,7 @@
 bool DCmdFactory::_send_jmx_notification = false;
 
 DCmdFactory* DCmdFactory::factory(DCmdSource source, const char* name, size_t len) {
-  MutexLockerEx ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
   DCmdFactory* factory = _DCmdFactoryList;
   while (factory != NULL) {
     if (strlen(factory->name()) == len &&
@@ -511,7 +511,7 @@
 }
 
 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
-  MutexLockerEx ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
   factory->_next = _DCmdFactoryList;
   _DCmdFactoryList = factory;
   if (_send_jmx_notification && !factory->_hidden
@@ -536,7 +536,7 @@
 }
 
 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
-  MutexLockerEx ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
   GrowableArray<const char*>* array = new GrowableArray<const char*>();
   DCmdFactory* factory = _DCmdFactoryList;
   while (factory != NULL) {
@@ -549,7 +549,7 @@
 }
 
 GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list(DCmdSource source ) {
-  MutexLockerEx ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(DCmdFactory_lock, Mutex::_no_safepoint_check_flag);
   GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>();
   DCmdFactory* factory = _DCmdFactoryList;
   while (factory != NULL) {
--- a/src/hotspot/share/services/gcNotifier.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/gcNotifier.cpp	Fri May 03 14:59:32 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
@@ -54,7 +54,7 @@
  }
 
 void GCNotifier::addRequest(GCNotificationRequest *request) {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   if(first_request == NULL) {
     first_request = request;
   } else {
@@ -65,7 +65,7 @@
 }
 
 GCNotificationRequest *GCNotifier::getRequest() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
   GCNotificationRequest *request = first_request;
   if(first_request != NULL) {
     first_request = first_request->next;
--- a/src/hotspot/share/services/lowMemoryDetector.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/lowMemoryDetector.cpp	Fri May 03 14:59:32 2019 -0400
@@ -80,7 +80,7 @@
 // This method could be called from any Java threads
 // and also VMThread.
 void LowMemoryDetector::detect_low_memory() {
-  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
 
   bool has_pending_requests = false;
   int num_memory_pools = MemoryService::num_memory_pools();
@@ -113,7 +113,7 @@
   }
 
   {
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
 
     MemoryUsage usage = pool->get_memory_usage();
     sensor->set_gauge_sensor_level(usage,
@@ -135,7 +135,7 @@
   }
 
   {
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
 
     MemoryUsage usage = pool->get_last_collection_usage();
     sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());
@@ -335,7 +335,7 @@
 
   {
     // Holds Service_lock and update the sensor state
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     assert(_pending_trigger_count > 0, "Must have pending trigger");
     _sensor_on = true;
     _sensor_count += count;
@@ -346,7 +346,7 @@
 void SensorInfo::clear(int count, TRAPS) {
   {
     // Holds Service_lock and update the sensor state
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
     if (_pending_clear_count == 0) {
       // Bail out if we lost a race to set_*_sensor_level() which may have
       // reactivated the sensor in the meantime because it was triggered again.
--- a/src/hotspot/share/services/management.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/management.cpp	Fri May 03 14:59:32 2019 -0400
@@ -844,7 +844,7 @@
 static jint get_vm_thread_count() {
   VmThreadCountClosure vmtcc;
   {
-    MutexLockerEx ml(Threads_lock);
+    MutexLocker ml(Threads_lock);
     Threads::threads_do(&vmtcc);
   }
 
@@ -1704,7 +1704,7 @@
 
   ThreadTimesClosure ttc(names_ah, times_ah);
   {
-    MutexLockerEx ml(Threads_lock);
+    MutexLocker ml(Threads_lock);
     Threads::threads_do(&ttc);
   }
   ttc.do_unlocked();
--- a/src/hotspot/share/services/memoryManager.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/memoryManager.cpp	Fri May 03 14:59:32 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
@@ -282,7 +282,7 @@
     _num_collections++;
     // alternately update two objects making one public when complete
     {
-      MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
       GCStatInfo *tmp = _last_gc_stat;
       _last_gc_stat = _current_gc_stat;
       _current_gc_stat = tmp;
@@ -297,7 +297,7 @@
 }
 
 size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {
-  MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
   if (_last_gc_stat->gc_index() != 0) {
     dest->set_index(_last_gc_stat->gc_index());
     dest->set_start_time(_last_gc_stat->start_time());
--- a/src/hotspot/share/services/threadService.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/services/threadService.cpp	Fri May 03 14:59:32 2019 -0400
@@ -97,7 +97,7 @@
 void ThreadService::reset_peak_thread_count() {
   // Acquire the lock to update the peak thread count
   // to synchronize with thread addition and removal.
-  MutexLockerEx mu(Threads_lock);
+  MutexLocker mu(Threads_lock);
   _peak_threads_count->set_value(get_live_thread_count());
 }
 
--- a/src/hotspot/share/utilities/bitMap.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/bitMap.cpp	Fri May 03 14:59:32 2019 -0400
@@ -111,26 +111,26 @@
 }
 
 template <class Allocator>
-void BitMap::resize(const Allocator& allocator, idx_t new_size_in_bits) {
-  bm_word_t* new_map = reallocate(allocator, map(), size(), new_size_in_bits);
+void BitMap::resize(const Allocator& allocator, idx_t new_size_in_bits, bool clear) {
+  bm_word_t* new_map = reallocate(allocator, map(), size(), new_size_in_bits, clear);
 
   update(new_map, new_size_in_bits);
 }
 
 template <class Allocator>
-void BitMap::initialize(const Allocator& allocator, idx_t size_in_bits) {
+void BitMap::initialize(const Allocator& allocator, idx_t size_in_bits, bool clear) {
   assert(map() == NULL, "precondition");
   assert(size() == 0,   "precondition");
 
-  resize(allocator, size_in_bits);
+  resize(allocator, size_in_bits, clear);
 }
 
 template <class Allocator>
-void BitMap::reinitialize(const Allocator& allocator, idx_t new_size_in_bits) {
-  // Remove previous bits.
-  resize(allocator, 0);
+void BitMap::reinitialize(const Allocator& allocator, idx_t new_size_in_bits, bool clear) {
+  // Remove previous bits - no need to clear
+  resize(allocator, 0, false /* clear */);
 
-  initialize(allocator, new_size_in_bits);
+  initialize(allocator, new_size_in_bits, clear);
 }
 
 ResourceBitMap::ResourceBitMap(idx_t size_in_bits)
@@ -138,15 +138,15 @@
 }
 
 void ResourceBitMap::resize(idx_t new_size_in_bits) {
-  BitMap::resize(ResourceBitMapAllocator(), new_size_in_bits);
+  BitMap::resize(ResourceBitMapAllocator(), new_size_in_bits, true /* clear */);
 }
 
 void ResourceBitMap::initialize(idx_t size_in_bits) {
-  BitMap::initialize(ResourceBitMapAllocator(), size_in_bits);
+  BitMap::initialize(ResourceBitMapAllocator(), size_in_bits, true /* clear */);
 }
 
 void ResourceBitMap::reinitialize(idx_t size_in_bits) {
-  BitMap::reinitialize(ResourceBitMapAllocator(), size_in_bits);
+  BitMap::reinitialize(ResourceBitMapAllocator(), size_in_bits, true /* clear */);
 }
 
 ArenaBitMap::ArenaBitMap(Arena* arena, idx_t size_in_bits)
@@ -161,16 +161,16 @@
   free(CHeapBitMapAllocator(_flags), map(), size());
 }
 
-void CHeapBitMap::resize(idx_t new_size_in_bits) {
-  BitMap::resize(CHeapBitMapAllocator(_flags), new_size_in_bits);
+void CHeapBitMap::resize(idx_t new_size_in_bits, bool clear) {
+  BitMap::resize(CHeapBitMapAllocator(_flags), new_size_in_bits, clear);
 }
 
-void CHeapBitMap::initialize(idx_t size_in_bits) {
-  BitMap::initialize(CHeapBitMapAllocator(_flags), size_in_bits);
+void CHeapBitMap::initialize(idx_t size_in_bits, bool clear) {
+  BitMap::initialize(CHeapBitMapAllocator(_flags), size_in_bits, clear);
 }
 
-void CHeapBitMap::reinitialize(idx_t size_in_bits) {
-  BitMap::reinitialize(CHeapBitMapAllocator(_flags), size_in_bits);
+void CHeapBitMap::reinitialize(idx_t size_in_bits, bool clear) {
+  BitMap::reinitialize(CHeapBitMapAllocator(_flags), size_in_bits, clear);
 }
 
 #ifdef ASSERT
--- a/src/hotspot/share/utilities/bitMap.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/bitMap.hpp	Fri May 03 14:59:32 2019 -0400
@@ -157,20 +157,20 @@
   // Old bits are transfered to the new memory
   // and the extended memory is cleared.
   template <class Allocator>
-  void resize(const Allocator& allocator, idx_t new_size_in_bits);
+  void resize(const Allocator& allocator, idx_t new_size_in_bits, bool clear);
 
   // Set up and clear the bitmap memory.
   //
   // Precondition: The bitmap was default constructed and has
   // not yet had memory allocated via resize or (re)initialize.
   template <class Allocator>
-  void initialize(const Allocator& allocator, idx_t size_in_bits);
+  void initialize(const Allocator& allocator, idx_t size_in_bits, bool clear);
 
   // Set up and clear the bitmap memory.
   //
   // Can be called on previously initialized bitmaps.
   template <class Allocator>
-  void reinitialize(const Allocator& allocator, idx_t new_size_in_bits);
+  void reinitialize(const Allocator& allocator, idx_t new_size_in_bits, bool clear);
 
   // Set the map and size.
   void update(bm_word_t* map, idx_t size) {
@@ -384,18 +384,18 @@
   //
   // Old bits are transfered to the new memory
   // and the extended memory is cleared.
-  void resize(idx_t new_size_in_bits);
+  void resize(idx_t new_size_in_bits, bool clear = true);
 
   // Set up and clear the bitmap memory.
   //
   // Precondition: The bitmap was default constructed and has
   // not yet had memory allocated via resize or initialize.
-  void initialize(idx_t size_in_bits);
+  void initialize(idx_t size_in_bits, bool clear = true);
 
   // Set up and clear the bitmap memory.
   //
   // Can be called on previously initialized bitmaps.
-  void reinitialize(idx_t size_in_bits);
+  void reinitialize(idx_t size_in_bits, bool clear = true);
 };
 
 // Convenience class wrapping BitMap which provides multiple bits per slot.
--- a/src/hotspot/share/utilities/debug.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/debug.hpp	Fri May 03 14:59:32 2019 -0400
@@ -63,6 +63,9 @@
 // For backward compatibility.
 #define assert(p, ...) vmassert(p, __VA_ARGS__)
 
+#define precond(p)   assert(p, "precond")
+#define postcond(p)  assert(p, "postcond")
+
 #ifndef ASSERT
 #define vmassert_status(p, status, msg)
 #else
--- a/src/hotspot/share/utilities/decoder.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/decoder.cpp	Fri May 03 14:59:32 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
@@ -78,19 +78,6 @@
   return decoder;
 }
 
-inline bool DecoderLocker::is_first_error_thread() {
-  return (os::current_thread_id() == VMError::get_first_error_tid());
-}
-
-DecoderLocker::DecoderLocker() :
-  MutexLockerEx(DecoderLocker::is_first_error_thread() ?
-                NULL : Decoder::shared_decoder_lock(),
-                Mutex::_no_safepoint_check_flag) {
-  _decoder = is_first_error_thread() ?
-    Decoder::get_error_handler_instance() : Decoder::get_shared_instance();
-  assert(_decoder != NULL, "null decoder");
-}
-
 Mutex* Decoder::shared_decoder_lock() {
   assert(SharedDecoder_lock != NULL, "Just check");
   return SharedDecoder_lock;
@@ -98,35 +85,34 @@
 
 bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
   bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
-  MutexLockerEx locker(error_handling_thread ? NULL : shared_decoder_lock(),
-                       Mutex::_no_safepoint_check_flag);
-  AbstractDecoder* decoder = error_handling_thread ?
-    get_error_handler_instance(): get_shared_instance();
-  assert(decoder != NULL, "null decoder");
+  if (error_handling_thread) {
+    return get_error_handler_instance()->decode(addr, buf, buflen, offset, modulepath, demangle);
+  } else {
+    MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
+    return get_shared_instance()->decode(addr, buf, buflen, offset, modulepath, demangle);
+  }
 
-  return decoder->decode(addr, buf, buflen, offset, modulepath, demangle);
 }
 
 bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const void* base) {
   bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
-  MutexLockerEx locker(error_handling_thread ? NULL : shared_decoder_lock(),
-                       Mutex::_no_safepoint_check_flag);
-  AbstractDecoder* decoder = error_handling_thread ?
-    get_error_handler_instance(): get_shared_instance();
-  assert(decoder != NULL, "null decoder");
-
-  return decoder->decode(addr, buf, buflen, offset, base);
+  if (error_handling_thread) {
+    return get_error_handler_instance()->decode(addr, buf, buflen, offset, base);
+  } else {
+    MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
+    return get_shared_instance()->decode(addr, buf, buflen, offset, base);
+  }
 }
 
 
 bool Decoder::demangle(const char* symbol, char* buf, int buflen) {
   bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid;
-  MutexLockerEx locker(error_handling_thread ? NULL : shared_decoder_lock(),
-                       Mutex::_no_safepoint_check_flag);
-  AbstractDecoder* decoder = error_handling_thread ?
-    get_error_handler_instance(): get_shared_instance();
-  assert(decoder != NULL, "null decoder");
-  return decoder->demangle(symbol, buf, buflen);
+  if (error_handling_thread) {
+    return get_error_handler_instance()->demangle(symbol, buf, buflen);
+  } else {
+    MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
+    return get_shared_instance()->demangle(symbol, buf, buflen);
+  }
 }
 
 void Decoder::print_state_on(outputStream* st) {
--- a/src/hotspot/share/utilities/decoder.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/decoder.hpp	Fri May 03 14:59:32 2019 -0400
@@ -136,14 +136,4 @@
   friend class DecoderLocker;
 };
 
-class DecoderLocker : public MutexLockerEx {
-  AbstractDecoder* _decoder;
-  inline bool is_first_error_thread();
-public:
-  DecoderLocker();
-  AbstractDecoder* decoder() {
-    return _decoder;
-  }
-};
-
 #endif // SHARE_UTILITIES_DECODER_HPP
--- a/src/hotspot/share/utilities/events.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/events.cpp	Fri May 03 14:59:32 2019 -0400
@@ -117,7 +117,7 @@
   if (!should_log()) return;
 
   double timestamp = fetch_timestamp();
-  MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(&_mutex, Mutex::_no_safepoint_check_flag);
   int index = compute_log_index();
   _records[index].thread = thread;
   _records[index].timestamp = timestamp;
--- a/src/hotspot/share/utilities/events.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/events.hpp	Fri May 03 14:59:32 2019 -0400
@@ -156,7 +156,7 @@
     if (!this->should_log()) return;
 
     double timestamp = this->fetch_timestamp();
-    MutexLockerEx ml(&this->_mutex, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(&this->_mutex, Mutex::_no_safepoint_check_flag);
     int index = this->compute_log_index();
     this->_records[index].thread = thread;
     this->_records[index].timestamp = timestamp;
@@ -291,7 +291,7 @@
     // Not yet attached? Don't try to use locking
     print_log_impl(out);
   } else {
-    MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(&_mutex, Mutex::_no_safepoint_check_flag);
     print_log_impl(out);
   }
 }
--- a/src/hotspot/share/utilities/vmError.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/hotspot/share/utilities/vmError.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1757,7 +1757,7 @@
   // from racing with Threads::add() or Threads::remove() as we
   // generate the hs_err_pid file. This makes our ErrorHandling tests
   // more stable.
-  MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(Threads_lock->owned_by_self() ? NULL : Threads_lock, Mutex::_no_safepoint_check_flag);
 
   switch (how) {
     case  1: vmassert(str == NULL, "expected null"); break;
--- a/src/java.base/share/classes/java/io/LineNumberReader.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/io/LineNumberReader.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, 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
@@ -261,6 +261,11 @@
      */
     public void mark(int readAheadLimit) throws IOException {
         synchronized (lock) {
+            // If the most recently read character is '\r', then increment the
+            // read ahead limit as in this case if the next character is '\n',
+            // two characters would actually be read by the next read().
+            if (skipLF)
+                readAheadLimit++;
             super.mark(readAheadLimit);
             markedLineNumber = lineNumber;
             markedSkipLF     = skipLF;
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Fri May 03 14:59:32 2019 -0400
@@ -1893,6 +1893,16 @@
      * otherwise, if unnamed, it will set the class path to the current
      * working directory.
      *
+     * <p> JAR files on the class path may contain a {@code Class-Path} manifest
+     * attribute to specify dependent JAR files to be included in the class path.
+     * {@code Class-Path} entries must meet certain conditions for validity (see
+     * the <a href="{@docRoot}/../specs/jar/jar.html#class-path-attribute">
+     * JAR File Specification</a> for details).  Invalid {@code Class-Path}
+     * entries are ignored.  For debugging purposes, ignored entries can be
+     * printed to the console if the
+     * {@systemProperty jdk.net.URLClassPath.showIgnoredClassPathEntries} system
+     * property is set to {@code true}.
+     *
      * @return  The system {@code ClassLoader}
      *
      * @throws  SecurityException
--- a/src/java.base/share/classes/java/lang/String.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/String.java	Fri May 03 14:59:32 2019 -0400
@@ -1020,9 +1020,8 @@
         }
         if (anObject instanceof String) {
             String aString = (String)anObject;
-            if (coder() == aString.coder()) {
-                return isLatin1() ? StringLatin1.equals(value, aString.value)
-                                  : StringUTF16.equals(value, aString.value);
+            if (!COMPACT_STRINGS || this.coder == aString.coder) {
+                return StringLatin1.equals(value, aString.value);
             }
         }
         return false;
@@ -1057,7 +1056,8 @@
         }
         byte v1[] = value;
         byte v2[] = sb.getValue();
-        if (coder() == sb.getCoder()) {
+        byte coder = coder();
+        if (coder == sb.getCoder()) {
             int n = v1.length;
             for (int i = 0; i < n; i++) {
                 if (v1[i] != v2[i]) {
@@ -1065,7 +1065,7 @@
                 }
             }
         } else {
-            if (!isLatin1()) {  // utf16 str and latin1 abs can never be "equal"
+            if (coder != LATIN1) {  // utf16 str and latin1 abs can never be "equal"
                 return false;
             }
             return StringUTF16.contentEquals(v1, v2, len);
@@ -1209,12 +1209,13 @@
     public int compareTo(String anotherString) {
         byte v1[] = value;
         byte v2[] = anotherString.value;
-        if (coder() == anotherString.coder()) {
-            return isLatin1() ? StringLatin1.compareTo(v1, v2)
-                              : StringUTF16.compareTo(v1, v2);
+        byte coder = coder();
+        if (coder == anotherString.coder()) {
+            return coder == LATIN1 ? StringLatin1.compareTo(v1, v2)
+                                   : StringUTF16.compareTo(v1, v2);
         }
-        return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
-                          : StringUTF16.compareToLatin1(v1, v2);
+        return coder == LATIN1 ? StringLatin1.compareToUTF16(v1, v2)
+                               : StringUTF16.compareToLatin1(v1, v2);
      }
 
     /**
@@ -1238,12 +1239,13 @@
         public int compare(String s1, String s2) {
             byte v1[] = s1.value;
             byte v2[] = s2.value;
-            if (s1.coder() == s2.coder()) {
-                return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2)
-                                     : StringUTF16.compareToCI(v1, v2);
+            byte coder = s1.coder();
+            if (coder == s2.coder()) {
+                return coder == LATIN1 ? StringLatin1.compareToCI(v1, v2)
+                                       : StringUTF16.compareToCI(v1, v2);
             }
-            return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2)
-                                 : StringUTF16.compareToCI_Latin1(v1, v2);
+            return coder == LATIN1 ? StringLatin1.compareToCI_UTF16(v1, v2)
+                                   : StringUTF16.compareToCI_Latin1(v1, v2);
         }
 
         /** Replaces the de-serialized object. */
@@ -1317,7 +1319,8 @@
              (ooffset > (long)other.length() - len)) {
             return false;
         }
-        if (coder() == other.coder()) {
+        byte coder = coder();
+        if (coder == other.coder()) {
             if (!isLatin1() && (len > 0)) {
                 toffset = toffset << 1;
                 ooffset = ooffset << 1;
@@ -1329,7 +1332,7 @@
                 }
             }
         } else {
-            if (coder() == LATIN1) {
+            if (coder == LATIN1) {
                 while (len-- > 0) {
                     if (StringLatin1.getChar(tv, toffset++) !=
                         StringUTF16.getChar(ov, ooffset++)) {
@@ -1411,12 +1414,13 @@
         }
         byte tv[] = value;
         byte ov[] = other.value;
-        if (coder() == other.coder()) {
-            return isLatin1()
+        byte coder = coder();
+        if (coder == other.coder()) {
+            return coder == LATIN1
               ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
               : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
         }
-        return isLatin1()
+        return coder == LATIN1
               ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
               : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
     }
@@ -1447,15 +1451,16 @@
         byte pa[] = prefix.value;
         int po = 0;
         int pc = pa.length;
-        if (coder() == prefix.coder()) {
-            int to = isLatin1() ? toffset : toffset << 1;
+        byte coder = coder();
+        if (coder == prefix.coder()) {
+            int to = (coder == LATIN1) ? toffset : toffset << 1;
             while (po < pc) {
                 if (ta[to++] != pa[po++]) {
                     return false;
                 }
             }
         } else {
-            if (isLatin1()) {  // && pcoder == UTF16
+            if (coder == LATIN1) {  // && pcoder == UTF16
                 return false;
             }
             // coder == UTF16 && pcoder == LATIN1)
@@ -1688,11 +1693,12 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str) {
-        if (coder() == str.coder()) {
+        byte coder = coder();
+        if (coder == str.coder()) {
             return isLatin1() ? StringLatin1.indexOf(value, str.value)
                               : StringUTF16.indexOf(value, str.value);
         }
-        if (coder() == LATIN1) {  // str.coder == UTF16
+        if (coder == LATIN1) {  // str.coder == UTF16
             return -1;
         }
         return StringUTF16.indexOfLatin1(value, str.value);
--- a/src/java.base/share/classes/java/lang/StringConcatHelper.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java	Fri May 03 14:59:32 2019 -0400
@@ -144,7 +144,7 @@
      * @param value      boolean value to encode
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, boolean value) {
+    private static long prepend(long indexCoder, byte[] buf, boolean value) {
         int index = (int)indexCoder;
         if (indexCoder < UTF16) {
             if (value) {
@@ -178,17 +178,41 @@
     }
 
     /**
-     * Prepends the stringly representation of byte value into buffer,
+     * Prepends constant and the stringly representation of value into buffer,
      * given the coder and final index. Index is measured in chars, not in bytes!
      *
      * @param indexCoder final char index in the buffer, along with coder packed
      *                   into higher bits.
      * @param buf        buffer to append to
-     * @param value      byte value to encode
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, byte value) {
-        return prepend(indexCoder, buf, (int)value);
+    static long prepend(long indexCoder, byte[] buf, String prefix, boolean value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
+    }
+
+    /**
+     * Prepends constant and the stringly representation of value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param indexCoder final char index in the buffer, along with coder packed
+     *                   into higher bits.
+     * @param buf        buffer to append to
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
+     * @return           updated index (coder value retained)
+     */
+    static long prepend(long indexCoder, byte[] buf, String prefix, byte value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, (int)value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
     }
 
     /**
@@ -201,7 +225,7 @@
      * @param value      char value to encode
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, char value) {
+    private static long prepend(long indexCoder, byte[] buf, char value) {
         if (indexCoder < UTF16) {
             buf[(int)(--indexCoder)] = (byte) (value & 0xFF);
         } else {
@@ -211,17 +235,41 @@
     }
 
     /**
-     * Prepends the stringly representation of short value into buffer,
+     * Prepends constant and the stringly representation of value into buffer,
      * given the coder and final index. Index is measured in chars, not in bytes!
      *
      * @param indexCoder final char index in the buffer, along with coder packed
      *                   into higher bits.
      * @param buf        buffer to append to
-     * @param value      short value to encode
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, short value) {
-        return prepend(indexCoder, buf, (int)value);
+    static long prepend(long indexCoder, byte[] buf, String prefix, char value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
+    }
+
+    /**
+     * Prepends constant and the stringly representation of value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param indexCoder final char index in the buffer, along with coder packed
+     *                   into higher bits.
+     * @param buf        buffer to append to
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
+     * @return           updated index (coder value retained)
+     */
+    static long prepend(long indexCoder, byte[] buf, String prefix, short value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, (int)value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
     }
 
     /**
@@ -234,7 +282,7 @@
      * @param value      integer value to encode
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, int value) {
+    private static long prepend(long indexCoder, byte[] buf, int value) {
         if (indexCoder < UTF16) {
             return Integer.getChars(value, (int)indexCoder, buf);
         } else {
@@ -243,6 +291,25 @@
     }
 
     /**
+     * Prepends constant and the stringly representation of value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param indexCoder final char index in the buffer, along with coder packed
+     *                   into higher bits.
+     * @param buf        buffer to append to
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
+     * @return           updated index (coder value retained)
+     */
+    static long prepend(long indexCoder, byte[] buf, String prefix, int value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
+    }
+
+    /**
      * Prepends the stringly representation of long value into buffer,
      * given the coder and final index. Index is measured in chars, not in bytes!
      *
@@ -252,7 +319,7 @@
      * @param value      long value to encode
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, long value) {
+    private static long prepend(long indexCoder, byte[] buf, long value) {
         if (indexCoder < UTF16) {
             return Long.getChars(value, (int)indexCoder, buf);
         } else {
@@ -261,6 +328,25 @@
     }
 
     /**
+     * Prepends constant and the stringly representation of value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param indexCoder final char index in the buffer, along with coder packed
+     *                   into higher bits.
+     * @param buf        buffer to append to
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
+     * @return           updated index (coder value retained)
+     */
+    static long prepend(long indexCoder, byte[] buf, String prefix, long value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
+    }
+
+    /**
      * Prepends the stringly representation of String value into buffer,
      * given the coder and final index. Index is measured in chars, not in bytes!
      *
@@ -270,7 +356,7 @@
      * @param value      String value to encode
      * @return           updated index (coder value retained)
      */
-    static long prepend(long indexCoder, byte[] buf, String value) {
+    private static long prepend(long indexCoder, byte[] buf, String value) {
         indexCoder -= value.length();
         if (indexCoder < UTF16) {
             value.getBytes(buf, (int)indexCoder, String.LATIN1);
@@ -281,6 +367,25 @@
     }
 
     /**
+     * Prepends constant and the stringly representation of value into buffer,
+     * given the coder and final index. Index is measured in chars, not in bytes!
+     *
+     * @param indexCoder final char index in the buffer, along with coder packed
+     *                   into higher bits.
+     * @param buf        buffer to append to
+     * @param prefix     a constant to prepend before value
+     * @param value      boolean value to encode
+     * @param suffix     a constant to prepend after value
+     * @return           updated index (coder value retained)
+     */
+    static long prepend(long indexCoder, byte[] buf, String prefix, String value, String suffix) {
+        if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix);
+        indexCoder = prepend(indexCoder, buf, value);
+        if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix);
+        return indexCoder;
+    }
+
+    /**
      * Instantiates the String with given buffer and coder
      * @param buf           buffer to use
      * @param indexCoder    remaining index (should be zero) and coder
--- a/src/java.base/share/classes/java/lang/Thread.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/Thread.java	Fri May 03 14:59:32 2019 -0400
@@ -194,11 +194,6 @@
     private final long stackSize;
 
     /*
-     * JVM-private state that persists after native thread termination.
-     */
-    private long nativeParkEventPointer;
-
-    /*
      * Thread ID
      */
     private final long tid;
--- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Fri May 03 14:59:32 2019 -0400
@@ -72,7 +72,7 @@
      *
      * @param name the fully qualified (dot-separated) binary class name
      * @return a {@linkplain ClassDesc} describing the desired class
-     * @throws NullPointerException if any argument is {@code null}
+     * @throws NullPointerException if the argument is {@code null}
      * @throws IllegalArgumentException if the name string is not in the
      * correct format
      */
@@ -123,7 +123,7 @@
      *
      * @param descriptor a field descriptor string
      * @return a {@linkplain ClassDesc} describing the desired class
-     * @throws NullPointerException if any argument is {@code null}
+     * @throws NullPointerException if the argument is {@code null}
      * @throws IllegalArgumentException if the name string is not in the
      * correct format
      * @jvms 4.3.2 Field Descriptors
@@ -193,7 +193,7 @@
      *
      * @param nestedName the unqualified name of the nested class
      * @return a {@linkplain ClassDesc} describing the nested class
-     * @throws NullPointerException if any argument is {@code null}
+     * @throws NullPointerException if the argument is {@code null}
      * @throws IllegalStateException if this {@linkplain ClassDesc} does not
      * describe a class or interface type
      * @throws IllegalArgumentException if the nested class name is invalid
--- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java	Fri May 03 14:59:32 2019 -0400
@@ -25,6 +25,7 @@
 
 package java.lang.invoke;
 
+import jdk.internal.access.SharedSecrets;
 import jdk.internal.loader.BootLoader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.FieldVisitor;
@@ -37,6 +38,7 @@
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -575,19 +577,19 @@
 
             // load class
             InvokerBytecodeGenerator.maybeDump(classBCName(className), classFile);
-            Class<?> speciesCode;
-
-            MethodHandles.Lookup lookup = IMPL_LOOKUP.in(topClass());
-            speciesCode = AccessController.doPrivileged(new PrivilegedAction<>() {
-                @Override
-                public Class<?> run() {
-                    try {
-                        return lookup.defineClass(classFile);
-                    } catch (Exception ex) {
-                        throw newInternalError(ex);
-                    }
-                }
-            });
+            ClassLoader cl = topClass.getClassLoader();
+            ProtectionDomain pd = null;
+            if (cl != null) {
+                pd = AccessController.doPrivileged(
+                        new PrivilegedAction<>() {
+                            @Override
+                            public ProtectionDomain run() {
+                                return topClass().getProtectionDomain();
+                            }
+                        });
+            }
+            Class<?> speciesCode = SharedSecrets.getJavaLangAccess()
+                    .defineClass(cl, className, classFile, pd, "_ClassSpecializer_generateConcreteSpeciesCode");
             return speciesCode.asSubclass(topClass());
         }
 
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -31,16 +31,13 @@
 import jdk.internal.org.objectweb.asm.Label;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.vm.annotation.ForceInline;
 import sun.invoke.util.Wrapper;
-import sun.security.action.GetPropertyAction;
 
 import java.lang.invoke.MethodHandles.Lookup;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
@@ -1531,27 +1528,33 @@
             if (recipe.getElements().size() == 2) {
                 // Two object arguments
                 if (mt.parameterCount() == 2 &&
-                        !mt.parameterType(0).isPrimitive() &&
-                        !mt.parameterType(1).isPrimitive()) {
+                    !mt.parameterType(0).isPrimitive() &&
+                    !mt.parameterType(1).isPrimitive() &&
+                    recipe.getElements().get(0).getTag() == TAG_ARG &&
+                    recipe.getElements().get(1).getTag() == TAG_ARG) {
+
                     return SIMPLE;
-                }
-                // One element is a constant
-                if (mt.parameterCount() == 1 && !mt.parameterType(0).isPrimitive()) {
+
+                } else if (mt.parameterCount() == 1 &&
+                           !mt.parameterType(0).isPrimitive()) {
+                    // One Object argument, one constant
                     MethodHandle mh = SIMPLE;
-                    // Insert constant element
 
-                    // First recipe element is a constant
                     if (recipe.getElements().get(0).getTag() == TAG_CONST &&
-                        recipe.getElements().get(1).getTag() != TAG_CONST) {
+                        recipe.getElements().get(1).getTag() == TAG_ARG) {
+                        // First recipe element is a constant
                         return MethodHandles.insertArguments(mh, 0,
                                 recipe.getElements().get(0).getValue());
+
                     } else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
-                               recipe.getElements().get(0).getTag() != TAG_CONST) {
+                               recipe.getElements().get(0).getTag() == TAG_ARG) {
+                        // Second recipe element is a constant
                         return MethodHandles.insertArguments(mh, 1,
                                 recipe.getElements().get(1).getValue());
+
                     }
-                    // else... fall-through to slow-path
                 }
+                // else... fall-through to slow-path
             }
 
             // Create filters and obtain filtered parameter types. Filters would be used in the beginning
@@ -1579,26 +1582,49 @@
 
             mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes);
 
+            long initialLengthCoder = INITIAL_CODER;
+
             // Mix in prependers. This happens when (byte[], long) = (storage, indexCoder) is already
             // known from the combinators below. We are assembling the string backwards, so the index coded
             // into indexCoder is the *ending* index.
+
+            // We need one prepender per argument, but also need to fold in constants. We do so by greedily
+            // create prependers that fold in surrounding constants into the argument prepender. This reduces
+            // the number of unique MH combinator tree shapes we'll create in an application.
+            String prefixConstant = null, suffixConstant = null;
+            int pos = -1;
             for (RecipeElement el : recipe.getElements()) {
                 // Do the prepend, and put "new" index at index 1
                 switch (el.getTag()) {
                     case TAG_CONST: {
-                        MethodHandle prepender = MethodHandles.insertArguments(prepender(String.class), 2, el.getValue());
-                        mh = MethodHandles.filterArgumentsWithCombiner(mh, 1, prepender,
-                                1, 0 // indexCoder, storage
-                        );
+                        String constantValue = el.getValue();
+
+                        // Eagerly update the initialLengthCoder value
+                        initialLengthCoder = (long)mixer(String.class).invoke(initialLengthCoder, constantValue);
+
+                        if (pos < 0) {
+                            // Collecting into prefixConstant
+                            prefixConstant = prefixConstant == null ? constantValue : prefixConstant + constantValue;
+                        } else {
+                            // Collecting into suffixConstant
+                            suffixConstant = suffixConstant == null ? constantValue : suffixConstant + constantValue;
+                        }
                         break;
                     }
                     case TAG_ARG: {
-                        int pos = el.getArgPos();
-                        MethodHandle prepender = prepender(ptypes[pos]);
-                        mh = MethodHandles.filterArgumentsWithCombiner(mh, 1, prepender,
+
+                        if (pos >= 0) {
+                            // Flush the previous non-constant arg with any prefix/suffix constant
+                            mh = MethodHandles.filterArgumentsWithCombiner(
+                                mh, 1,
+                                prepender(prefixConstant, ptypes[pos], suffixConstant),
                                 1, 0, // indexCoder, storage
                                 2 + pos  // selected argument
-                        );
+                            );
+                            prefixConstant = suffixConstant = null;
+                        }
+                        // Mark the pos of next non-constant arg
+                        pos = el.getArgPos();
                         break;
                     }
                     default:
@@ -1606,6 +1632,24 @@
                 }
             }
 
+            // Insert any trailing args, constants
+            if (pos >= 0) {
+                mh = MethodHandles.filterArgumentsWithCombiner(
+                    mh, 1,
+                    prepender(prefixConstant, ptypes[pos], suffixConstant),
+                    1, 0, // indexCoder, storage
+                    2 + pos  // selected argument
+                );
+            } else if (prefixConstant != null) {
+                assert (suffixConstant == null);
+                // Sole prefixConstant can only happen if there were no non-constant arguments
+                mh = MethodHandles.filterArgumentsWithCombiner(
+                    mh, 1,
+                    MethodHandles.insertArguments(prepender(null, String.class, null), 2, prefixConstant),
+                    1, 0 // indexCoder, storage
+                );
+            }
+
             // Fold in byte[] instantiation at argument 0
             mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, NEW_ARRAY,
                     1 // index
@@ -1624,12 +1668,11 @@
             //
             // The method handle shape before and after all mixers are combined in is:
             //   (long, <args>)String = ("indexCoder", <args>)
-            long initialLengthCoder = INITIAL_CODER;
+
             for (RecipeElement el : recipe.getElements()) {
                 switch (el.getTag()) {
                     case TAG_CONST:
-                        String constant = el.getValue();
-                        initialLengthCoder = (long)mixer(String.class).invoke(initialLengthCoder, constant);
+                        // Constants already handled in the code above
                         break;
                     case TAG_ARG:
                         int ac = el.getArgPos();
@@ -1661,8 +1704,10 @@
             return mh;
         }
 
-        private static MethodHandle prepender(Class<?> cl) {
-            return PREPENDERS.computeIfAbsent(cl, PREPEND);
+        private static MethodHandle prepender(String prefix, Class<?> cl, String suffix) {
+            return MethodHandles.insertArguments(
+                    MethodHandles.insertArguments(
+                        PREPENDERS.computeIfAbsent(cl, PREPEND),2, prefix), 3, suffix);
         }
 
         private static MethodHandle mixer(Class<?> cl) {
@@ -1670,16 +1715,16 @@
         }
 
         // This one is deliberately non-lambdified to optimize startup time:
-        private static final Function<Class<?>, MethodHandle> PREPEND = new Function<Class<?>, MethodHandle>() {
+        private static final Function<Class<?>, MethodHandle> PREPEND = new Function<>() {
             @Override
             public MethodHandle apply(Class<?> c) {
                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", long.class, long.class, byte[].class,
-                        Wrapper.asPrimitiveType(c));
+                        String.class, Wrapper.asPrimitiveType(c), String.class);
             }
         };
 
         // This one is deliberately non-lambdified to optimize startup time:
-        private static final Function<Class<?>, MethodHandle> MIX = new Function<Class<?>, MethodHandle>() {
+        private static final Function<Class<?>, MethodHandle> MIX = new Function<>() {
             @Override
             public MethodHandle apply(Class<?> c) {
                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mix", long.class, long.class,
--- a/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -74,6 +74,12 @@
     /* indicates connection reset state */
     private volatile boolean connectionReset;
 
+    /* indicates whether impl is bound  */
+    boolean isBound;
+
+    /* indicates whether impl is connected  */
+    volatile boolean isConnected;
+
    /* whether this Socket is a stream (TCP) socket or not (UDP)
     */
     protected boolean stream;
@@ -105,6 +111,10 @@
         return isReusePortAvailable;
     }
 
+    AbstractPlainSocketImpl(boolean isServer) {
+        super(isServer);
+    }
+
     /**
      * Returns a set of SocketOptions supported by this impl and by this impl's
      * socket (Socket or ServerSocket)
@@ -148,10 +158,6 @@
             socketCreate(true);
             SocketCleanable.register(fd);
         }
-        if (socket != null)
-            socket.setCreated();
-        if (serverSocket != null)
-            serverSocket.setCreated();
     }
 
     /**
@@ -180,6 +186,7 @@
                        it will be passed up the call stack */
                 }
             }
+            isConnected = connected;
         }
     }
 
@@ -195,6 +202,7 @@
 
         try {
             connectToAddress(address, port, timeout);
+            isConnected = true;
             return;
         } catch (IOException e) {
             // everything failed
@@ -236,6 +244,7 @@
                        it will be passed up the call stack */
                 }
             }
+            isConnected = connected;
         }
     }
 
@@ -393,7 +402,7 @@
 
     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
         synchronized (fdLock) {
-            if (!closePending && (socket == null || !socket.isBound())) {
+            if (!closePending && !isBound) {
                 NetHooks.beforeTcpConnect(fd, address, port);
             }
         }
@@ -407,14 +416,6 @@
                         throw new SocketException ("Socket closed");
                     }
                 }
-                // If we have a ref. to the Socket, then sets the flags
-                // created, bound & connected to true.
-                // This is normally done in Socket.connect() but some
-                // subclasses of Socket may call impl.connect() directly!
-                if (socket != null) {
-                    socket.setBound();
-                    socket.setConnected();
-                }
             } finally {
                 releaseFD();
             }
@@ -433,15 +434,12 @@
         throws IOException
     {
        synchronized (fdLock) {
-            if (!closePending && (socket == null || !socket.isBound())) {
+            if (!closePending && !isBound) {
                 NetHooks.beforeTcpBind(fd, address, lport);
             }
         }
         socketBind(address, lport);
-        if (socket != null)
-            socket.setBound();
-        if (serverSocket != null)
-            serverSocket.setBound();
+        isBound = true;
     }
 
     /**
@@ -727,7 +725,7 @@
         socketClose0(false);
     }
 
-    abstract void socketCreate(boolean isServer) throws IOException;
+    abstract void socketCreate(boolean stream) throws IOException;
     abstract void socketConnect(InetAddress address, int port, int timeout)
         throws IOException;
     abstract void socketBind(InetAddress address, int port)
--- a/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -51,6 +51,7 @@
     private static final Method doTunneling;
 
     private final String server;
+    private final Socket socket;
     private InetSocketAddress external_address;
     private HashMap<Integer, Object> optionsMap = new HashMap<>();
 
@@ -75,8 +76,9 @@
         }
     }
 
-    HttpConnectSocketImpl(Proxy proxy, SocketImpl delegate) {
+    HttpConnectSocketImpl(Proxy proxy, SocketImpl delegate, Socket socket) {
         super(delegate);
+        this.socket = socket;
         SocketAddress a = proxy.address();
         if ( !(a instanceof InetSocketAddress) )
             throw new IllegalArgumentException("Unsupported address type");
@@ -97,17 +99,6 @@
     }
 
     @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
     {
@@ -137,7 +128,7 @@
 
         // update the Sockets impl to the impl from the http Socket
         SocketImpl si = httpSocket.impl;
-        getSocket().setImpl(si);
+        socket.setImpl(si);
 
         // best effort is made to try and reset options previously set
         Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet();
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Fri May 03 14:59:32 2019 -0400
@@ -72,11 +72,6 @@
     private SocketImpl impl;
 
     /**
-     * Are we using an older SocketImpl?
-     */
-    private boolean oldImpl = false;
-
-    /**
      * Creates a server socket with a user-specified {@code SocketImpl}.
      *
      * @param      impl an instance of a SocketImpl to use on the ServerSocket.
@@ -87,7 +82,6 @@
      */
     protected ServerSocket(SocketImpl impl) {
         this.impl = impl;
-        impl.setServerSocket(this);
     }
 
     /**
@@ -270,36 +264,13 @@
         return impl;
     }
 
-    private void checkOldImpl() {
-        if (impl == null)
-            return;
-        // SocketImpl.connect() is a protected method, therefore we need to use
-        // getDeclaredMethod, therefore we need permission to access the member
-        try {
-            AccessController.doPrivileged(
-                new PrivilegedExceptionAction<Void>() {
-                    public Void run() throws NoSuchMethodException {
-                        impl.getClass().getDeclaredMethod("connect",
-                                                          SocketAddress.class,
-                                                          int.class);
-                        return null;
-                    }
-                });
-        } catch (java.security.PrivilegedActionException e) {
-            oldImpl = true;
-        }
-    }
-
     private void setImpl() {
         SocketImplFactory factory = ServerSocket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
-            checkOldImpl();
         } else {
             impl = SocketImpl.createPlatformSocketImpl(true);
         }
-        if (impl != null)
-            impl.setServerSocket(this);
     }
 
     /**
@@ -368,7 +339,7 @@
     public void bind(SocketAddress endpoint, int backlog) throws IOException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        if (!oldImpl && isBound())
+        if (isBound())
             throw new SocketException("Already bound");
         if (endpoint == null)
             endpoint = new InetSocketAddress(0);
@@ -722,8 +693,7 @@
      * @since 1.4
      */
     public boolean isBound() {
-        // Before 1.3 ServerSockets were always bound during creation
-        return bound || oldImpl;
+        return bound;
     }
 
     /**
@@ -866,14 +836,6 @@
                 ",localport=" + impl.getLocalPort()  + "]";
     }
 
-    void setBound() {
-        bound = true;
-    }
-
-    void setCreated() {
-        created = true;
-    }
-
     /**
      * The factory for all server sockets.
      */
--- a/src/java.base/share/classes/java/net/Socket.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/Socket.java	Fri May 03 14:59:32 2019 -0400
@@ -72,11 +72,6 @@
     SocketImpl impl;
 
     /**
-     * Are we using an older SocketImpl?
-     */
-    private boolean oldImpl = false;
-
-    /**
      * Socket input/output streams
      */
     private volatile InputStream in;
@@ -158,8 +153,7 @@
             // 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);
+                                              : new HttpConnectSocketImpl(p, delegate, this);
         } else {
             if (p == Proxy.NO_PROXY) {
                 // create a platform or custom SocketImpl for the DIRECT case
@@ -169,7 +163,6 @@
                 } else {
                     impl = factory.createSocketImpl();
                 }
-                impl.setSocket(this);
             } else
                 throw new IllegalArgumentException("Invalid Proxy");
         }
@@ -188,10 +181,6 @@
      */
     protected Socket(SocketImpl impl) throws SocketException {
         this.impl = impl;
-        if (impl != null) {
-            checkOldImpl();
-            this.impl.setSocket(this);
-        }
     }
 
     /**
@@ -486,37 +475,8 @@
         }
     }
 
-    private void checkOldImpl() {
-        if (impl == null)
-            return;
-        // SocketImpl.connect() is a protected method, therefore we need to use
-        // getDeclaredMethod, therefore we need permission to access the member
-
-        oldImpl = AccessController.doPrivileged
-                                (new PrivilegedAction<>() {
-            public Boolean run() {
-                Class<?> clazz = impl.getClass();
-                while (true) {
-                    try {
-                        clazz.getDeclaredMethod("connect", SocketAddress.class, int.class);
-                        return Boolean.FALSE;
-                    } catch (NoSuchMethodException e) {
-                        clazz = clazz.getSuperclass();
-                        // java.net.SocketImpl class will always have this abstract method.
-                        // If we have not found it by now in the hierarchy then it does not
-                        // exist, we are an old style impl.
-                        if (clazz.equals(java.net.SocketImpl.class)) {
-                            return Boolean.TRUE;
-                        }
-                    }
-                }
-            }
-        });
-    }
-
     void setImpl(SocketImpl si) {
          impl = si;
-         impl.setSocket(this);
     }
 
     /**
@@ -527,14 +487,11 @@
         SocketImplFactory factory = Socket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
-            checkOldImpl();
         } else {
             // 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);
     }
 
     /**
@@ -596,7 +553,7 @@
         if (isClosed())
             throw new SocketException("Socket is closed");
 
-        if (!oldImpl && isConnected())
+        if (isConnected())
             throw new SocketException("already connected");
 
         if (!(endpoint instanceof InetSocketAddress))
@@ -616,15 +573,7 @@
         }
         if (!created)
             createImpl(true);
-        if (!oldImpl)
-            impl.connect(epoint, timeout);
-        else if (timeout == 0) {
-            if (epoint.isUnresolved())
-                impl.connect(addr.getHostName(), port);
-            else
-                impl.connect(addr, port);
-        } else
-            throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
+        impl.connect(epoint, timeout);
         connected = true;
         /*
          * If the socket was not bound before the connect, it is now because
@@ -654,7 +603,7 @@
     public void bind(SocketAddress bindpoint) throws IOException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        if (!oldImpl && isBound())
+        if (isBound())
             throw new SocketException("Already bound");
 
         if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
@@ -694,18 +643,6 @@
         bound = true;
     }
 
-    void setCreated() {
-        created = true;
-    }
-
-    void setBound() {
-        bound = true;
-    }
-
-    void setConnected() {
-        connected = true;
-    }
-
     /**
      * Returns the address to which the socket is connected.
      * <p>
@@ -957,6 +894,7 @@
     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;
@@ -975,6 +913,7 @@
         public int available() throws IOException {
             return in.available();
         }
+
         @Override
         public void close() throws IOException {
             parent.close();
@@ -1040,6 +979,7 @@
         public void write(byte b[], int off, int len) throws IOException {
             out.write(b, off, len);
         }
+
         @Override
         public void close() throws IOException {
             parent.close();
@@ -1672,8 +1612,7 @@
      * @since 1.4
      */
     public boolean isConnected() {
-        // Before 1.3 Sockets were always connected during creation
-        return connected || oldImpl;
+        return connected;
     }
 
     /**
@@ -1689,8 +1628,7 @@
      * @see #bind
      */
     public boolean isBound() {
-        // Before 1.3 Sockets were always bound during creation
-        return bound || oldImpl;
+        return bound;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -51,16 +51,10 @@
      */
     @SuppressWarnings("unchecked")
     static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
-        return (S) new PlainSocketImpl();
+        return (S) new PlainSocketImpl(server);
     }
 
     /**
-     * The actual Socket object.
-     */
-    Socket socket = null;
-    ServerSocket serverSocket = null;
-
-    /**
      * The file descriptor object for this socket.
      */
     protected FileDescriptor fd;
@@ -81,6 +75,23 @@
     protected int localport;
 
     /**
+     * Whether this is a server or not.
+     */
+    final boolean isServer;
+
+
+    SocketImpl(boolean isServer) {
+        this.isServer = isServer;
+    }
+
+    /**
+     * Initialize a new instance of this class
+     */
+    public SocketImpl() {
+        this.isServer = false;
+    }
+
+    /**
      * Creates either a stream or a datagram socket.
      *
      * @param      stream   if {@code true}, create a stream socket;
@@ -300,22 +311,6 @@
         return localport;
     }
 
-    void setSocket(Socket soc) {
-        this.socket = soc;
-    }
-
-    Socket getSocket() {
-        return socket;
-    }
-
-    void setServerSocket(ServerSocket soc) {
-        this.serverSocket = soc;
-    }
-
-    ServerSocket getServerSocket() {
-        return serverSocket;
-    }
-
     /**
      * Returns the address and port of this socket as a {@code String}.
      *
@@ -395,11 +390,9 @@
      * @since 9
      */
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE &&
-                (getSocket() != null)) {
+        if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
             setOption(SocketOptions.SO_KEEPALIVE, value);
-        } else if (name == StandardSocketOptions.SO_SNDBUF &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
             setOption(SocketOptions.SO_SNDBUF, value);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             setOption(SocketOptions.SO_RCVBUF, value);
@@ -408,13 +401,11 @@
         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
             supportedOptions().contains(name)) {
             setOption(SocketOptions.SO_REUSEPORT, value);
-        } else if (name == StandardSocketOptions.SO_LINGER &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
             setOption(SocketOptions.SO_LINGER, value);
         } else if (name == StandardSocketOptions.IP_TOS) {
             setOption(SocketOptions.IP_TOS, value);
-        } else if (name == StandardSocketOptions.TCP_NODELAY &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY && !isServer) {
             setOption(SocketOptions.TCP_NODELAY, value);
         } else {
             throw new UnsupportedOperationException("unsupported option");
@@ -438,11 +429,9 @@
      */
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE &&
-                (getSocket() != null)) {
+        if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
             return (T)getOption(SocketOptions.SO_KEEPALIVE);
-        } else if (name == StandardSocketOptions.SO_SNDBUF &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
             return (T)getOption(SocketOptions.SO_SNDBUF);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             return (T)getOption(SocketOptions.SO_RCVBUF);
@@ -451,13 +440,11 @@
         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
             supportedOptions().contains(name)) {
             return (T)getOption(SocketOptions.SO_REUSEPORT);
-        } else if (name == StandardSocketOptions.SO_LINGER &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
             return (T)getOption(SocketOptions.SO_LINGER);
         } else if (name == StandardSocketOptions.IP_TOS) {
             return (T)getOption(SocketOptions.IP_TOS);
-        } else if (name == StandardSocketOptions.TCP_NODELAY &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY && !isServer) {
             return (T)getOption(SocketOptions.TCP_NODELAY);
         } else {
             throw new UnsupportedOperationException("unsupported option");
@@ -504,7 +491,7 @@
      * @since 9
      */
     protected Set<SocketOption<?>> supportedOptions() {
-        if (getSocket() != null) {
+        if (!isServer) {
             return socketOptions;
         } else {
             return serverSocketOptions;
--- a/src/java.base/share/classes/java/net/SocketInputStream.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketInputStream.java	Fri May 03 14:59:32 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
@@ -48,7 +48,6 @@
     private boolean eof;
     private AbstractPlainSocketImpl impl = null;
     private byte temp[];
-    private Socket socket = null;
 
     /**
      * Creates a new SocketInputStream. Can only be called
@@ -59,7 +58,6 @@
     SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
         super(impl.getFileDescriptor());
         this.impl = impl;
-        socket = impl.getSocket();
     }
 
     /**
@@ -236,25 +234,14 @@
         return eof ? 0 : available;
     }
 
-    /**
-     * Closes the stream.
-     */
-    private boolean closing = false;
-    public void close() throws IOException {
-        // Prevent recursion. See BugId 4484411
-        if (closing)
-            return;
-        closing = true;
-        if (socket != null) {
-            if (!socket.isClosed())
-                socket.close();
-        } else
-            impl.close();
-        closing = false;
+    void setEOF(boolean eof) {
+        this.eof = eof;
     }
 
-    void setEOF(boolean eof) {
-        this.eof = eof;
+    public void close() throws IOException {
+        // No longer used. Socket.getInputStream returns an
+        // InputStream which calls Socket.close directly
+        assert false;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocketOutputStream.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketOutputStream.java	Fri May 03 14:59:32 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
@@ -45,7 +45,6 @@
 
     private AbstractPlainSocketImpl impl = null;
     private byte temp[] = new byte[1];
-    private Socket socket = null;
 
     /**
      * Creates a new SocketOutputStream. Can only be called
@@ -56,7 +55,6 @@
     SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
         super(impl.getFileDescriptor());
         this.impl = impl;
-        socket = impl.getSocket();
     }
 
     /**
@@ -150,21 +148,10 @@
         socketWrite(b, off, len);
     }
 
-    /**
-     * Closes the stream.
-     */
-    private boolean closing = false;
     public void close() throws IOException {
-        // Prevent recursion. See BugId 4484411
-        if (closing)
-            return;
-        closing = true;
-        if (socket != null) {
-            if (!socket.isClosed())
-                socket.close();
-        } else
-            impl.close();
-        closing = false;
+        // No longer used. Socket.getOutputStream returns an
+        // OutputStream which calls Socket.close directly
+        assert false;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocksSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -256,17 +256,6 @@
         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
--- a/src/java.base/share/classes/java/net/URL.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/net/URL.java	Fri May 03 14:59:32 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
@@ -1403,8 +1403,9 @@
 
         URLStreamHandlerFactory fac;
         boolean checkedWithFactory = false;
+        boolean overrideableProtocol = isOverrideable(protocol);
 
-        if (isOverrideable(protocol) && jdk.internal.misc.VM.isBooted()) {
+        if (overrideableProtocol && jdk.internal.misc.VM.isBooted()) {
             // Use the factory (if any). Volatile read makes
             // URLStreamHandlerFactory appear fully initialized to current thread.
             fac = factory;
@@ -1440,7 +1441,8 @@
 
             // Check with factory if another thread set a
             // factory since our last check
-            if (!checkedWithFactory && (fac = factory) != null) {
+            if (overrideableProtocol && !checkedWithFactory &&
+                (fac = factory) != null) {
                 handler2 = fac.createURLStreamHandler(protocol);
             }
 
--- a/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java	Fri May 03 14:59:32 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
@@ -23,13 +23,15 @@
  * questions.
  */
 
-/*
- */
-
 package java.nio.channels.spi;
 
 import java.io.IOException;
-import java.nio.channels.*;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.Channel;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.InterruptibleChannel;
+import java.util.concurrent.locks.ReentrantLock;
+
 import jdk.internal.access.SharedSecrets;
 import sun.nio.ch.Interruptible;
 
@@ -84,8 +86,7 @@
 public abstract class AbstractInterruptibleChannel
     implements Channel, InterruptibleChannel
 {
-
-    private final Object closeLock = new Object();
+    private final ReentrantLock closeLock = new ReentrantLock();
     private volatile boolean closed;
 
     /**
@@ -105,11 +106,14 @@
      *          If an I/O error occurs
      */
     public final void close() throws IOException {
-        synchronized (closeLock) {
+        closeLock.lock();
+        try {
             if (closed)
                 return;
             closed = true;
             implCloseChannel();
+        } finally {
+            closeLock.unlock();
         }
     }
 
@@ -153,7 +157,8 @@
         if (interruptor == null) {
             interruptor = new Interruptible() {
                     public void interrupt(Thread target) {
-                        synchronized (closeLock) {
+                        closeLock.lock();
+                        try {
                             if (closed)
                                 return;
                             closed = true;
@@ -161,6 +166,8 @@
                             try {
                                 AbstractInterruptibleChannel.this.implCloseChannel();
                             } catch (IOException x) { }
+                        } finally {
+                            closeLock.unlock();
                         }
                     }};
         }
--- a/src/java.base/share/classes/java/nio/file/FileSystems.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/nio/file/FileSystems.java	Fri May 03 14:59:32 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
@@ -365,14 +365,13 @@
      * systems where the contents of one or more files is treated as a file
      * system.
      *
-     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
-     * installed} providers. It invokes, in turn, each provider's {@link
-     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method
-     * with an empty map. If a provider returns a file system then the iteration
-     * terminates and the file system is returned. If none of the installed
-     * providers return a {@code FileSystem} then an attempt is made to locate
-     * the provider using the given class loader. If a provider returns a file
-     * system then the lookup terminates and the file system is returned.
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path, Map, ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method with an empty map. If none
+     * of the installed providers return a {@code FileSystem} then an attempt is
+     * made to locate the provider using the given class loader. If a provider
+     * returns a file system then the lookup terminates and the file system is
+     * returned.
      *
      * @param   path
      *          the path to the file
@@ -396,10 +395,131 @@
                                            ClassLoader loader)
         throws IOException
     {
+        return newFileSystem(path, Map.of(), loader);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env)
+        throws IOException
+    {
+        return newFileSystem(path, env, null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked with an empty map to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path) throws IOException {
+        return newFileSystem(path, Map.of(), null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers. It invokes, in turn, each provider's {@link
+     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)}
+     * method. If a provider returns a file system then the iteration
+     * terminates and the file system is returned.
+     * If none of the installed providers return a {@code FileSystem} then
+     * an attempt is made to locate the provider using the given class loader.
+     * If a provider returns a file
+     * system, then the lookup terminates and the file system is returned.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     * @param   loader
+     *          the class loader to locate the provider or {@code null} to only
+     *          attempt to locate an installed provider
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env,
+                                           ClassLoader loader)
+        throws IOException
+    {
         if (path == null)
             throw new NullPointerException();
-        Map<String,?> env = Collections.emptyMap();
-
         // check installed providers
         for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
             try {
--- a/src/java.base/share/classes/java/security/Key.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/security/Key.java	Fri May 03 14:59:32 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
@@ -74,7 +74,7 @@
  * </UL>
  *
  * Keys are generally obtained through key generators, certificates,
- * or various Identity classes used to manage keys.
+ * key stores or other classes used to manage keys.
  * Keys may also be obtained from key specifications (transparent
  * representations of the underlying key material) through the use of a key
  * factory (see {@link KeyFactory}).
@@ -119,10 +119,11 @@
     /**
      * Returns the standard algorithm name for this key. For
      * example, "DSA" would indicate that this key is a DSA key.
-     * See the <a href=
+     * See the key related sections (KeyFactory, KeyGenerator,
+     * KeyPairGenerator, and SecretKeyFactory) in the <a href=
      * "{@docRoot}/../specs/security/standard-names.html">
-     * Java Security Standard Algorithm Names</a> document
-     * for more information.
+     * Java Security Standard Algorithm Names Specification</a>
+     * for information about standard key algorithm names.
      *
      * @return the name of the algorithm associated with this key.
      */
--- a/src/java.base/share/classes/java/util/Objects.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/Objects.java	Fri May 03 14:59:32 2019 -0400
@@ -62,10 +62,11 @@
      * Returns {@code true} if the arguments are equal to each other
      * and {@code false} otherwise.
      * Consequently, if both arguments are {@code null}, {@code true}
-     * is returned and if exactly one argument is {@code null}, {@code
-     * false} is returned.  Otherwise, equality is determined by using
-     * the {@link Object#equals equals} method of the first
-     * argument.
+     * is returned.  Otherwise, if the first argument is not {@code
+     * null}, equality is determined by calling the {@link
+     * Object#equals equals} method of the first argument with the
+     * second argument of this method. Otherwise, {@code false} is
+     * returned.
      *
      * @param a an object
      * @param b an object to be compared with {@code a} for equality
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri May 03 14:59:32 2019 -0400
@@ -1129,6 +1129,7 @@
             clone.entrySet = null;
             clone.values = null;
             clone.descendingMap = null;
+            clone.adder = null;
             clone.buildFromSorted(this);
             return clone;
         } catch (CloneNotSupportedException e) {
--- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri May 03 14:59:32 2019 -0400
@@ -413,8 +413,9 @@
             if (oldValue != element) {
                 es = es.clone();
                 es[index] = element;
-                setArray(es);
             }
+            // Ensure volatile write semantics even when oldvalue == element
+            setArray(es);
             return oldValue;
         }
     }
--- a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java	Fri May 03 14:59:32 2019 -0400
@@ -66,7 +66,7 @@
  * <p>The {@link Executors} class provides factory methods for the
  * executor services provided in this package.
  *
- * <h3>Usage Examples</h3>
+ * <h2>Usage Examples</h2>
  *
  * Here is a sketch of a network service in which threads in a thread
  * pool service incoming requests. It uses the preconfigured {@link
--- a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java	Fri May 03 14:59:32 2019 -0400
@@ -65,7 +65,7 @@
  * <p>The {@link Executors} class provides convenient factory methods for
  * the ScheduledExecutorService implementations provided in this package.
  *
- * <h3>Usage Example</h3>
+ * <h2>Usage Example</h2>
  *
  * Here is a class with a method that sets up a ScheduledExecutorService
  * to beep every ten seconds for an hour:
--- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Fri May 03 14:59:32 2019 -0400
@@ -922,13 +922,13 @@
 
                     if (isRunning(c) ||
                         (runStateLessThan(c, STOP) && firstTask == null)) {
-                        if (t.isAlive()) // precheck that t is startable
+                        if (t.getState() != Thread.State.NEW)
                             throw new IllegalThreadStateException();
                         workers.add(w);
+                        workerAdded = true;
                         int s = workers.size();
                         if (s > largestPoolSize)
                             largestPoolSize = s;
-                        workerAdded = true;
                     }
                 } finally {
                     mainLock.unlock();
--- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri May 03 14:59:32 2019 -0400
@@ -104,7 +104,7 @@
  * define a {@code readObject} method that restores this to a known
  * initial state upon deserialization.
  *
- * <h3>Usage</h3>
+ * <h2>Usage</h2>
  *
  * <p>To use this class as the basis of a synchronizer, redefine the
  * following methods, as applicable, by inspecting and/or modifying
@@ -187,7 +187,7 @@
  * {@link java.util.Queue} classes, and {@link LockSupport} blocking
  * support.
  *
- * <h3>Usage Examples</h3>
+ * <h2>Usage Examples</h2>
  *
  * <p>Here is a non-reentrant mutual exclusion lock class that uses
  * the value zero to represent the unlocked state, and one to
--- a/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri May 03 14:59:32 2019 -0400
@@ -138,7 +138,7 @@
  * <p>Except where noted, passing a {@code null} value for any parameter
  * will result in a {@link NullPointerException} being thrown.
  *
- * <h3>Implementation Considerations</h3>
+ * <h2>Implementation Considerations</h2>
  *
  * <p>When waiting upon a {@code Condition}, a &quot;<em>spurious
  * wakeup</em>&quot; is permitted to occur, in
--- a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Fri May 03 14:59:32 2019 -0400
@@ -117,7 +117,7 @@
  * parameter will result in a {@link NullPointerException} being
  * thrown.
  *
- * <h3>Memory Synchronization</h3>
+ * <h2>Memory Synchronization</h2>
  *
  * <p>All {@code Lock} implementations <em>must</em> enforce the same
  * memory synchronization semantics as provided by the built-in monitor
@@ -136,7 +136,7 @@
  * locking/unlocking operations, do not require any memory
  * synchronization effects.
  *
- * <h3>Implementation Considerations</h3>
+ * <h2>Implementation Considerations</h2>
  *
  * <p>The three forms of lock acquisition (interruptible,
  * non-interruptible, and timed) may differ in their performance
--- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri May 03 14:59:32 2019 -0400
@@ -204,7 +204,7 @@
  *   }
  * }}</pre>
  *
- * <h3>Implementation Notes</h3>
+ * <h2>Implementation Notes</h2>
  *
  * <p>This lock supports a maximum of 65535 recursive write locks
  * and 65535 read locks. Attempts to exceed these limits result in
--- a/src/java.base/share/classes/module-info.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/module-info.java	Fri May 03 14:59:32 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
@@ -214,6 +214,7 @@
         java.sql,
         java.sql.rowset,
         jdk.dynalink,
+        jdk.internal.vm.ci,
         jdk.scripting.nashorn,
         jdk.unsupported;
     exports jdk.internal.vm to
--- a/src/java.base/share/classes/sun/net/www/ParseUtil.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/net/www/ParseUtil.java	Fri May 03 14:59:32 2019 -0400
@@ -146,7 +146,7 @@
 
     /**
      * Appends the URL escape sequence for the specified char to the
-     * specified StringBuffer.
+     * specified character array.
      */
     private static int escape(char[] cc, char c, int index) {
         cc[index++] = '%';
@@ -336,7 +336,7 @@
                             String query,
                             String fragment)
     {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         if (scheme != null) {
             sb.append(scheme);
             sb.append(':');
@@ -348,7 +348,7 @@
         return sb.toString();
     }
 
-    private static void appendSchemeSpecificPart(StringBuffer sb,
+    private static void appendSchemeSpecificPart(StringBuilder sb,
                                           String opaquePart,
                                           String authority,
                                           String userInfo,
@@ -389,7 +389,7 @@
         }
     }
 
-    private static void appendAuthority(StringBuffer sb,
+    private static void appendAuthority(StringBuilder sb,
                                  String authority,
                                  String userInfo,
                                  String host,
@@ -437,7 +437,7 @@
         }
     }
 
-    private static void appendFragment(StringBuffer sb, String fragment) {
+    private static void appendFragment(StringBuilder sb, String fragment) {
         if (fragment != null) {
             sb.append('#');
             sb.append(quote(fragment, L_URIC, H_URIC));
@@ -449,14 +449,14 @@
     //
     private static String quote(String s, long lowMask, long highMask) {
         int n = s.length();
-        StringBuffer sb = null;
+        StringBuilder sb = null;
         boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0);
         for (int i = 0; i < s.length(); i++) {
             char c = s.charAt(i);
             if (c < '\u0080') {
                 if (!match(c, lowMask, highMask) && !isEscaped(s, i)) {
                     if (sb == null) {
-                        sb = new StringBuffer();
+                        sb = new StringBuilder();
                         sb.append(s, 0, i);
                     }
                     appendEscape(sb, (byte)c);
@@ -468,7 +468,7 @@
                        && (Character.isSpaceChar(c)
                            || Character.isISOControl(c))) {
                 if (sb == null) {
-                    sb = new StringBuffer();
+                    sb = new StringBuilder();
                     sb.append(s, 0, i);
                 }
                 appendEncoded(sb, c);
@@ -493,7 +493,7 @@
                && match(s.charAt(pos + 2), L_HEX, H_HEX);
     }
 
-    private static void appendEncoded(StringBuffer sb, char c) {
+    private static void appendEncoded(StringBuilder sb, char c) {
         ByteBuffer bb = null;
         try {
             bb = ThreadLocalCoders.encoderFor("UTF-8")
@@ -515,7 +515,7 @@
         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
     };
 
-    private static void appendEscape(StringBuffer sb, byte b) {
+    private static void appendEscape(StringBuilder sb, byte b) {
         sb.append('%');
         sb.append(hexDigits[(b >> 4) & 0x0f]);
         sb.append(hexDigits[(b >> 0) & 0x0f]);
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -53,6 +53,7 @@
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
 import sun.net.ResourceManager;
@@ -89,7 +90,8 @@
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
-    private final Object stateLock = new Object();
+    private final ReentrantLock stateLock = new ReentrantLock();
+    private final Condition stateCondition = stateLock.newCondition();
 
     // -- The following fields are protected by stateLock
 
@@ -179,8 +181,11 @@
                 : StandardProtocolFamily.INET;
         this.fd = fd;
         this.fdVal = IOUtil.fdVal(fd);
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             this.localAddress = Net.localAddress(fd);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -192,27 +197,36 @@
 
     @Override
     public DatagramSocket socket() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (socket == null)
                 socket = DatagramSocketAdaptor.create(this);
             return socket;
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketAddress getLocalAddress() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             // Perform security check before returning address
             return Net.getRevealedLocalAddress(localAddress);
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketAddress getRemoteAddress() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             return remoteAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -224,7 +238,8 @@
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             if (name == StandardSocketOptions.IP_TOS ||
@@ -264,6 +279,8 @@
             // remaining options don't need any special handling
             Net.setSocketOption(fd, Net.UNSPEC, name, value);
             return this;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -276,7 +293,8 @@
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             if (name == StandardSocketOptions.IP_TOS ||
@@ -315,6 +333,8 @@
 
             // no special handling
             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -362,7 +382,8 @@
             begin();
         }
         SocketAddress remote;
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             remote = remoteAddress;
             if ((remote == null) && mustBeConnected)
@@ -371,6 +392,8 @@
                 bindInternal(null);
             if (blocking)
                 readerThread = NativeThread.current();
+        } finally {
+            stateLock.unlock();
         }
         return remote;
     }
@@ -384,12 +407,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 readerThread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -414,21 +440,29 @@
                 SecurityManager sm = System.getSecurityManager();
                 if (connected || (sm == null)) {
                     // connected or no security manager
-                    do {
-                        n = receive(fd, dst, connected);
-                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
-                    if (n == IOStatus.UNAVAILABLE)
+                    n = receive(fd, dst, connected);
+                    if (blocking) {
+                        while (IOStatus.okayToRetry(n) && isOpen()) {
+                            park(Net.POLLIN);
+                            n = receive(fd, dst, connected);
+                        }
+                    } else if (n == IOStatus.UNAVAILABLE) {
                         return null;
+                    }
                 } else {
                     // Cannot receive into user's buffer when running with a
                     // security manager and not connected
                     bb = Util.getTemporaryDirectBuffer(dst.remaining());
                     for (;;) {
-                        do {
-                            n = receive(fd, bb, connected);
-                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
-                        if (n == IOStatus.UNAVAILABLE)
+                        n = receive(fd, bb, connected);
+                        if (blocking) {
+                            while (IOStatus.okayToRetry(n) && isOpen()) {
+                                park(Net.POLLIN);
+                                n = receive(fd, bb, connected);
+                            }
+                        } else if (n == IOStatus.UNAVAILABLE) {
                             return null;
+                        }
                         InetSocketAddress isa = (InetSocketAddress)sender;
                         try {
                             sm.checkAccept(isa.getAddress().getHostAddress(),
@@ -493,6 +527,7 @@
         return n;
     }
 
+    @Override
     public int send(ByteBuffer src, SocketAddress target)
         throws IOException
     {
@@ -510,9 +545,13 @@
                     if (!target.equals(remote)) {
                         throw new AlreadyConnectedException();
                     }
-                    do {
-                        n = IOUtil.write(fd, src, -1, nd);
-                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                    n = IOUtil.write(fd, src, -1, nd);
+                    if (blocking) {
+                        while (IOStatus.okayToRetry(n) && isOpen()) {
+                            park(Net.POLLOUT);
+                            n = IOUtil.write(fd, src, -1, nd);
+                        }
+                    }
                 } else {
                     // not connected
                     SecurityManager sm = System.getSecurityManager();
@@ -524,9 +563,13 @@
                             sm.checkConnect(ia.getHostAddress(), isa.getPort());
                         }
                     }
-                    do {
-                        n = send(fd, src, isa);
-                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                    n = send(fd, src, isa);
+                    if (blocking) {
+                        while (IOStatus.okayToRetry(n) && isOpen()) {
+                            park(Net.POLLOUT);
+                            n = send(fd, src, isa);
+                        }
+                    }
                 }
             } finally {
                 endWrite(blocking, n > 0);
@@ -602,10 +645,13 @@
             int n = 0;
             try {
                 beginRead(blocking, true);
-                do {
-                    n = IOUtil.read(fd, buf, -1, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
+                n = IOUtil.read(fd, buf, -1, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = IOUtil.read(fd, buf, -1, nd);
+                    }
+                }
             } finally {
                 endRead(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -628,10 +674,13 @@
             long n = 0;
             try {
                 beginRead(blocking, true);
-                do {
-                    n = IOUtil.read(fd, dsts, offset, length, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
+                n = IOUtil.read(fd, dsts, offset, length, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = IOUtil.read(fd, dsts, offset, length, nd);
+                    }
+                }
             } finally {
                 endRead(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -659,7 +708,8 @@
             begin();
         }
         SocketAddress remote;
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             remote = remoteAddress;
             if ((remote == null) && mustBeConnected)
@@ -668,6 +718,8 @@
                 bindInternal(null);
             if (blocking)
                 writerThread = NativeThread.current();
+        } finally {
+            stateLock.unlock();
         }
         return remote;
     }
@@ -681,12 +733,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 writerThread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -703,9 +758,13 @@
             int n = 0;
             try {
                 beginWrite(blocking, true);
-                do {
-                    n = IOUtil.write(fd, buf, -1, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.write(fd, buf, -1, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
+                        n = IOUtil.write(fd, buf, -1, nd);
+                    }
+                }
             } finally {
                 endWrite(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -728,9 +787,13 @@
             long n = 0;
             try {
                 beginWrite(blocking, true);
-                do {
-                    n = IOUtil.write(fd, srcs, offset, length, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.write(fd, srcs, offset, length, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
+                        n = IOUtil.write(fd, srcs, offset, length, nd);
+                    }
+                }
             } finally {
                 endWrite(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -747,9 +810,12 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
+                stateLock.lock();
+                try {
                     ensureOpen();
                     IOUtil.configureBlocking(fd, block);
+                } finally {
+                    stateLock.unlock();
                 }
             } finally {
                 writeLock.unlock();
@@ -760,14 +826,20 @@
     }
 
     InetSocketAddress localAddress() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return localAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
     InetSocketAddress remoteAddress() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return remoteAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -777,11 +849,14 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
+                stateLock.lock();
+                try {
                     ensureOpen();
                     if (localAddress != null)
                         throw new AlreadyBoundException();
                     bindInternal(local);
+                } finally {
+                    stateLock.unlock();
                 }
             } finally {
                 writeLock.unlock();
@@ -793,7 +868,7 @@
     }
 
     private void bindInternal(SocketAddress local) throws IOException {
-        assert Thread.holdsLock(stateLock) && (localAddress == null);
+        assert stateLock.isHeldByCurrentThread() && (localAddress == null);
 
         InetSocketAddress isa;
         if (local == null) {
@@ -816,8 +891,11 @@
 
     @Override
     public boolean isConnected() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return (state == ST_CONNECTED);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -839,7 +917,8 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
+                stateLock.lock();
+                try {
                     ensureOpen();
                     if (state == ST_CONNECTED)
                         throw new AlreadyConnectedException();
@@ -865,7 +944,7 @@
                     }
                     try {
                         ByteBuffer buf = ByteBuffer.allocate(100);
-                        while (receive(buf) != null) {
+                        while (receive(fd, buf, false) > 0) {
                             buf.clear();
                         }
                     } finally {
@@ -873,6 +952,9 @@
                             IOUtil.configureBlocking(fd, true);
                         }
                     }
+
+                } finally {
+                    stateLock.unlock();
                 }
             } finally {
                 writeLock.unlock();
@@ -889,7 +971,8 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
+                stateLock.lock();
+                try {
                     if (!isOpen() || (state != ST_CONNECTED))
                         return this;
 
@@ -903,6 +986,8 @@
 
                     // refresh local address
                     localAddress = Net.localAddress(fd);
+                } finally {
+                    stateLock.unlock();
                 }
             } finally {
                 writeLock.unlock();
@@ -950,7 +1035,8 @@
         if (sm != null)
             sm.checkMulticast(group);
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             // check the registry to see if we are already a member of the group
@@ -1005,6 +1091,8 @@
 
             registry.add(key);
             return key;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -1030,7 +1118,8 @@
     void drop(MembershipKeyImpl key) {
         assert key.channel() == this;
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (!key.isValid())
                 return;
 
@@ -1051,6 +1140,8 @@
 
             key.invalidate();
             registry.remove(key);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -1064,7 +1155,8 @@
         assert key.channel() == this;
         assert key.sourceAddress() == null;
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (!key.isValid())
                 throw new IllegalStateException("key is no longer valid");
             if (source.isAnyLocalAddress())
@@ -1090,6 +1182,8 @@
                 // ancient kernel
                 throw new UnsupportedOperationException();
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -1100,7 +1194,8 @@
         assert key.channel() == this;
         assert key.sourceAddress() == null;
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (!key.isValid())
                 throw new IllegalStateException("key is no longer valid");
 
@@ -1120,6 +1215,8 @@
                 // should not happen
                 throw new AssertionError(ioe);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -1144,7 +1241,8 @@
         boolean interrupted = false;
 
         // set state to ST_CLOSING and invalid membership keys
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state < ST_CLOSING;
             blocking = isBlocking();
             state = ST_CLOSING;
@@ -1152,11 +1250,14 @@
             // if member of any multicast groups then invalidate the keys
             if (registry != null)
                 registry.invalidateAll();
+        } finally {
+            stateLock.unlock();
         }
 
         // wait for any outstanding I/O operations to complete
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 assert state == ST_CLOSING;
                 long reader = readerThread;
                 long writer = writerThread;
@@ -1171,12 +1272,14 @@
                     // wait for blocking I/O operations to end
                     while (readerThread != 0 || writerThread != 0) {
                         try {
-                            stateLock.wait();
+                            stateCondition.await();
                         } catch (InterruptedException e) {
                             interrupted = true;
                         }
                     }
                 }
+            } finally {
+                stateLock.unlock();
             }
         } else {
             // non-blocking mode: wait for read/write to complete
@@ -1190,9 +1293,12 @@
         }
 
         // set state to ST_KILLPENDING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state == ST_CLOSING;
             state = ST_KILLPENDING;
+        } finally {
+            stateLock.unlock();
         }
 
         // close socket if not registered with Selector
@@ -1206,7 +1312,8 @@
 
     @Override
     public void kill() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (state == ST_KILLPENDING) {
                 state = ST_KILLED;
                 try {
@@ -1216,6 +1323,8 @@
                     ResourceManager.afterUdpClose();
                 }
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
--- a/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java	Fri May 03 14:59:32 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
@@ -42,6 +42,7 @@
 import java.nio.channels.DatagramChannel;
 import java.nio.channels.IllegalBlockingModeException;
 import java.util.Objects;
+import java.util.Set;
 
 
 // Make a datagram-socket channel look like a datagram socket.
@@ -51,7 +52,7 @@
 // class.
 //
 
-public class DatagramSocketAdaptor
+class DatagramSocketAdaptor
     extends DatagramSocket
 {
     // The channel being adapted
@@ -61,7 +62,7 @@
     private volatile int timeout;
 
     // ## super will create a useless impl
-    private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
+    private DatagramSocketAdaptor(DatagramChannelImpl dc) {
         // Invoke the DatagramSocketAdaptor(SocketAddress) constructor,
         // passing a dummy DatagramSocketImpl object to avoid any native
         // resource allocation in super class and invoking our bind method
@@ -70,12 +71,8 @@
         this.dc = dc;
     }
 
-    public static DatagramSocket create(DatagramChannelImpl dc) {
-        try {
-            return new DatagramSocketAdaptor(dc);
-        } catch (IOException x) {
-            throw new Error(x);
-        }
+    static DatagramSocket create(DatagramChannelImpl dc) {
+        return new DatagramSocketAdaptor(dc);
     }
 
     private void connectInternal(SocketAddress remote)
@@ -96,6 +93,7 @@
         }
     }
 
+    @Override
     public void bind(SocketAddress local) throws SocketException {
         try {
             if (local == null)
@@ -106,6 +104,7 @@
         }
     }
 
+    @Override
     public void connect(InetAddress address, int port) {
         try {
             connectInternal(new InetSocketAddress(address, port));
@@ -114,11 +113,13 @@
         }
     }
 
+    @Override
     public void connect(SocketAddress remote) throws SocketException {
         Objects.requireNonNull(remote, "Address can't be null");
         connectInternal(remote);
     }
 
+    @Override
     public void disconnect() {
         try {
             dc.disconnect();
@@ -127,24 +128,39 @@
         }
     }
 
+    @Override
     public boolean isBound() {
         return dc.localAddress() != null;
     }
 
+    @Override
     public boolean isConnected() {
         return dc.remoteAddress() != null;
     }
 
+    @Override
     public InetAddress getInetAddress() {
         InetSocketAddress remote = dc.remoteAddress();
         return (remote != null) ? remote.getAddress() : null;
     }
 
+    @Override
     public int getPort() {
         InetSocketAddress remote = dc.remoteAddress();
         return (remote != null) ? remote.getPort() : -1;
     }
 
+    @Override
+    public SocketAddress getRemoteSocketAddress() {
+        return dc.remoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalSocketAddress() {
+        return dc.localAddress();
+    }
+
+    @Override
     public void send(DatagramPacket p) throws IOException {
         synchronized (dc.blockingLock()) {
             if (!dc.isBlocking())
@@ -198,6 +214,7 @@
         }
     }
 
+    @Override
     public void receive(DatagramPacket p) throws IOException {
         synchronized (dc.blockingLock()) {
             if (!dc.isBlocking())
@@ -217,6 +234,7 @@
         }
     }
 
+    @Override
     public InetAddress getLocalAddress() {
         if (isClosed())
             return null;
@@ -235,6 +253,7 @@
         return result;
     }
 
+    @Override
     public int getLocalPort() {
         if (isClosed())
             return -1;
@@ -248,11 +267,19 @@
         return 0;
     }
 
+    @Override
     public void setSoTimeout(int timeout) throws SocketException {
+        if (!dc.isOpen())
+            throw new SocketException("Socket is closed");
+        if (timeout < 0)
+            throw new IllegalArgumentException("timeout < 0");
         this.timeout = timeout;
     }
 
+    @Override
     public int getSoTimeout() throws SocketException {
+        if (!dc.isOpen())
+            throw new SocketException("Socket is closed");
         return timeout;
     }
 
@@ -294,51 +321,62 @@
         }
     }
 
+    @Override
     public void setSendBufferSize(int size) throws SocketException {
         if (size <= 0)
             throw new IllegalArgumentException("Invalid send size");
         setIntOption(StandardSocketOptions.SO_SNDBUF, size);
     }
 
+    @Override
     public int getSendBufferSize() throws SocketException {
         return getIntOption(StandardSocketOptions.SO_SNDBUF);
     }
 
+    @Override
     public void setReceiveBufferSize(int size) throws SocketException {
         if (size <= 0)
             throw new IllegalArgumentException("Invalid receive size");
         setIntOption(StandardSocketOptions.SO_RCVBUF, size);
     }
 
+    @Override
     public int getReceiveBufferSize() throws SocketException {
         return getIntOption(StandardSocketOptions.SO_RCVBUF);
     }
 
+    @Override
     public void setReuseAddress(boolean on) throws SocketException {
         setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);
     }
 
+    @Override
     public boolean getReuseAddress() throws SocketException {
         return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);
 
     }
 
+    @Override
     public void setBroadcast(boolean on) throws SocketException {
         setBooleanOption(StandardSocketOptions.SO_BROADCAST, on);
     }
 
+    @Override
     public boolean getBroadcast() throws SocketException {
         return getBooleanOption(StandardSocketOptions.SO_BROADCAST);
     }
 
+    @Override
     public void setTrafficClass(int tc) throws SocketException {
         setIntOption(StandardSocketOptions.IP_TOS, tc);
     }
 
+    @Override
     public int getTrafficClass() throws SocketException {
         return getIntOption(StandardSocketOptions.IP_TOS);
     }
 
+    @Override
     public void close() {
         try {
             dc.close();
@@ -347,14 +385,32 @@
         }
     }
 
+    @Override
     public boolean isClosed() {
         return !dc.isOpen();
     }
 
+    @Override
     public DatagramChannel getChannel() {
         return dc;
     }
 
+    @Override
+    public <T> DatagramSocket setOption(SocketOption<T> name, T value) throws IOException {
+        dc.setOption(name, value);
+        return this;
+    }
+
+    @Override
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return dc.getOption(name);
+    }
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
+        return dc.supportedOptions();
+    }
+
    /*
     * A dummy implementation of DatagramSocketImpl that can be passed to the
     * DatagramSocket constructor so that no native resources are allocated in
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/DummySocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,153 @@
+/*
+ * 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.nio.ch;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.SocketImpl;
+import java.net.SocketOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+
+/**
+ * Dummy SocketImpl for use by the socket adaptors. All methods are overridden
+ * to throw an error.
+ */
+
+class DummySocketImpl extends SocketImpl {
+    private static final PrivilegedAction<SocketImpl> NEW = DummySocketImpl::new;
+
+    private DummySocketImpl() { }
+
+    static SocketImpl create() {
+        return AccessController.doPrivileged(NEW);
+    }
+
+    private static <T> T shouldNotGetHere() {
+        throw new InternalError("Should not get here");
+    }
+
+    @Override
+    protected void create(boolean stream) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void connect(SocketAddress remote, int millis) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void connect(String host, int port) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void connect(InetAddress address, int port) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void bind(InetAddress host, int port) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void listen(int backlog) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void accept(SocketImpl si) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected InputStream getInputStream() {
+        return shouldNotGetHere();
+    }
+    @Override
+    protected OutputStream getOutputStream() {
+        return shouldNotGetHere();
+    }
+    @Override
+    protected int available() {
+        return shouldNotGetHere();
+    }
+
+    @Override
+    protected void close() {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected Set<SocketOption<?>> supportedOptions() {
+        return shouldNotGetHere();
+    }
+
+    @Override
+    protected <T> void setOption(SocketOption<T> opt, T value) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected <T> T getOption(SocketOption<T> opt) {
+        return shouldNotGetHere();
+    }
+
+    @Override
+    public void setOption(int opt, Object value) {
+        shouldNotGetHere();
+    }
+
+    @Override
+    public Object getOption(int opt) {
+        return shouldNotGetHere();
+    }
+
+    @Override
+    protected void shutdownInput() {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected void shutdownOutput() {
+        shouldNotGetHere();
+    }
+
+    @Override
+    protected boolean supportsUrgentData() {
+        return shouldNotGetHere();
+    }
+
+    @Override
+    protected void sendUrgentData(int data) {
+        shouldNotGetHere();
+    }
+}
--- a/src/java.base/share/classes/sun/nio/ch/SelChImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/SelChImpl.java	Fri May 03 14:59:32 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
@@ -29,6 +29,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
 /**
  * An interface that allows translation (and more!).
  *
@@ -68,4 +70,40 @@
 
     void kill() throws IOException;
 
+    /**
+     * Disables the current thread for scheduling purposes until this
+     * channel is ready for I/O, or asynchronously closed, for up to the
+     * specified waiting time.
+     *
+     * <p> This method does <em>not</em> report which of these caused the
+     * method to return. Callers should re-check the conditions which caused
+     * the thread to park.
+     *
+     * @param event the event to poll
+     * @param nanos the timeout to wait; {@code <= 0} to wait indefinitely
+     */
+    default void park(int event, long nanos) throws IOException {
+        long millis;
+        if (nanos <= 0) {
+            millis = -1;
+        } else {
+            millis = NANOSECONDS.toMillis(nanos);
+        }
+        Net.poll(getFD(), event, millis);
+    }
+
+    /**
+     * Disables the current thread for scheduling purposes until this
+     * channel is ready for I/O, or asynchronously closed.
+     *
+     * <p> This method does <em>not</em> report which of these caused the
+     * method to return. Callers should re-check the conditions which caused
+     * the thread to park.
+     *
+     * @param event the event to poll
+     */
+    default void park(int event) throws IOException {
+        park(event, 0L);
+    }
+
 }
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Fri May 03 14:59:32 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
@@ -32,12 +32,14 @@
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.net.SocketException;
-import java.net.SocketTimeoutException;
+import java.net.SocketOption;
 import java.net.StandardSocketOptions;
 import java.nio.channels.IllegalBlockingModeException;
-import java.nio.channels.NotYetBoundException;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
+import java.util.Set;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 
 // Make a server-socket channel look like a server socket.
@@ -56,23 +58,21 @@
     // Timeout "option" value for accepts
     private volatile int timeout;
 
-    public static ServerSocket create(ServerSocketChannelImpl ssc) {
-        try {
-            return new ServerSocketAdaptor(ssc);
-        } catch (IOException x) {
-            throw new Error(x);
-        }
+    static ServerSocket create(ServerSocketChannelImpl ssc) {
+        return new ServerSocketAdaptor(ssc);
     }
 
-    // ## super will create a useless impl
-    private ServerSocketAdaptor(ServerSocketChannelImpl ssc) throws IOException {
+    private ServerSocketAdaptor(ServerSocketChannelImpl ssc) {
+        super(DummySocketImpl.create());
         this.ssc = ssc;
     }
 
+    @Override
     public void bind(SocketAddress local) throws IOException {
         bind(local, 50);
     }
 
+    @Override
     public void bind(SocketAddress local, int backlog) throws IOException {
         if (local == null)
             local = new InetSocketAddress(0);
@@ -83,6 +83,7 @@
         }
     }
 
+    @Override
     public InetAddress getInetAddress() {
         InetSocketAddress local = ssc.localAddress();
         if (local == null) {
@@ -92,6 +93,7 @@
         }
     }
 
+    @Override
     public int getLocalPort() {
         InetSocketAddress local = ssc.localAddress();
         if (local == null) {
@@ -101,65 +103,65 @@
         }
     }
 
+    @Override
     public Socket accept() throws IOException {
-        synchronized (ssc.blockingLock()) {
-            try {
-                if (!ssc.isBound())
-                    throw new NotYetBoundException();
-
-                long to = this.timeout;
-                if (to == 0) {
-                    // for compatibility reasons: accept connection if available
-                    // when configured non-blocking
-                    SocketChannel sc = ssc.accept();
-                    if (sc == null && !ssc.isBlocking())
-                        throw new IllegalBlockingModeException();
-                    return sc.socket();
+        SocketChannel sc = null;
+        try {
+            int timeout = this.timeout;
+            if (timeout > 0) {
+                long nanos = MILLISECONDS.toNanos(timeout);
+                sc = ssc.blockingAccept(nanos);
+            } else {
+                // accept connection if possible when non-blocking (to preserve
+                // long standing behavior)
+                sc = ssc.accept();
+                if (sc == null) {
+                    throw new IllegalBlockingModeException();
                 }
-
-                if (!ssc.isBlocking())
-                    throw new IllegalBlockingModeException();
-                for (;;) {
-                    long st = System.currentTimeMillis();
-                    if (ssc.pollAccept(to))
-                        return ssc.accept().socket();
-                    to -= System.currentTimeMillis() - st;
-                    if (to <= 0)
-                        throw new SocketTimeoutException();
-                }
-
-            } catch (Exception x) {
-                Net.translateException(x);
-                assert false;
-                return null;            // Never happens
             }
+        } catch (Exception e) {
+            Net.translateException(e);
         }
+        return sc.socket();
     }
 
+    @Override
     public void close() throws IOException {
         ssc.close();
     }
 
+    @Override
     public ServerSocketChannel getChannel() {
         return ssc;
     }
 
+    @Override
     public boolean isBound() {
         return ssc.isBound();
     }
 
+    @Override
     public boolean isClosed() {
         return !ssc.isOpen();
     }
 
+    @Override
     public void setSoTimeout(int timeout) throws SocketException {
+        if (!ssc.isOpen())
+            throw new SocketException("Socket is closed");
+        if (timeout < 0)
+            throw new IllegalArgumentException("timeout < 0");
         this.timeout = timeout;
     }
 
+    @Override
     public int getSoTimeout() throws SocketException {
+        if (!ssc.isOpen())
+            throw new SocketException("Socket is closed");
         return timeout;
     }
 
+    @Override
     public void setReuseAddress(boolean on) throws SocketException {
         try {
             ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
@@ -168,6 +170,7 @@
         }
     }
 
+    @Override
     public boolean getReuseAddress() throws SocketException {
         try {
             return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue();
@@ -177,6 +180,7 @@
         }
     }
 
+    @Override
     public String toString() {
         if (!isBound())
             return "ServerSocket[unbound]";
@@ -184,6 +188,7 @@
                ",localport=" + getLocalPort()  + "]";
     }
 
+    @Override
     public void setReceiveBufferSize(int size) throws SocketException {
         // size 0 valid for ServerSocketChannel, invalid for ServerSocket
         if (size <= 0)
@@ -195,6 +200,7 @@
         }
     }
 
+    @Override
     public int getReceiveBufferSize() throws SocketException {
         try {
             return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
@@ -203,4 +209,20 @@
             return -1;          // Never happens
         }
     }
+
+    @Override
+    public <T> ServerSocket setOption(SocketOption<T> name, T value) throws IOException {
+        ssc.setOption(name, value);
+        return this;
+    }
+
+    @Override
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return ssc.getOption(name);
+    }
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
+        return ssc.supportedOptions();
+    }
 }
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -31,10 +31,12 @@
 import java.net.ServerSocket;
 import java.net.SocketAddress;
 import java.net.SocketOption;
+import java.net.SocketTimeoutException;
 import java.net.StandardSocketOptions;
 import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.AsynchronousCloseException;
 import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
 import java.nio.channels.NotYetBoundException;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.ServerSocketChannel;
@@ -44,6 +46,7 @@
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
 import sun.net.NetHooks;
@@ -69,7 +72,8 @@
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
-    private final Object stateLock = new Object();
+    private final ReentrantLock stateLock = new ReentrantLock();
+    private final Condition stateCondition = stateLock.newCondition();
 
     // -- The following fields are protected by stateLock
 
@@ -95,7 +99,7 @@
     // -- End of fields protected by stateLock
 
 
-    ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
+    ServerSocketChannelImpl(SelectorProvider sp) {
         super(sp);
         this.fd = Net.serverSocket(true);
         this.fdVal = IOUtil.fdVal(fd);
@@ -108,8 +112,11 @@
         this.fd =  fd;
         this.fdVal = IOUtil.fdVal(fd);
         if (bound) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 localAddress = Net.localAddress(fd);
+            } finally {
+                stateLock.unlock();
             }
         }
     }
@@ -122,20 +129,26 @@
 
     @Override
     public ServerSocket socket() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (socket == null)
                 socket = ServerSocketAdaptor.create(this);
             return socket;
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketAddress getLocalAddress() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             return (localAddress == null)
                     ? null
                     : Net.getRevealedLocalAddress(localAddress);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -146,7 +159,8 @@
         Objects.requireNonNull(name);
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
@@ -157,6 +171,8 @@
                 Net.setSocketOption(fd, Net.UNSPEC, name, value);
             }
             return this;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -169,7 +185,8 @@
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
                 // SO_REUSEADDR emulated when using exclusive bind
@@ -177,6 +194,8 @@
             }
             // no options that require special handling
             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -202,7 +221,8 @@
 
     @Override
     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (localAddress != null)
                 throw new AlreadyBoundException();
@@ -216,6 +236,8 @@
             Net.bind(fd, isa.getAddress(), isa.getPort());
             Net.listen(fd, backlog < 1 ? 50 : backlog);
             localAddress = Net.localAddress(fd);
+        } finally {
+            stateLock.unlock();
         }
         return this;
     }
@@ -229,12 +251,15 @@
     private void begin(boolean blocking) throws ClosedChannelException {
         if (blocking)
             begin();  // set blocker to close channel if interrupted
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (localAddress == null)
                 throw new NotYetBoundException();
             if (blocking)
                 thread = NativeThread.current();
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -248,12 +273,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 thread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             end(completed);
         }
@@ -270,22 +298,82 @@
             boolean blocking = isBlocking();
             try {
                 begin(blocking);
-                do {
-                    n = Net.accept(this.fd, newfd, isaa);
-                } while (n == IOStatus.INTERRUPTED && isOpen());
+                n = Net.accept(this.fd, newfd, isaa);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = Net.accept(this.fd, newfd, isaa);
+                    }
+                }
             } finally {
                 end(blocking, n > 0);
                 assert IOStatus.check(n);
             }
-
         } finally {
             acceptLock.unlock();
         }
 
-        if (n < 1)
+        if (n > 0) {
+            return finishAccept(newfd, isaa[0]);
+        } else {
             return null;
+        }
+    }
 
-        InetSocketAddress isa = isaa[0];
+    /**
+     * Accepts a new connection with a given timeout. This method requires the
+     * channel to be configured in blocking mode.
+     *
+     * @apiNote This method is for use by the socket adaptor.
+     *
+     * @param nanos the timeout, in nanoseconds
+     * @throws IllegalBlockingModeException if the channel is configured non-blocking
+     * @throws SocketTimeoutException if the timeout expires
+     */
+    SocketChannel blockingAccept(long nanos) throws IOException {
+        int n = 0;
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+
+        acceptLock.lock();
+        try {
+            // check that channel is configured blocking
+            if (!isBlocking())
+                throw new IllegalBlockingModeException();
+
+            try {
+                begin(true);
+                // change socket to non-blocking
+                lockedConfigureBlocking(false);
+                try {
+                    long startNanos = System.nanoTime();
+                    n = Net.accept(fd, newfd, isaa);
+                    while (n == IOStatus.UNAVAILABLE && isOpen()) {
+                        long remainingNanos = nanos - (System.nanoTime() - startNanos);
+                        if (remainingNanos <= 0) {
+                            throw new SocketTimeoutException("Accept timed out");
+                        }
+                        park(Net.POLLIN, remainingNanos);
+                        n = Net.accept(fd, newfd, isaa);
+                    }
+                } finally {
+                    // restore socket to blocking mode
+                    lockedConfigureBlocking(true);
+                }
+            } finally {
+                end(true, n > 0);
+            }
+        } finally {
+            acceptLock.unlock();
+        }
+
+        assert n > 0;
+        return finishAccept(newfd, isaa[0]);
+    }
+
+    private SocketChannel finishAccept(FileDescriptor newfd, InetSocketAddress isa)
+        throws IOException
+    {
         try {
             // newly accepted socket is initially in blocking mode
             IOUtil.configureBlocking(newfd, true);
@@ -306,16 +394,27 @@
     protected void implConfigureBlocking(boolean block) throws IOException {
         acceptLock.lock();
         try {
-            synchronized (stateLock) {
-                ensureOpen();
-                IOUtil.configureBlocking(fd, block);
-            }
+            lockedConfigureBlocking(block);
         } finally {
             acceptLock.unlock();
         }
     }
 
     /**
+     * Adjust the blocking mode while holding acceptLock.
+     */
+    private void lockedConfigureBlocking(boolean block) throws IOException {
+        assert acceptLock.isHeldByCurrentThread();
+        stateLock.lock();
+        try {
+            ensureOpen();
+            IOUtil.configureBlocking(fd, block);
+        } finally {
+            stateLock.unlock();
+        }
+    }
+
+    /**
      * Invoked by implCloseChannel to close the channel.
      *
      * This method waits for outstanding I/O operations to complete. When in
@@ -336,15 +435,19 @@
         boolean blocking;
 
         // set state to ST_CLOSING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state < ST_CLOSING;
             state = ST_CLOSING;
             blocking = isBlocking();
+        } finally {
+            stateLock.unlock();
         }
 
         // wait for any outstanding accept to complete
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 assert state == ST_CLOSING;
                 long th = thread;
                 if (th != 0) {
@@ -354,12 +457,14 @@
                     // wait for accept operation to end
                     while (thread != 0) {
                         try {
-                            stateLock.wait();
+                            stateCondition.await();
                         } catch (InterruptedException e) {
                             interrupted = true;
                         }
                     }
                 }
+            } finally {
+                stateLock.unlock();
             }
         } else {
             // non-blocking mode: wait for accept to complete
@@ -368,9 +473,12 @@
         }
 
         // set state to ST_KILLPENDING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state == ST_CLOSING;
             state = ST_KILLPENDING;
+        } finally {
+            stateLock.unlock();
         }
 
         // close socket if not registered with Selector
@@ -384,11 +492,14 @@
 
     @Override
     public void kill() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (state == ST_KILLPENDING) {
                 state = ST_KILLED;
                 nd.close(fd);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -396,8 +507,11 @@
      * Returns true if channel's socket is bound
      */
     boolean isBound() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return localAddress != null;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -405,30 +519,11 @@
      * Returns the local address, or null if not bound
      */
     InetSocketAddress localAddress() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return localAddress;
-        }
-    }
-
-    /**
-     * Poll this channel's socket for a new connection up to the given timeout.
-     * @return {@code true} if there is a connection to accept
-     */
-    boolean pollAccept(long timeout) throws IOException {
-        assert Thread.holdsLock(blockingLock()) && isBlocking();
-        acceptLock.lock();
-        try {
-            boolean polled = false;
-            try {
-                begin(true);
-                int events = Net.poll(fd, Net.POLLIN, timeout);
-                polled = (events != 0);
-            } finally {
-                end(true, polled);
-            }
-            return polled;
         } finally {
-            acceptLock.unlock();
+            stateLock.unlock();
         }
     }
 
@@ -494,13 +589,16 @@
         if (!isOpen()) {
             sb.append("closed");
         } else {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 InetSocketAddress addr = localAddress;
                 if (addr == null) {
                     sb.append("unbound");
                 } else {
                     sb.append(Net.getRevealedLocalAddressAsString(addr));
                 }
+            } finally {
+                stateLock.unlock();
             }
         }
         sb.append(']');
--- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java	Fri May 03 14:59:32 2019 -0400
@@ -33,18 +33,12 @@
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.net.SocketException;
-import java.net.SocketImpl;
 import java.net.SocketOption;
-import java.net.SocketTimeoutException;
 import java.net.StandardSocketOptions;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.IllegalBlockingModeException;
 import java.nio.channels.SocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
-import static java.util.concurrent.TimeUnit.*;
+import java.util.Set;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 // Make a socket channel look like a socket.
 //
@@ -62,11 +56,11 @@
     private volatile int timeout;
 
     private SocketAdaptor(SocketChannelImpl sc) throws SocketException {
-        super((SocketImpl) null);
+        super(DummySocketImpl.create());
         this.sc = sc;
     }
 
-    public static Socket create(SocketChannelImpl sc) {
+    static Socket create(SocketChannelImpl sc) {
         try {
             return new SocketAdaptor(sc);
         } catch (SocketException e) {
@@ -74,70 +68,30 @@
         }
     }
 
-    public SocketChannel getChannel() {
-        return sc;
-    }
-
-    // Override this method just to protect against changes in the superclass
-    //
+    @Override
     public void connect(SocketAddress remote) throws IOException {
         connect(remote, 0);
     }
 
+    @Override
     public void connect(SocketAddress remote, int timeout) throws IOException {
         if (remote == null)
             throw new IllegalArgumentException("connect: The address can't be null");
         if (timeout < 0)
             throw new IllegalArgumentException("connect: timeout can't be negative");
-
-        synchronized (sc.blockingLock()) {
-            if (!sc.isBlocking())
-                throw new IllegalBlockingModeException();
-
-            try {
-                // no timeout
-                if (timeout == 0) {
-                    sc.connect(remote);
-                    return;
-                }
-
-                // timed connect
-                sc.configureBlocking(false);
-                try {
-                    if (sc.connect(remote))
-                        return;
-                } finally {
-                    try {
-                        sc.configureBlocking(true);
-                    } catch (ClosedChannelException e) { }
-                }
-
-                long timeoutNanos = NANOSECONDS.convert(timeout, MILLISECONDS);
-                long to = timeout;
-                for (;;) {
-                    long startTime = System.nanoTime();
-                    if (sc.pollConnected(to)) {
-                        boolean connected = sc.finishConnect();
-                        assert connected;
-                        break;
-                    }
-                    timeoutNanos -= System.nanoTime() - startTime;
-                    if (timeoutNanos <= 0) {
-                        try {
-                            sc.close();
-                        } catch (IOException x) { }
-                        throw new SocketTimeoutException();
-                    }
-                    to = MILLISECONDS.convert(timeoutNanos, NANOSECONDS);
-                }
-
-            } catch (Exception x) {
-                Net.translateException(x, true);
+        try {
+            if (timeout > 0) {
+                long nanos = MILLISECONDS.toNanos(timeout);
+                sc.blockingConnect(remote, nanos);
+            } else {
+                sc.blockingConnect(remote, Long.MAX_VALUE);
             }
+        } catch (Exception e) {
+            Net.translateException(e, true);
         }
-
     }
 
+    @Override
     public void bind(SocketAddress local) throws IOException {
         try {
             sc.bind(local);
@@ -146,6 +100,7 @@
         }
     }
 
+    @Override
     public InetAddress getInetAddress() {
         InetSocketAddress remote = sc.remoteAddress();
         if (remote == null) {
@@ -155,6 +110,7 @@
         }
     }
 
+    @Override
     public InetAddress getLocalAddress() {
         if (sc.isOpen()) {
             InetSocketAddress local = sc.localAddress();
@@ -165,6 +121,7 @@
         return new InetSocketAddress(0).getAddress();
     }
 
+    @Override
     public int getPort() {
         InetSocketAddress remote = sc.remoteAddress();
         if (remote == null) {
@@ -174,6 +131,7 @@
         }
     }
 
+    @Override
     public int getLocalPort() {
         InetSocketAddress local = sc.localAddress();
         if (local == null) {
@@ -183,48 +141,27 @@
         }
     }
 
-    private class SocketInputStream
-        extends ChannelInputStream
-    {
-        private SocketInputStream() {
-            super(sc);
-        }
-
-        protected int read(ByteBuffer bb)
-            throws IOException
-        {
-            synchronized (sc.blockingLock()) {
-                if (!sc.isBlocking())
-                    throw new IllegalBlockingModeException();
-
-                // no timeout
-                long to = SocketAdaptor.this.timeout;
-                if (to == 0)
-                    return sc.read(bb);
+    @Override
+    public SocketAddress getRemoteSocketAddress() {
+        return sc.remoteAddress();
+    }
 
-                // timed read
-                long timeoutNanos = NANOSECONDS.convert(to, MILLISECONDS);
-                for (;;) {
-                    long startTime = System.nanoTime();
-                    if (sc.pollRead(to)) {
-                        return sc.read(bb);
-                    }
-                    timeoutNanos -= System.nanoTime() - startTime;
-                    if (timeoutNanos <= 0)
-                        throw new SocketTimeoutException();
-                    to = MILLISECONDS.convert(timeoutNanos, NANOSECONDS);
-                }
-            }
-        }
-
-        @Override
-        public int available() throws IOException {
-            return sc.available();
+    @Override
+    public SocketAddress getLocalSocketAddress() {
+        InetSocketAddress local = sc.localAddress();
+        if (local != null) {
+            return Net.getRevealedLocalAddress(local);
+        } else {
+            return null;
         }
     }
 
-    private InputStream socketInputStream = null;
+    @Override
+    public SocketChannel getChannel() {
+        return sc;
+    }
 
+    @Override
     public InputStream getInputStream() throws IOException {
         if (!sc.isOpen())
             throw new SocketException("Socket is closed");
@@ -232,21 +169,35 @@
             throw new SocketException("Socket is not connected");
         if (!sc.isInputOpen())
             throw new SocketException("Socket input is shutdown");
-        if (socketInputStream == null) {
-            try {
-                socketInputStream = AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<InputStream>() {
-                        public InputStream run() throws IOException {
-                            return new SocketInputStream();
-                        }
-                    });
-            } catch (java.security.PrivilegedActionException e) {
-                throw (IOException)e.getException();
+        return new InputStream() {
+            @Override
+            public int read() throws IOException {
+                byte[] a = new byte[1];
+                int n = read(a, 0, 1);
+                return (n > 0) ? (a[0] & 0xff) : -1;
             }
-        }
-        return socketInputStream;
+            @Override
+            public int read(byte[] b, int off, int len) throws IOException {
+                int timeout = SocketAdaptor.this.timeout;
+                if (timeout > 0) {
+                    long nanos = MILLISECONDS.toNanos(timeout);
+                    return sc.blockingRead(b, off, len, nanos);
+                } else {
+                    return sc.blockingRead(b, off, len, 0);
+                }
+            }
+            @Override
+            public int available() throws IOException {
+                return sc.available();
+            }
+            @Override
+            public void close() throws IOException {
+                sc.close();
+            }
+        };
     }
 
+    @Override
     public OutputStream getOutputStream() throws IOException {
         if (!sc.isOpen())
             throw new SocketException("Socket is closed");
@@ -254,18 +205,21 @@
             throw new SocketException("Socket is not connected");
         if (!sc.isOutputOpen())
             throw new SocketException("Socket output is shutdown");
-        OutputStream os = null;
-        try {
-            os = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<OutputStream>() {
-                    public OutputStream run() throws IOException {
-                        return Channels.newOutputStream(sc);
-                    }
-                });
-        } catch (java.security.PrivilegedActionException e) {
-            throw (IOException)e.getException();
-        }
-        return os;
+        return new OutputStream() {
+            @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 {
+                sc.blockingWriteFully(b, off, len);
+            }
+            @Override
+            public void close() throws IOException {
+                sc.close();
+            }
+        };
     }
 
     private void setBooleanOption(SocketOption<Boolean> name, boolean value)
@@ -306,48 +260,62 @@
         }
     }
 
+    @Override
     public void setTcpNoDelay(boolean on) throws SocketException {
         setBooleanOption(StandardSocketOptions.TCP_NODELAY, on);
     }
 
+    @Override
     public boolean getTcpNoDelay() throws SocketException {
         return getBooleanOption(StandardSocketOptions.TCP_NODELAY);
     }
 
+    @Override
     public void setSoLinger(boolean on, int linger) throws SocketException {
         if (!on)
             linger = -1;
         setIntOption(StandardSocketOptions.SO_LINGER, linger);
     }
 
+    @Override
     public int getSoLinger() throws SocketException {
         return getIntOption(StandardSocketOptions.SO_LINGER);
     }
 
+    @Override
     public void sendUrgentData(int data) throws IOException {
         int n = sc.sendOutOfBandData((byte) data);
         if (n == 0)
             throw new IOException("Socket buffer full");
     }
 
+    @Override
     public void setOOBInline(boolean on) throws SocketException {
         setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on);
     }
 
+    @Override
     public boolean getOOBInline() throws SocketException {
         return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE);
     }
 
+    @Override
     public void setSoTimeout(int timeout) throws SocketException {
+        if (!sc.isOpen())
+            throw new SocketException("Socket is closed");
         if (timeout < 0)
-            throw new IllegalArgumentException("timeout can't be negative");
+            throw new IllegalArgumentException("timeout < 0");
         this.timeout = timeout;
     }
 
+    @Override
     public int getSoTimeout() throws SocketException {
+        if (!sc.isOpen())
+            throw new SocketException("Socket is closed");
         return timeout;
     }
 
+    @Override
     public void setSendBufferSize(int size) throws SocketException {
         // size 0 valid for SocketChannel, invalid for Socket
         if (size <= 0)
@@ -355,10 +323,12 @@
         setIntOption(StandardSocketOptions.SO_SNDBUF, size);
     }
 
+    @Override
     public int getSendBufferSize() throws SocketException {
         return getIntOption(StandardSocketOptions.SO_SNDBUF);
     }
 
+    @Override
     public void setReceiveBufferSize(int size) throws SocketException {
         // size 0 valid for SocketChannel, invalid for Socket
         if (size <= 0)
@@ -366,38 +336,47 @@
         setIntOption(StandardSocketOptions.SO_RCVBUF, size);
     }
 
+    @Override
     public int getReceiveBufferSize() throws SocketException {
         return getIntOption(StandardSocketOptions.SO_RCVBUF);
     }
 
+    @Override
     public void setKeepAlive(boolean on) throws SocketException {
         setBooleanOption(StandardSocketOptions.SO_KEEPALIVE, on);
     }
 
+    @Override
     public boolean getKeepAlive() throws SocketException {
         return getBooleanOption(StandardSocketOptions.SO_KEEPALIVE);
     }
 
+    @Override
     public void setTrafficClass(int tc) throws SocketException {
         setIntOption(StandardSocketOptions.IP_TOS, tc);
     }
 
+    @Override
     public int getTrafficClass() throws SocketException {
         return getIntOption(StandardSocketOptions.IP_TOS);
     }
 
+    @Override
     public void setReuseAddress(boolean on) throws SocketException {
         setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);
     }
 
+    @Override
     public boolean getReuseAddress() throws SocketException {
         return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);
     }
 
+    @Override
     public void close() throws IOException {
         sc.close();
     }
 
+    @Override
     public void shutdownInput() throws IOException {
         try {
             sc.shutdownInput();
@@ -406,6 +385,7 @@
         }
     }
 
+    @Override
     public void shutdownOutput() throws IOException {
         try {
             sc.shutdownOutput();
@@ -414,6 +394,7 @@
         }
     }
 
+    @Override
     public String toString() {
         if (sc.isConnected())
             return "Socket[addr=" + getInetAddress() +
@@ -422,23 +403,44 @@
         return "Socket[unconnected]";
     }
 
+    @Override
     public boolean isConnected() {
         return sc.isConnected();
     }
 
+    @Override
     public boolean isBound() {
         return sc.localAddress() != null;
     }
 
+    @Override
     public boolean isClosed() {
         return !sc.isOpen();
     }
 
+    @Override
     public boolean isInputShutdown() {
         return !sc.isInputOpen();
     }
 
+    @Override
     public boolean isOutputShutdown() {
         return !sc.isOutputOpen();
     }
+
+    @Override
+    public <T> Socket setOption(SocketOption<T> name, T value) throws IOException {
+        sc.setOption(name, value);
+        return this;
+    }
+
+    @Override
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return sc.getOption(name);
+    }
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
+        return sc.supportedOptions();
+    }
 }
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -34,6 +34,7 @@
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.net.SocketOption;
+import java.net.SocketTimeoutException;
 import java.net.StandardProtocolFamily;
 import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
@@ -42,6 +43,7 @@
 import java.nio.channels.AsynchronousCloseException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
 import java.nio.channels.NoConnectionPendingException;
 import java.nio.channels.NotYetConnectedException;
 import java.nio.channels.SelectionKey;
@@ -51,6 +53,7 @@
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
 import sun.net.ConnectionResetException;
@@ -81,7 +84,8 @@
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
-    private final Object stateLock = new Object();
+    private final ReentrantLock stateLock = new ReentrantLock();
+    private final Condition stateCondition = stateLock.newCondition();
 
     // Input/Output closed
     private volatile boolean isInputClosed;
@@ -133,8 +137,11 @@
         this.fd = fd;
         this.fdVal = IOUtil.fdVal(fd);
         if (bound) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 this.localAddress = Net.localAddress(fd);
+            } finally {
+                stateLock.unlock();
             }
         }
     }
@@ -147,10 +154,13 @@
         super(sp);
         this.fd = fd;
         this.fdVal = IOUtil.fdVal(fd);
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             this.localAddress = Net.localAddress(fd);
             this.remoteAddress = isa;
             this.state = ST_CONNECTED;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -187,26 +197,35 @@
 
     @Override
     public Socket socket() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (socket == null)
                 socket = SocketAdaptor.create(this);
             return socket;
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketAddress getLocalAddress() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             return Net.getRevealedLocalAddress(localAddress);
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketAddress getRemoteAddress() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             return remoteAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -218,7 +237,8 @@
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             if (name == StandardSocketOptions.IP_TOS) {
@@ -237,6 +257,8 @@
             // no options that require special handling
             Net.setSocketOption(fd, name, value);
             return this;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -249,7 +271,8 @@
         if (!supportedOptions().contains(name))
             throw new UnsupportedOperationException("'" + name + "' not supported");
 
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
 
             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
@@ -266,6 +289,8 @@
 
             // no options that require special handling
             return (T) Net.getSocketOption(fd, name);
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -307,10 +332,13 @@
             // set hook for Thread.interrupt
             begin();
 
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 ensureOpenAndConnected();
                 // record thread so it can be signalled if needed
                 readerThread = NativeThread.current();
+            } finally {
+                stateLock.unlock();
             }
         } else {
             ensureOpenAndConnected();
@@ -327,12 +355,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 readerThread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -362,12 +393,12 @@
                 if (isInputClosed)
                     return IOStatus.EOF;
 
+                n = IOUtil.read(fd, buf, -1, nd);
                 if (blocking) {
-                    do {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
                         n = IOUtil.read(fd, buf, -1, nd);
-                    } while (n == IOStatus.INTERRUPTED && isOpen());
-                } else {
-                    n = IOUtil.read(fd, buf, -1, nd);
+                    }
                 }
             } catch (ConnectionResetException e) {
                 connectionReset = true;
@@ -404,12 +435,12 @@
                 if (isInputClosed)
                     return IOStatus.EOF;
 
+                n = IOUtil.read(fd, dsts, offset, length, nd);
                 if (blocking) {
-                    do {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
                         n = IOUtil.read(fd, dsts, offset, length, nd);
-                    } while (n == IOStatus.INTERRUPTED && isOpen());
-                } else {
-                    n = IOUtil.read(fd, dsts, offset, length, nd);
+                    }
                 }
             } catch (ConnectionResetException e) {
                 connectionReset = true;
@@ -436,12 +467,15 @@
             // set hook for Thread.interrupt
             begin();
 
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 ensureOpenAndConnected();
                 if (isOutputClosed)
                     throw new ClosedChannelException();
                 // record thread so it can be signalled if needed
                 writerThread = NativeThread.current();
+            } finally {
+                stateLock.unlock();
             }
         } else {
             ensureOpenAndConnected();
@@ -458,12 +492,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 writerThread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -480,12 +517,12 @@
             int n = 0;
             try {
                 beginWrite(blocking);
+                n = IOUtil.write(fd, buf, -1, nd);
                 if (blocking) {
-                    do {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
                         n = IOUtil.write(fd, buf, -1, nd);
-                    } while (n == IOStatus.INTERRUPTED && isOpen());
-                } else {
-                    n = IOUtil.write(fd, buf, -1, nd);
+                    }
                 }
             } finally {
                 endWrite(blocking, n > 0);
@@ -510,12 +547,12 @@
             long n = 0;
             try {
                 beginWrite(blocking);
+                n = IOUtil.write(fd, srcs, offset, length, nd);
                 if (blocking) {
-                    do {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
                         n = IOUtil.write(fd, srcs, offset, length, nd);
-                    } while (n == IOStatus.INTERRUPTED && isOpen());
-                } else {
-                    n = IOUtil.write(fd, srcs, offset, length, nd);
+                    }
                 }
             } finally {
                 endWrite(blocking, n > 0);
@@ -562,10 +599,7 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
-                    ensureOpen();
-                    IOUtil.configureBlocking(fd, block);
-                }
+                lockedConfigureBlocking(block);
             } finally {
                 writeLock.unlock();
             }
@@ -575,11 +609,28 @@
     }
 
     /**
+     * Adjust the blocking mode while holding the readLock or writeLock.
+     */
+    private void lockedConfigureBlocking(boolean block) throws IOException {
+        assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
+        stateLock.lock();
+        try {
+            ensureOpen();
+            IOUtil.configureBlocking(fd, block);
+        } finally {
+            stateLock.unlock();
+        }
+    }
+
+    /**
      * Returns the local address, or null if not bound
      */
     InetSocketAddress localAddress() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return localAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -587,8 +638,11 @@
      * Returns the remote address, or null if not connected
      */
     InetSocketAddress remoteAddress() {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             return remoteAddress;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -598,7 +652,8 @@
         try {
             writeLock.lock();
             try {
-                synchronized (stateLock) {
+                stateLock.lock();
+                try {
                     ensureOpen();
                     if (state == ST_CONNECTIONPENDING)
                         throw new ConnectionPendingException();
@@ -613,6 +668,8 @@
                     NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
                     Net.bind(fd, isa.getAddress(), isa.getPort());
                     localAddress = Net.localAddress(fd);
+                } finally {
+                    stateLock.unlock();
                 }
             } finally {
                 writeLock.unlock();
@@ -649,7 +706,8 @@
             // set hook for Thread.interrupt
             begin();
         }
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             int state = this.state;
             if (state == ST_CONNECTED)
@@ -667,6 +725,8 @@
                 // record thread so it can be signalled if needed
                 readerThread = NativeThread.current();
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -683,43 +743,62 @@
         endRead(blocking, completed);
 
         if (completed) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 if (state == ST_CONNECTIONPENDING) {
                     localAddress = Net.localAddress(fd);
                     state = ST_CONNECTED;
                 }
+            } finally {
+                stateLock.unlock();
             }
         }
     }
 
+    /**
+     * Checks the remote address to which this channel is to be connected.
+     */
+    private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {
+        InetSocketAddress isa = Net.checkAddress(sa);
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
+        }
+        if (isa.getAddress().isAnyLocalAddress()) {
+            return new InetSocketAddress(InetAddress.getLocalHost(), isa.getPort());
+        } else {
+            return isa;
+        }
+    }
+
     @Override
-    public boolean connect(SocketAddress sa) throws IOException {
-        InetSocketAddress isa = Net.checkAddress(sa);
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null)
-            sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
-
-        InetAddress ia = isa.getAddress();
-        if (ia.isAnyLocalAddress())
-            ia = InetAddress.getLocalHost();
-
+    public boolean connect(SocketAddress remote) throws IOException {
+        InetSocketAddress isa = checkRemote(remote);
         try {
             readLock.lock();
             try {
                 writeLock.lock();
                 try {
-                    int n = 0;
                     boolean blocking = isBlocking();
+                    boolean connected = false;
                     try {
                         beginConnect(blocking, isa);
-                        do {
-                            n = Net.connect(fd, ia, isa.getPort());
-                        } while (n == IOStatus.INTERRUPTED && isOpen());
+                        int n = Net.connect(fd, isa.getAddress(), isa.getPort());
+                        if (n > 0) {
+                            connected = true;
+                        } else if (blocking) {
+                            assert IOStatus.okayToRetry(n);
+                            boolean polled = false;
+                            while (!polled && isOpen()) {
+                                park(Net.POLLOUT);
+                                polled = Net.pollConnectNow(fd);
+                            }
+                            connected = polled && isOpen();
+                        }
                     } finally {
-                        endConnect(blocking, (n > 0));
+                        endConnect(blocking, connected);
                     }
-                    assert IOStatus.check(n);
-                    return n > 0;
+                    return connected;
                 } finally {
                     writeLock.unlock();
                 }
@@ -744,7 +823,8 @@
             // set hook for Thread.interrupt
             begin();
         }
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (state != ST_CONNECTIONPENDING)
                 throw new NoConnectionPendingException();
@@ -752,6 +832,8 @@
                 // record thread so it can be signalled if needed
                 readerThread = NativeThread.current();
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -768,11 +850,14 @@
         endRead(blocking, completed);
 
         if (completed) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 if (state == ST_CONNECTIONPENDING) {
                     localAddress = Net.localAddress(fd);
                     state = ST_CONNECTED;
                 }
+            } finally {
+                stateLock.unlock();
             }
         }
     }
@@ -792,13 +877,14 @@
                     boolean connected = false;
                     try {
                         beginFinishConnect(blocking);
+                        boolean polled = Net.pollConnectNow(fd);
                         if (blocking) {
-                            do {
-                                connected = Net.pollConnect(fd, -1);
-                            } while (!connected && isOpen());
-                        } else {
-                            connected = Net.pollConnect(fd, 0);
+                            while (!polled && isOpen()) {
+                                park(Net.POLLOUT);
+                                polled = Net.pollConnectNow(fd);
+                            }
                         }
+                        connected = polled && isOpen();
                     } finally {
                         endFinishConnect(blocking, connected);
                     }
@@ -843,16 +929,20 @@
         boolean interrupted = false;
 
         // set state to ST_CLOSING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state < ST_CLOSING;
             blocking = isBlocking();
             connected = (state == ST_CONNECTED);
             state = ST_CLOSING;
+        } finally {
+            stateLock.unlock();
         }
 
         // wait for any outstanding I/O operations to complete
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 assert state == ST_CLOSING;
                 long reader = readerThread;
                 long writer = writerThread;
@@ -868,12 +958,14 @@
                     // wait for blocking I/O operations to end
                     while (readerThread != 0 || writerThread != 0) {
                         try {
-                            stateLock.wait();
+                            stateCondition.await();
                         } catch (InterruptedException e) {
                             interrupted = true;
                         }
                     }
                 }
+            } finally {
+                stateLock.unlock();
             }
         } else {
             // non-blocking mode: wait for read/write to complete
@@ -887,7 +979,8 @@
         }
 
         // set state to ST_KILLPENDING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state == ST_CLOSING;
             // if connected and the channel is registered with a Selector then
             // shutdown the output if possible so that the peer reads EOF. If
@@ -908,6 +1001,8 @@
                 } catch (IOException ignore) { }
             }
             state = ST_KILLPENDING;
+        } finally {
+            stateLock.unlock();
         }
 
         // close socket if not registered with Selector
@@ -921,17 +1016,21 @@
 
     @Override
     public void kill() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (state == ST_KILLPENDING) {
                 state = ST_KILLED;
                 nd.close(fd);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketChannel shutdownInput() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (!isConnected())
                 throw new NotYetConnectedException();
@@ -943,12 +1042,15 @@
                 isInputClosed = true;
             }
             return this;
+        } finally {
+            stateLock.unlock();
         }
     }
 
     @Override
     public SocketChannel shutdownOutput() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpen();
             if (!isConnected())
                 throw new NotYetConnectedException();
@@ -960,6 +1062,8 @@
                 isOutputClosed = true;
             }
             return this;
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -972,58 +1076,223 @@
     }
 
     /**
-     * Poll this channel's socket for reading up to the given timeout.
-     * @return {@code true} if the socket is polled
+     * Waits for a connection attempt to finish with a timeout
+     * @throws SocketTimeoutException if the connect timeout elapses
+     */
+    private boolean finishTimedConnect(long nanos) throws IOException {
+        long startNanos = System.nanoTime();
+        boolean polled = Net.pollConnectNow(fd);
+        while (!polled && isOpen()) {
+            long remainingNanos = nanos - (System.nanoTime() - startNanos);
+            if (remainingNanos <= 0) {
+                throw new SocketTimeoutException("Connect timed out");
+            }
+            park(Net.POLLOUT, remainingNanos);
+            polled = Net.pollConnectNow(fd);
+        }
+        return polled && isOpen();
+    }
+
+    /**
+     * Attempts to establish a connection to the given socket address with a
+     * timeout. Closes the socket if connection cannot be established.
+     *
+     * @apiNote This method is for use by the socket adaptor.
+     *
+     * @throws IllegalBlockingModeException if the channel is non-blocking
+     * @throws SocketTimeoutException if the read timeout elapses
      */
-    boolean pollRead(long timeout) throws IOException {
-        boolean blocking = isBlocking();
-        assert Thread.holdsLock(blockingLock()) && blocking;
+    void blockingConnect(SocketAddress remote, long nanos) throws IOException {
+        InetSocketAddress isa = checkRemote(remote);
+        try {
+            readLock.lock();
+            try {
+                writeLock.lock();
+                try {
+                    if (!isBlocking())
+                        throw new IllegalBlockingModeException();
+                    boolean connected = false;
+                    try {
+                        beginConnect(true, isa);
+                        // change socket to non-blocking
+                        lockedConfigureBlocking(false);
+                        try {
+                            int n = Net.connect(fd, isa.getAddress(), isa.getPort());
+                            connected = (n > 0) ? true : finishTimedConnect(nanos);
+                        } finally {
+                            // restore socket to blocking mode
+                            lockedConfigureBlocking(true);
+                        }
+                    } finally {
+                        endConnect(true, connected);
+                    }
+                } finally {
+                    writeLock.unlock();
+                }
+            } finally {
+                readLock.unlock();
+            }
+        } catch (IOException ioe) {
+            // connect failed, close the channel
+            close();
+            throw SocketExceptions.of(ioe, isa);
+        }
+    }
+
+    /**
+     * Attempts to read bytes from the socket into the given byte array.
+     */
+    private int tryRead(byte[] b, int off, int len) throws IOException {
+        ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
+        assert dst.position() == 0;
+        try {
+            int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
+            if (n > 0) {
+                dst.get(b, off, n);
+            }
+            return n;
+        } finally{
+            Util.offerFirstTemporaryDirectBuffer(dst);
+        }
+    }
+
+    /**
+     * Reads bytes from the socket into the given byte array with a timeout.
+     * @throws SocketTimeoutException if the read timeout elapses
+     */
+    private int timedRead(byte[] b, int off, int len, long nanos) throws IOException {
+        long startNanos = System.nanoTime();
+        int n = tryRead(b, off, len);
+        while (n == IOStatus.UNAVAILABLE && isOpen()) {
+            long remainingNanos = nanos - (System.nanoTime() - startNanos);
+            if (remainingNanos <= 0) {
+                throw new SocketTimeoutException("Read timed out");
+            }
+            park(Net.POLLIN, remainingNanos);
+            n = tryRead(b, off, len);
+        }
+        return n;
+    }
+
+    /**
+     * Reads bytes from the socket into the given byte array.
+     *
+     * @apiNote This method is for use by the socket adaptor.
+     *
+     * @throws IllegalBlockingModeException if the channel is non-blocking
+     * @throws SocketTimeoutException if the read timeout elapses
+     */
+    int blockingRead(byte[] b, int off, int len, long nanos) throws IOException {
+        Objects.checkFromIndexSize(off, len, b.length);
+        if (len == 0) {
+            // nothing to do
+            return 0;
+        }
 
         readLock.lock();
         try {
-            boolean polled = false;
+            // check that channel is configured blocking
+            if (!isBlocking())
+                throw new IllegalBlockingModeException();
+
+            int n = 0;
             try {
-                beginRead(blocking);
-                int events = Net.poll(fd, Net.POLLIN, timeout);
-                polled = (events != 0);
+                beginRead(true);
+
+                // check if connection has been reset
+                if (connectionReset)
+                    throwConnectionReset();
+
+                // check if input is shutdown
+                if (isInputClosed)
+                    return IOStatus.EOF;
+
+                if (nanos > 0) {
+                    // change socket to non-blocking
+                    lockedConfigureBlocking(false);
+                    try {
+                        n = timedRead(b, off, len, nanos);
+                    } finally {
+                        // restore socket to blocking mode
+                        lockedConfigureBlocking(true);
+                    }
+                } else {
+                    // read, no timeout
+                    n = tryRead(b, off, len);
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = tryRead(b, off, len);
+                    }
+                }
+            } catch (ConnectionResetException e) {
+                connectionReset = true;
+                throwConnectionReset();
             } finally {
-                endRead(blocking, polled);
+                endRead(true, n > 0);
+                if (n <= 0 && isInputClosed)
+                    return IOStatus.EOF;
             }
-            return polled;
+            assert n > 0 || n == -1;
+            return n;
         } finally {
             readLock.unlock();
         }
     }
 
     /**
-     * Poll this channel's socket for a connection, up to the given timeout.
-     * @return {@code true} if the socket is polled
+     * Attempts to write a sequence of bytes to the socket from the given
+     * byte array.
      */
-    boolean pollConnected(long timeout) throws IOException {
-        boolean blocking = isBlocking();
-        assert Thread.holdsLock(blockingLock()) && blocking;
+    private int tryWrite(byte[] b, int off, int len) throws IOException {
+        ByteBuffer src = Util.getTemporaryDirectBuffer(len);
+        assert src.position() == 0;
+        try {
+            src.put(b, off, len);
+            return nd.write(fd, ((DirectBuffer)src).address(), len);
+        } finally {
+            Util.offerFirstTemporaryDirectBuffer(src);
+        }
+    }
 
-        readLock.lock();
+    /**
+     * Writes a sequence of bytes to the socket from the given byte array.
+     *
+     * @apiNote This method is for use by the socket adaptor.
+     */
+    void blockingWriteFully(byte[] b, int off, int len) throws IOException {
+        Objects.checkFromIndexSize(off, len, b.length);
+        if (len == 0) {
+            // nothing to do
+            return;
+        }
+
+        writeLock.lock();
         try {
-            writeLock.lock();
+            // check that channel is configured blocking
+            if (!isBlocking())
+                throw new IllegalBlockingModeException();
+
+            // loop until all bytes have been written
+            int pos = off;
+            int end = off + len;
+            beginWrite(true);
             try {
-                boolean polled = false;
-                try {
-                    beginFinishConnect(blocking);
-                    int events = Net.poll(fd, Net.POLLCONN, timeout);
-                    polled = (events != 0);
-                } finally {
-                    // invoke endFinishConnect with completed = false so that
-                    // the state is not changed to ST_CONNECTED. The socket
-                    // adaptor will use finishConnect to finish.
-                    endFinishConnect(blocking, /*completed*/false);
+                while (pos < end && isOpen()) {
+                    int size = end - pos;
+                    int n = tryWrite(b, pos, size);
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
+                        n = tryWrite(b, pos, size);
+                    }
+                    if (n > 0) {
+                        pos += n;
+                    }
                 }
-                return polled;
             } finally {
-                writeLock.unlock();
+                endWrite(true, pos >= end);
             }
         } finally {
-            readLock.unlock();
+            writeLock.unlock();
         }
     }
 
@@ -1031,13 +1300,16 @@
      * Return the number of bytes in the socket input buffer.
      */
     int available() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             ensureOpenAndConnected();
             if (isInputClosed) {
                 return 0;
             } else {
                 return Net.available(fd);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -1117,7 +1389,8 @@
         if (!isOpen())
             sb.append("closed");
         else {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 switch (state) {
                 case ST_UNCONNECTED:
                     sb.append("unconnected");
@@ -1142,6 +1415,8 @@
                     sb.append(" remote=");
                     sb.append(remoteAddress().toString());
                 }
+            } finally {
+                stateLock.unlock();
             }
         }
         sb.append(']');
Binary file src/java.base/share/lib/security/cacerts has changed
--- a/src/java.base/share/native/include/classfile_constants.h.template	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/native/include/classfile_constants.h.template	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2017, 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
@@ -109,7 +109,9 @@
     JVM_CONSTANT_MethodType             = 16,  // JSR 292
     JVM_CONSTANT_Dynamic                = 17,
     JVM_CONSTANT_InvokeDynamic          = 18,
-    JVM_CONSTANT_ExternalMax            = 18
+    JVM_CONSTANT_Module                 = 19,
+    JVM_CONSTANT_Package                = 20,
+    JVM_CONSTANT_ExternalMax            = 20 
 };
 
 /* JVM_CONSTANT_MethodHandle subtypes */
--- a/src/java.base/share/native/libnet/net_util.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/native/libnet/net_util.c	Fri May 03 14:59:32 2019 -0400
@@ -27,12 +27,19 @@
 
 #include "java_net_InetAddress.h"
 
+int IPv4_supported();
 int IPv6_supported();
 int reuseport_supported();
 
+static int IPv4_available;
 static int IPv6_available;
 static int REUSEPORT_available;
 
+JNIEXPORT jint JNICALL ipv4_available()
+{
+    return IPv4_available;
+}
+
 JNIEXPORT jint JNICALL ipv6_available()
 {
     return IPv6_available;
@@ -68,6 +75,7 @@
      * check now whether we have IPv6 on this platform and if the
      * supporting socket APIs are available
      */
+    IPv4_available = IPv4_supported();
     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
 
     /* check if SO_REUSEPORT is supported on this platform */
--- a/src/java.base/share/native/libnet/net_util.h	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/share/native/libnet/net_util.h	Fri May 03 14:59:32 2019 -0400
@@ -126,6 +126,7 @@
 
 jfieldID NET_GetFileDescriptorID(JNIEnv *env);
 
+JNIEXPORT jint JNICALL ipv4_available();
 JNIEXPORT jint JNICALL ipv6_available();
 
 JNIEXPORT jint JNICALL reuseport_available();
--- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -45,13 +45,8 @@
     /**
      * Constructs an empty instance.
      */
-    PlainSocketImpl() { }
-
-    /**
-     * Constructs an instance with the given file descriptor.
-     */
-    PlainSocketImpl(FileDescriptor fd) {
-        this.fd = fd;
+    PlainSocketImpl(boolean isServer) {
+        super(isServer);
     }
 
     static final ExtendedSocketOptions extendedOptions =
@@ -90,7 +85,7 @@
 
     protected Set<SocketOption<?>> supportedOptions() {
         HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
-        if (getServerSocket() != null) {
+        if (isServer) {
             options.addAll(ExtendedSocketOptions.serverSocketOptions());
         } else {
             options.addAll(ExtendedSocketOptions.clientSocketOptions());
@@ -106,12 +101,16 @@
         try {
             socketSetOption0(opt, b, val);
         } catch (SocketException se) {
-            if (socket == null || !socket.isConnected())
+            if (!isConnected)
                 throw se;
         }
     }
 
-    native void socketCreate(boolean isServer) throws IOException;
+    void socketCreate(boolean stream) throws IOException {
+        socketCreate(stream, isServer);
+    }
+
+    native void socketCreate(boolean stream, boolean isServer) throws IOException;
 
     native void socketConnect(InetAddress address, int port, int timeout)
         throws IOException;
--- a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -35,6 +35,7 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.spi.SelectorProvider;
 import java.util.Objects;
+import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
 class SinkChannelImpl
@@ -53,7 +54,8 @@
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
-    private final Object stateLock = new Object();
+    private final ReentrantLock stateLock = new ReentrantLock();
+    private final Condition stateCondition = stateLock.newCondition();
 
     // -- The following fields are protected by stateLock
 
@@ -95,15 +97,19 @@
         boolean blocking;
 
         // set state to ST_CLOSING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state < ST_CLOSING;
             state = ST_CLOSING;
             blocking = isBlocking();
+        } finally {
+            stateLock.unlock();
         }
 
         // wait for any outstanding write to complete
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 assert state == ST_CLOSING;
                 long th = thread;
                 if (th != 0) {
@@ -113,12 +119,14 @@
                     // wait for write operation to end
                     while (thread != 0) {
                         try {
-                            stateLock.wait();
+                            stateCondition.await();
                         } catch (InterruptedException e) {
                             interrupted = true;
                         }
                     }
                 }
+            } finally {
+                stateLock.unlock();
             }
         } else {
             // non-blocking mode: wait for write to complete
@@ -127,9 +135,12 @@
         }
 
         // set state to ST_KILLPENDING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state == ST_CLOSING;
             state = ST_KILLPENDING;
+        } finally {
+            stateLock.unlock();
         }
 
         // close socket if not registered with Selector
@@ -143,12 +154,15 @@
 
     @Override
     public void kill() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert thread == 0;
             if (state == ST_KILLPENDING) {
                 state = ST_KILLED;
                 nd.close(fd);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -156,8 +170,11 @@
     protected void implConfigureBlocking(boolean block) throws IOException {
         writeLock.lock();
         try {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 IOUtil.configureBlocking(fd, block);
+            } finally {
+                stateLock.unlock();
             }
         } finally {
             writeLock.unlock();
@@ -212,11 +229,14 @@
             // set hook for Thread.interrupt
             begin();
         }
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (!isOpen())
                 throw new ClosedChannelException();
             if (blocking)
                 thread = NativeThread.current();
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -230,12 +250,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 thread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -252,9 +275,13 @@
             int n = 0;
             try {
                 beginWrite(blocking);
-                do {
-                    n = IOUtil.write(fd, src, -1, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.write(fd, src, -1, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
+                        n = IOUtil.write(fd, src, -1, nd);
+                    }
+                }
             } finally {
                 endWrite(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -275,9 +302,13 @@
             long n = 0;
             try {
                 beginWrite(blocking);
-                do {
-                    n = IOUtil.write(fd, srcs, offset, length, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.write(fd, srcs, offset, length, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLOUT);
+                        n = IOUtil.write(fd, srcs, offset, length, nd);
+                    }
+                }
             } finally {
                 endWrite(blocking, n > 0);
                 assert IOStatus.check(n);
--- a/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -35,6 +35,7 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.spi.SelectorProvider;
 import java.util.Objects;
+import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
 class SourceChannelImpl
@@ -53,7 +54,8 @@
 
     // Lock held by any thread that modifies the state fields declared below
     // DO NOT invoke a blocking I/O operation while holding this lock!
-    private final Object stateLock = new Object();
+    private final ReentrantLock stateLock = new ReentrantLock();
+    private final Condition stateCondition = stateLock.newCondition();
 
     // -- The following fields are protected by stateLock
 
@@ -95,15 +97,19 @@
         boolean blocking;
 
         // set state to ST_CLOSING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state < ST_CLOSING;
             state = ST_CLOSING;
             blocking = isBlocking();
+        } finally {
+            stateLock.unlock();
         }
 
         // wait for any outstanding read to complete
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 assert state == ST_CLOSING;
                 long th = thread;
                 if (th != 0) {
@@ -113,12 +119,14 @@
                     // wait for read operation to end
                     while (thread != 0) {
                         try {
-                            stateLock.wait();
+                            stateCondition.await();
                         } catch (InterruptedException e) {
                             interrupted = true;
                         }
                     }
                 }
+            } finally {
+                stateLock.unlock();
             }
         } else {
             // non-blocking mode: wait for read to complete
@@ -127,9 +135,12 @@
         }
 
         // set state to ST_KILLPENDING
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert state == ST_CLOSING;
             state = ST_KILLPENDING;
+        } finally {
+            stateLock.unlock();
         }
 
         // close socket if not registered with Selector
@@ -143,12 +154,15 @@
 
     @Override
     public void kill() throws IOException {
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             assert thread == 0;
             if (state == ST_KILLPENDING) {
                 state = ST_KILLED;
                 nd.close(fd);
             }
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -156,8 +170,11 @@
     protected void implConfigureBlocking(boolean block) throws IOException {
         readLock.lock();
         try {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 IOUtil.configureBlocking(fd, block);
+            } finally {
+                stateLock.unlock();
             }
         } finally {
             readLock.unlock();
@@ -212,11 +229,14 @@
             // set hook for Thread.interrupt
             begin();
         }
-        synchronized (stateLock) {
+        stateLock.lock();
+        try {
             if (!isOpen())
                 throw new ClosedChannelException();
             if (blocking)
                 thread = NativeThread.current();
+        } finally {
+            stateLock.unlock();
         }
     }
 
@@ -230,12 +250,15 @@
         throws AsynchronousCloseException
     {
         if (blocking) {
-            synchronized (stateLock) {
+            stateLock.lock();
+            try {
                 thread = 0;
                 // notify any thread waiting in implCloseSelectableChannel
                 if (state == ST_CLOSING) {
-                    stateLock.notifyAll();
+                    stateCondition.signalAll();
                 }
+            } finally {
+                stateLock.unlock();
             }
             // remove hook for Thread.interrupt
             end(completed);
@@ -252,9 +275,13 @@
             int n = 0;
             try {
                 beginRead(blocking);
-                do {
-                    n = IOUtil.read(fd, dst, -1, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.read(fd, dst, -1, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = IOUtil.read(fd, dst, -1, nd);
+                    }
+                }
             } finally {
                 endRead(blocking, n > 0);
                 assert IOStatus.check(n);
@@ -275,9 +302,13 @@
             long n = 0;
             try {
                 beginRead(blocking);
-                do {
-                    n = IOUtil.read(fd, dsts, offset, length, nd);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                n = IOUtil.read(fd, dsts, offset, length, nd);
+                if (blocking) {
+                    while (IOStatus.okayToRetry(n) && isOpen()) {
+                        park(Net.POLLIN);
+                        n = IOUtil.read(fd, dsts, offset, length, nd);
+                    }
+                }
             } finally {
                 endRead(blocking, n > 0);
                 assert IOStatus.check(n);
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java	Fri May 03 14:59:32 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
@@ -73,15 +73,23 @@
 
             boolean haveFd = false;
             boolean useFutimes = false;
+            boolean useLutimes = false;
             int fd = -1;
             try {
-                fd = file.openForAttributeAccess(followLinks);
-                if (fd != -1) {
-                    haveFd = true;
-                    useFutimes = futimesSupported();
+                if (!followLinks) {
+                    useLutimes = lutimesSupported() &&
+                        UnixFileAttributes.get(file, false).isSymbolicLink();
+                }
+                if (!useLutimes) {
+                    fd = file.openForAttributeAccess(followLinks);
+                    if (fd != -1) {
+                        haveFd = true;
+                        useFutimes = futimesSupported();
+                    }
                 }
             } catch (UnixException x) {
-                if (x.errno() != UnixConstants.ENXIO) {
+                if (!(x.errno() == UnixConstants.ENXIO ||
+                     (x.errno() == UnixConstants.ELOOP && useLutimes))) {
                     x.rethrowAsIOException(file);
                 }
             }
@@ -112,6 +120,8 @@
                 try {
                     if (useFutimes) {
                         futimes(fd, accessValue, modValue);
+                    } else if (useLutimes) {
+                        lutimes(file, accessValue, modValue);
                     } else {
                         utimes(file, accessValue, modValue);
                     }
@@ -131,6 +141,8 @@
                     try {
                         if (useFutimes) {
                             futimes(fd, accessValue, modValue);
+                        } else if (useLutimes) {
+                            lutimes(file, accessValue, modValue);
                         } else {
                             utimes(file, accessValue, modValue);
                         }
--- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Fri May 03 14:59:32 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
@@ -401,7 +401,7 @@
     static native void fchmod(int fd, int mode) throws UnixException;
 
     /**
-     * utimes(conar char* path, const struct timeval times[2])
+     * utimes(const char* path, const struct timeval times[2])
      */
     static void utimes(UnixPath path, long times0, long times1)
         throws UnixException
@@ -417,11 +417,27 @@
         throws UnixException;
 
     /**
-     * futimes(int fildes,, const struct timeval times[2])
+     * futimes(int fildes, const struct timeval times[2])
      */
     static native void futimes(int fd, long times0, long times1) throws UnixException;
 
     /**
+     * lutimes(const char* path, const struct timeval times[2])
+     */
+    static void lutimes(UnixPath path, long times0, long times1)
+        throws UnixException
+    {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            lutimes0(buffer.address(), times0, times1);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void lutimes0(long pathAddress, long times0, long times1)
+        throws UnixException;
+
+    /**
      * DIR *opendir(const char* dirname)
      */
     static long opendir(UnixPath path) throws UnixException {
@@ -578,9 +594,10 @@
     /**
      * Capabilities
      */
-    private static final int SUPPORTS_OPENAT        = 1 << 1;    // syscalls
+    private static final int SUPPORTS_OPENAT        = 1 << 1;  // syscalls
     private static final int SUPPORTS_FUTIMES       = 1 << 2;
-    private static final int SUPPORTS_BIRTHTIME     = 1 << 16;   // other features
+    private static final int SUPPORTS_LUTIMES       = 1 << 4;
+    private static final int SUPPORTS_BIRTHTIME     = 1 << 16; // other features
     private static final int capabilities;
 
     /**
@@ -598,6 +615,13 @@
     }
 
     /**
+     * Supports lutimes
+     */
+    static boolean lutimesSupported() {
+        return (capabilities & SUPPORTS_LUTIMES) != 0;
+    }
+
+    /**
      * Supports file birth (creation) time attribute
      */
     static boolean birthtimeSupported() {
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Fri May 03 14:59:32 2019 -0400
@@ -915,8 +915,10 @@
         return;
     }
 
-    /* Disable IPV6_V6ONLY to ensure dual-socket support */
-    if (domain == AF_INET6) {
+    /*
+     * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+     */
+    if (domain == AF_INET6 && ipv4_available()) {
         arg = 0;
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                        sizeof(int)) < 0) {
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c	Fri May 03 14:59:32 2019 -0400
@@ -43,7 +43,6 @@
 jfieldID psi_localportID;
 jfieldID psi_timeoutID;
 jfieldID psi_trafficClassID;
-jfieldID psi_serverSocketID;
 jfieldID psi_fdLockID;
 jfieldID psi_closePendingID;
 
@@ -128,9 +127,6 @@
     CHECK_NULL(psi_timeoutID);
     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
     CHECK_NULL(psi_trafficClassID);
-    psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
-                        "Ljava/net/ServerSocket;");
-    CHECK_NULL(psi_serverSocketID);
     psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
                                       "Ljava/lang/Object;");
     CHECK_NULL(psi_fdLockID);
@@ -156,10 +152,10 @@
 /*
  * Class:     java_net_PlainSocketImpl
  * Method:    socketCreate
- * Signature: (Z)V */
+ * Signature: (ZZ)V */
 JNIEXPORT void JNICALL
 Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
-                                           jboolean stream) {
+                                           jboolean stream, jboolean isServer) {
     jobject fdObj, ssObj;
     int fd;
     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
@@ -187,8 +183,10 @@
         return;
     }
 
-    /* Disable IPV6_V6ONLY to ensure dual-socket support */
-    if (domain == AF_INET6) {
+    /*
+     * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+     */
+    if (domain == AF_INET6 && ipv4_available()) {
         int arg = 0;
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                        sizeof(int)) < 0) {
@@ -202,8 +200,7 @@
      * If this is a server socket then enable SO_REUSEADDR
      * automatically and set to non blocking.
      */
-    ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
-    if (ssObj != NULL) {
+    if (isServer) {
         int arg = 1;
         SET_NONBLOCKING(fd);
         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
--- a/src/java.base/unix/native/libnet/net_util_md.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/native/libnet/net_util_md.c	Fri May 03 14:59:32 2019 -0400
@@ -278,6 +278,16 @@
     return (*env)->GetFieldID(env, cls, "fd", "I");
 }
 
+jint  IPv4_supported()
+{
+    int fd = socket(AF_INET, SOCK_STREAM, 0) ;
+    if (fd < 0) {
+        return JNI_FALSE;
+    }
+    close(fd);
+    return JNI_TRUE;
+}
+
 #if defined(DONT_ENABLE_IPV6)
 jint  IPv6_supported()
 {
--- a/src/java.base/unix/native/libnio/ch/Net.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/native/libnio/ch/Net.c	Fri May 03 14:59:32 2019 -0400
@@ -216,8 +216,10 @@
         return handleSocketError(env, errno);
     }
 
-    /* Disable IPV6_V6ONLY to ensure dual-socket support */
-    if (domain == AF_INET6) {
+    /*
+     * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+     */
+    if (domain == AF_INET6 && ipv4_available()) {
         int arg = 0;
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                        sizeof(int)) < 0) {
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Fri May 03 14:59:32 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
@@ -143,6 +143,7 @@
 typedef int unlinkat_func(int, const char*, int);
 typedef int renameat_func(int, const char*, int, const char*);
 typedef int futimesat_func(int, const char *, const struct timeval *);
+typedef int lutimes_func(const char *, const struct timeval *);
 typedef DIR* fdopendir_func(int);
 
 static openat64_func* my_openat64_func = NULL;
@@ -150,6 +151,7 @@
 static unlinkat_func* my_unlinkat_func = NULL;
 static renameat_func* my_renameat_func = NULL;
 static futimesat_func* my_futimesat_func = NULL;
+static lutimes_func* my_lutimes_func = NULL;
 static fdopendir_func* my_fdopendir_func = NULL;
 
 /**
@@ -269,7 +271,10 @@
 #endif
     my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
     my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
+#ifndef _ALLBSD_SOURCE
     my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
+    my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes");
+#endif
 #if defined(_AIX)
     my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64");
 #else
@@ -282,13 +287,16 @@
         my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
 #endif
 
-    /* supports futimes or futimesat */
+    /* supports futimes or futimesat and/or lutimes */
 
 #ifdef _ALLBSD_SOURCE
     capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
+    capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
 #else
     if (my_futimesat_func != NULL)
         capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
+    if (my_lutimes_func != NULL)
+        capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
 #endif
 
     /* supports openat, etc. */
@@ -675,7 +683,7 @@
     RESTARTABLE(futimes(filedes, &times[0]), err);
 #else
     if (my_futimesat_func == NULL) {
-        JNU_ThrowInternalError(env, "my_ftimesat_func is NULL");
+        JNU_ThrowInternalError(env, "my_futimesat_func is NULL");
         return;
     }
     RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
@@ -685,6 +693,34 @@
     }
 }
 
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this,
+    jlong pathAddress, jlong accessTime, jlong modificationTime)
+{
+    int err;
+    struct timeval times[2];
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    times[0].tv_sec = accessTime / 1000000;
+    times[0].tv_usec = accessTime % 1000000;
+
+    times[1].tv_sec = modificationTime / 1000000;
+    times[1].tv_usec = modificationTime % 1000000;
+
+#ifdef _ALLBSD_SOURCE
+    RESTARTABLE(lutimes(path, &times[0]), err);
+#else
+    if (my_lutimes_func == NULL) {
+        JNU_ThrowInternalError(env, "my_lutimes_func is NULL");
+        return;
+    }
+    RESTARTABLE((*my_lutimes_func)(path, &times[0]), err);
+#endif
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
     jlong pathAddress)
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Fri May 03 14:59:32 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
@@ -65,14 +65,8 @@
     /**
      * Constructs an empty instance.
      */
-    public PlainSocketImpl() {
-    }
-
-    /**
-     * Constructs an instance with the given file descriptor.
-     */
-    public PlainSocketImpl(FileDescriptor fd) {
-        this.fd = fd;
+    PlainSocketImpl(boolean isServer) {
+        super(isServer);
     }
 
     @Override
@@ -222,7 +216,7 @@
             if (preferIPv4Stack) {
                 // Don't enable the socket option on ServerSocket as it's
                 // meaningless (we don't receive on a ServerSocket).
-                if (serverSocket == null) {
+                if (!isServer) {
                     setSoTimeout0(nativefd, ((Integer)value).intValue());
                 }
             } // else timeout is implemented through select.
--- a/src/java.base/windows/native/libnet/net_util_md.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.base/windows/native/libnet/net_util_md.c	Fri May 03 14:59:32 2019 -0400
@@ -214,6 +214,12 @@
     return (*env)->GetFieldID(env, cls, "fd", "I");
 }
 
+jint  IPv4_supported()
+{
+    /* TODO: properly check for IPv4 support on Windows */
+    return JNI_TRUE;
+}
+
 jint  IPv6_supported()
 {
     SOCKET s = socket(AF_INET6, SOCK_STREAM, 0) ;
--- a/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Fri May 03 14:59:32 2019 -0400
@@ -25,6 +25,7 @@
 
 package javax.annotation.processing;
 
+import java.util.List;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
@@ -80,10 +81,9 @@
      */
     public Set<String> getSupportedOptions() {
         SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class);
-        if  (so == null)
-            return Collections.emptySet();
-        else
-            return arrayToSet(so.value(), false);
+        return (so == null) ?
+            Set.of() :
+            arrayToSet(so.value(), false, "option value", "@SupportedOptions");
     }
 
     /**
@@ -110,12 +110,13 @@
                                                              "No SupportedAnnotationTypes annotation " +
                                                              "found on " + this.getClass().getName() +
                                                              ", returning an empty set.");
-                return Collections.emptySet();
+                return Set.of();
             } else {
                 boolean stripModulePrefixes =
                         initialized &&
                         processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0;
-                return arrayToSet(sat.value(), stripModulePrefixes);
+                return arrayToSet(sat.value(), stripModulePrefixes,
+                                  "annotation type", "@SupportedAnnotationTypes");
             }
         }
 
@@ -181,7 +182,7 @@
                                                          AnnotationMirror annotation,
                                                          ExecutableElement member,
                                                          String userText) {
-        return Collections.emptyList();
+        return List.of();
     }
 
     /**
@@ -195,17 +196,33 @@
         return initialized;
     }
 
-    private static Set<String> arrayToSet(String[] array,
-                                          boolean stripModulePrefixes) {
+    private Set<String> arrayToSet(String[] array,
+                                          boolean stripModulePrefixes,
+                                   String contentType,
+                                   String annotationName) {
         assert array != null;
-        Set<String> set = new HashSet<>(array.length);
+        Set<String> set = new HashSet<>();
         for (String s : array) {
+            boolean stripped = false;
             if (stripModulePrefixes) {
                 int index = s.indexOf('/');
-                if (index != -1)
+                if (index != -1) {
                     s = s.substring(index + 1);
+                    stripped = true;
+                }
             }
-            set.add(s);
+            boolean added = set.add(s);
+            // Don't issue a duplicate warning when the module name is
+            // stripped off to avoid spurious warnings in a case like
+            // "foo/a.B", "bar/a.B".
+            if (!added && !stripped && isInitialized() ) {
+                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
+                                                         "Duplicate " + contentType  +
+                                                         " ``" + s  + "'' for processor " +
+                                                         this.getClass().getName() +
+                                                         " in its " + annotationName  +
+                                                         "annotation.");
+            }
         }
         return Collections.unmodifiableSet(set);
     }
--- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Fri May 03 14:59:32 2019 -0400
@@ -252,7 +252,7 @@
      * "/"} character. For example, if a processor supports {@code
      * "a.B"}, this can include multiple annotation types named {@code
      * a.B} which reside in different modules. To only support {@code
-     * a.B} in the {@code Foo} module, instead use {@code "Foo/a.B"}.
+     * a.B} in the {@code foo} module, instead use {@code "foo/a.B"}.
      *
      * If a module name is included, only an annotation in that module
      * is matched. In particular, if a module name is given in an
--- a/src/java.desktop/macosx/classes/sun/font/CFont.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/macosx/classes/sun/font/CFont.java	Fri May 03 14:59:32 2019 -0400
@@ -78,17 +78,10 @@
     }
 
     @Override
-    protected long getLayoutTableCache() {
-        return getLayoutTableCacheNative(getNativeFontPtr());
-    }
-
-    @Override
     protected byte[] getTableBytes(int tag) {
         return getTableBytesNative(getNativeFontPtr(), tag);
     }
 
-    private native synchronized long getLayoutTableCacheNative(long nativeFontPtr);
-
     private native byte[] getTableBytesNative(long nativeFontPtr, int tag);
 
     private static native long createNativeFont(final String nativeFontName,
--- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h	Fri May 03 14:59:32 2019 -0400
@@ -26,8 +26,6 @@
 #import <Cocoa/Cocoa.h>
 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
 
-#import "fontscalerdefs.h"
-
 #define MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE 256
 
 @interface AWTFont : NSObject {
@@ -35,7 +33,6 @@
     NSFont    *fFont;
     CGFontRef  fNativeCGFont;
     BOOL       fIsFakeItalic;
-    TTLayoutTableCache* layoutTableCache;
 }
 
 + (AWTFont *) awtFontForName:(NSString *)name
--- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m	Fri May 03 14:59:32 2019 -0400
@@ -42,33 +42,10 @@
     if (self) {
         fFont = [font retain];
         fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);
-        layoutTableCache = NULL;
     }
     return self;
 }
 
-static TTLayoutTableCache* newCFontLayoutTableCache() {
-  TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
-  if (ltc) {
-    int i;
-    for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
-      ltc->entries[i].len = -1;
-    }
-  }
-  return ltc;
-}
-
-static void freeCFontLayoutTableCache(TTLayoutTableCache* ltc) {
-  if (ltc) {
-    int i;
-    for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
-      if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);
-    }
-    if (ltc->kernPairs) free(ltc->kernPairs);
-    free(ltc);
-  }
-}
-
 - (void) dealloc {
     [fFont release];
     fFont = nil;
@@ -76,10 +53,6 @@
     if (fNativeCGFont) {
         CGFontRelease(fNativeCGFont);
     fNativeCGFont = NULL;
-    if (layoutTableCache != NULL) {
-        freeCFontLayoutTableCache(layoutTableCache);
-        layoutTableCache = NULL;
-    }
     }
 
     [super dealloc];
@@ -90,10 +63,6 @@
         CGFontRelease(fNativeCGFont);
     fNativeCGFont = NULL;
     }
-    if (layoutTableCache != NULL) {
-        freeCFontLayoutTableCache(layoutTableCache);
-        layoutTableCache = NULL;
-    }
     [super finalize];
 }
 
@@ -433,23 +402,6 @@
 
 /*
  * Class:     sun_font_CFont
- * Method:    getLayoutTableCacheNative
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_sun_font_CFont_getLayoutTableCacheNative
-    (JNIEnv *env, jclass clazz,
-     jlong awtFontPtr)
-{
-    AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
-    if (awtFont->layoutTableCache == NULL) {
-        awtFont->layoutTableCache = newCFontLayoutTableCache();
-    }
-    return (jlong)(awtFont->layoutTableCache);
-}
-
-/*
- * Class:     sun_font_CFont
  * Method:    getTableBytesNative
  * Signature: (JI)[B
  */
--- a/src/java.desktop/share/classes/sun/font/Font2D.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/Font2D.java	Fri May 03 14:59:32 2019 -0400
@@ -465,13 +465,6 @@
         return null;
     }
 
-    /* implemented for fonts backed by an sfnt that has
-     * OpenType or AAT layout tables.
-     */
-    protected long getLayoutTableCache() {
-        return 0L;
-    }
-
     /* Used only on OS X.
      */
     protected long getPlatformNativeFontPtr() {
--- a/src/java.desktop/share/classes/sun/font/FontScaler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/FontScaler.java	Fri May 03 14:59:32 2019 -0400
@@ -181,25 +181,6 @@
     abstract int getMissingGlyphCode() throws FontScalerException;
     abstract int getGlyphCode(char charCode) throws FontScalerException;
 
-    /* This method returns table cache used by native layout engine.
-     * This cache is essentially just small collection of
-     * pointers to various truetype tables. See definition of TTLayoutTableCache
-     * in the fontscalerdefs.h for more details.
-     *
-     * Note that tables themselves have same format as defined in the truetype
-     * specification, i.e. font scaler do not need to perform any preprocessing.
-     *
-     * Probably it is better to have API to request pointers to each table
-     * separately instead of requesting pointer to some native structure.
-     * (then there is not need to share its definition by different
-     * implementations of scaler).
-     * However, this means multiple JNI calls and potential impact on performance.
-     *
-     * Note: return value 0 is legal.
-     *   This means tables are not available (e.g. type1 font).
-     */
-    abstract long getLayoutTableCache() throws FontScalerException;
-
     /* Used by the OpenType engine for mark positioning. */
     abstract Point2D.Float getGlyphPoint(long pScalerContext,
                                 int glyphCode, int ptNumber)
--- a/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/FreetypeFontScaler.java	Fri May 03 14:59:32 2019 -0400
@@ -163,10 +163,6 @@
             .getNullScaler().getGlyphVectorOutline(0L, glyphs, numGlyphs, x, y);
     }
 
-    synchronized long getLayoutTableCache() throws FontScalerException {
-        return getLayoutTableCacheNative(nativeScaler);
-    }
-
     public synchronized void dispose() {
         if (nativeScaler != 0L) {
             disposeNativeScaler(font.get(), nativeScaler);
@@ -243,8 +239,6 @@
     native Point2D.Float getGlyphPointNative(Font2D font,
             long pScalerContext, long pScaler, int glyphCode, int ptNumber);
 
-    private native long getLayoutTableCacheNative(long pScaler);
-
     private native void disposeNativeScaler(Font2D font2D, long pScaler);
 
     private native int getGlyphCodeNative(Font2D font, long pScaler, char charCode);
--- a/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Fri May 03 14:59:32 2019 -0400
@@ -64,8 +64,6 @@
         return new GeneralPath();
     }
 
-    long getLayoutTableCache() {return 0L;}
-
     long createScalerContext(double[] matrix, int aa,
         int fm, float boldness, float italic, boolean disableHinting) {
         return getNullScalerContext();
--- a/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java	Fri May 03 14:59:32 2019 -0400
@@ -31,10 +31,12 @@
 package sun.font;
 
 import sun.font.GlyphLayout.*;
+import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
+
 import java.awt.geom.Point2D;
 import java.lang.ref.SoftReference;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.Locale;
 import java.util.WeakHashMap;
 
 /*
@@ -150,8 +152,10 @@
     }
 
     static WeakHashMap<Font2D, Boolean> aatInfo = new WeakHashMap<>();
+    private static final WeakHashMap<Font2D, FaceRef> facePtr =
+            new WeakHashMap<>();
 
-    private boolean isAAT(Font2D font) {
+    private static boolean isAAT(Font2D font) {
        Boolean aatObj;
        synchronized (aatInfo) {
            aatObj = aatInfo.get(font);
@@ -175,30 +179,67 @@
        return aat;
     }
 
+    private long getFacePtr(Font2D font2D) {
+        FaceRef ref;
+        synchronized (facePtr) {
+            ref = facePtr.computeIfAbsent(font2D, FaceRef::new);
+        }
+        return ref.getNativePtr();
+    }
+
     public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
                        int baseIndex, TextRecord tr, int typo_flags,
                        Point2D.Float pt, GVData data) {
         Font2D font = key.font();
         FontStrike strike = font.getStrike(desc);
-        long layoutTables = font.getLayoutTableCache();
         long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX
-        // pScaler probably not needed long term.
-        long pScaler = 0L;
-        if (font instanceof FileFont) {
-            pScaler = ((FileFont)font).getScaler().nativeScaler;
+        long pFace = getFacePtr(font);
+        if (pFace != 0) {
+            shape(font, strike, ptSize, mat, pNativeFont,
+                    pFace, isAAT(font),
+                    tr.text, data, key.script(),
+                    tr.start, tr.limit, baseIndex, pt,
+                    typo_flags, gmask);
         }
-        shape(font, strike, ptSize, mat, pScaler, pNativeFont,
-              layoutTables, isAAT(font),
-              tr.text, data, key.script(),
-              tr.start, tr.limit, baseIndex, pt,
-              typo_flags, gmask);
     }
 
     /* Native method to invoke harfbuzz layout engine */
     private static native boolean
         shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
-              long pscaler, long pNativeFont, long layoutTables, boolean aat,
+              long pNativeFont, long pFace, boolean aat,
               char[] chars, GVData data,
               int script, int offset, int limit,
               int baseIndex, Point2D.Float pt, int typo_flags, int slot);
+
+    private static native long createFace(Font2D font,
+                                          boolean aat,
+                                          long platformNativeFontPtr);
+
+    private static native void disposeFace(long facePtr);
+
+    private static class FaceRef implements DisposerRecord {
+        private Font2D font;
+        private Long facePtr;
+
+        private FaceRef(Font2D font) {
+            this.font = font;
+        }
+
+        private synchronized long getNativePtr() {
+            if (facePtr == null) {
+                facePtr = createFace(font, isAAT(font),
+                        font.getPlatformNativeFontPtr());
+                if (facePtr != 0) {
+                    Disposer.addObjectRecord(font, this);
+                }
+                font = null;
+            }
+            return facePtr;
+        }
+
+        @Override
+        public void dispose() {
+            disposeFace(facePtr);
+        }
+    }
 }
--- a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java	Fri May 03 14:59:32 2019 -0400
@@ -897,15 +897,6 @@
     }
 
     @Override
-    protected long getLayoutTableCache() {
-        try {
-          return getScaler().getLayoutTableCache();
-        } catch(FontScalerException fe) {
-            return 0L;
-        }
-    }
-
-    @Override
     protected byte[] getTableBytes(int tag) {
         ByteBuffer buffer = getTableBuffer(tag);
         if (buffer == null) {
--- a/src/java.desktop/share/native/common/font/fontscalerdefs.h	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/common/font/fontscalerdefs.h	Fri May 03 14:59:32 2019 -0400
@@ -88,32 +88,8 @@
    */
 #define INVISIBLE_GLYPHS 0xfffe
 
-#define GSUB_TAG 0x47535542 /* 'GSUB' */
-#define GPOS_TAG 0x47504F53 /* 'GPOS' */
-#define GDEF_TAG 0x47444546 /* 'GDEF' */
-#define HEAD_TAG 0x68656164 /* 'head' */
-#define MORT_TAG 0x6D6F7274 /* 'mort' */
-#define MORX_TAG 0x6D6F7278 /* 'morx' */
-#define KERN_TAG 0x6B65726E /* 'kern' */
-
-typedef struct TTLayoutTableCacheEntry {
-  const void* ptr;
-  int   len;
-  int   tag;
-} TTLayoutTableCacheEntry;
-
-#define LAYOUTCACHE_ENTRIES 7
-
-typedef struct TTLayoutTableCache {
-  TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
-  void* kernPairs;
-} TTLayoutTableCache;
-
 #include "sunfontids.h"
 
-JNIEXPORT extern TTLayoutTableCache* newLayoutTableCache();
-JNIEXPORT extern void freeLayoutTableCache(TTLayoutTableCache* ltc);
-
 /* If font is malformed then scaler context created by particular scaler
  * will be replaced by null scaler context.
  * Note that this context is not compatible with structure of the context
--- a/src/java.desktop/share/native/libfontmanager/HBShaper.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/libfontmanager/HBShaper.c	Fri May 03 14:59:32 2019 -0400
@@ -201,9 +201,7 @@
                        jobject font2D,
                        jobject fontStrike,
                        jfloat ptSize,
-                       jlong pScaler,
                        jlong pNativeFont,
-                       jlong layoutTables,
                        jfloatArray matrix,
                        jboolean aat) {
 
@@ -216,7 +214,6 @@
     fi->font2D = font2D;
     fi->fontStrike = fontStrike;
     fi->nativeFont = pNativeFont;
-    fi->layoutTables = (TTLayoutTableCache*)layoutTables;
     fi->aat = aat;
     (*env)->GetFloatArrayRegion(env, matrix, 0, 4, fi->matrix);
     fi->ptSize = ptSize;
@@ -241,9 +238,8 @@
      jobject fontStrike,
      jfloat ptSize,
      jfloatArray matrix,
-     jlong pScaler,
      jlong pNativeFont,
-     jlong layoutTables,
+     jlong pFace,
      jboolean aat,
      jcharArray text,
      jobject gvdata,
@@ -256,6 +252,7 @@
      jint slot) {
 
      hb_buffer_t *buffer;
+     hb_face_t* hbface;
      hb_font_t* hbfont;
      jchar  *chars;
      jsize len;
@@ -272,7 +269,7 @@
 
      JDKFontInfo *jdkFontInfo =
          createJDKFontInfo(env, font2D, fontStrike, ptSize,
-                           pScaler, pNativeFont, layoutTables, matrix, aat);
+                           pNativeFont, matrix, aat);
      if (!jdkFontInfo) {
         return JNI_FALSE;
      }
@@ -280,7 +277,8 @@
      jdkFontInfo->font2D = font2D;
      jdkFontInfo->fontStrike = fontStrike;
 
-     hbfont = hb_jdk_font_create(jdkFontInfo, NULL);
+     hbface = (hb_face_t*) jlong_to_ptr(pFace);
+     hbfont = hb_jdk_font_create(hbface, jdkFontInfo, NULL);
 
      buffer = hb_buffer_create();
      hb_buffer_set_script(buffer, getHBScriptCode(script));
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Fri May 03 14:59:32 2019 -0400
@@ -69,7 +69,6 @@
     unsigned fontDataOffset;
     unsigned fontDataLength;
     unsigned fileSize;
-    TTLayoutTableCache* layoutTables;
 } FTScalerInfo;
 
 typedef struct FTScalerContext {
@@ -251,7 +250,6 @@
     if (type == TYPE1_FROM_JAVA) { /* TYPE1 */
         scalerInfo->fontData = (unsigned char*) malloc(filesize);
         scalerInfo->directBuffer = NULL;
-        scalerInfo->layoutTables = NULL;
         scalerInfo->fontDataLength = filesize;
 
         if (scalerInfo->fontData != NULL) {
@@ -866,32 +864,6 @@
     return ptr_to_jlong(glyphInfo);
 }
 
-
-/*
- * Class:     sun_font_FreetypeFontScaler
- * Method:    getLayoutTableCacheNative
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_sun_font_FreetypeFontScaler_getLayoutTableCacheNative(
-        JNIEnv *env, jobject scaler, jlong pScaler) {
-    FTScalerInfo *scalerInfo = (FTScalerInfo*) jlong_to_ptr(pScaler);
-
-    if (scalerInfo == NULL) {
-        invalidateJavaScaler(env, scaler, scalerInfo);
-        return 0L;
-    }
-
-    // init layout table cache in font
-    // we're assuming the font is a file font and moreover it is Truetype font
-    // otherwise we shouldn't be able to get here...
-    if (scalerInfo->layoutTables == NULL) {
-        scalerInfo->layoutTables = newLayoutTableCache();
-    }
-
-    return ptr_to_jlong(scalerInfo->layoutTables);
-}
-
 /*
  * Class:     sun_font_FreetypeFontScaler
  * Method:    disposeNativeScaler
--- a/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Fri May 03 14:59:32 2019 -0400
@@ -23,6 +23,9 @@
  * questions.
  */
 
+#include "jlong.h"
+#include "sun_font_SunLayoutEngine.h"
+
 #include "hb.h"
 #include "hb-jdk.h"
 #ifdef MACOSX
@@ -304,79 +307,113 @@
 static void _free_nothing(void*) {
 }
 
+struct Font2DPtr {
+    JavaVM* vmPtr;
+    jweak font2DRef;
+};
+
+static void cleanupFontInfo(void* data) {
+  Font2DPtr* fontInfo;
+  JNIEnv* env;
+
+  fontInfo = (Font2DPtr*) data;
+  fontInfo->vmPtr->GetEnv((void**)&env, JNI_VERSION_1_1);
+  env->DeleteWeakGlobalRef(fontInfo->font2DRef);
+  free(data);
+}
+
 static hb_blob_t *
 reference_table(hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) {
 
-  JDKFontInfo *jdkFontInfo = (JDKFontInfo*)user_data;
-  JNIEnv* env = jdkFontInfo->env;
-  jobject font2D = jdkFontInfo->font2D;
-  jsize length = 0;
-  void* buffer = NULL;
-  int cacheIdx = 0;
+  Font2DPtr *fontInfo;
+  JNIEnv* env;
+  jobject font2D;
+  jsize length;
+  void* buffer;
 
   // HB_TAG_NONE is 0 and is used to get the whole font file.
   // It is not expected to be needed for JDK.
-  if (tag == 0 || jdkFontInfo->layoutTables == NULL) {
+  if (tag == 0) {
       return NULL;
   }
 
-  for (cacheIdx=0; cacheIdx<LAYOUTCACHE_ENTRIES; cacheIdx++) {
-    if (tag == jdkFontInfo->layoutTables->entries[cacheIdx].tag) break;
+  fontInfo = (Font2DPtr*)user_data;
+  fontInfo->vmPtr->GetEnv((void**)&env, JNI_VERSION_1_1);
+  if (env == NULL) {
+    return NULL;
   }
-
-  if (cacheIdx < LAYOUTCACHE_ENTRIES) { // if found
-      if (jdkFontInfo->layoutTables->entries[cacheIdx].len != -1) {
-          length = jdkFontInfo->layoutTables->entries[cacheIdx].len;
-          buffer = (void*)jdkFontInfo->layoutTables->entries[cacheIdx].ptr;
-      }
-  }
+  font2D = fontInfo->font2DRef;
 
-  if (buffer == NULL) {
-      jbyteArray tableBytes = (jbyteArray)
-         env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag);
-      if (tableBytes == NULL) {
-          return NULL;
-      }
-      length = env->GetArrayLength(tableBytes);
-      buffer = calloc(length, sizeof(jbyte));
-      env->GetByteArrayRegion(tableBytes, 0, length, (jbyte*)buffer);
-
-     if (cacheIdx >= LAYOUTCACHE_ENTRIES) { // not a cacheable table
-          return hb_blob_create((const char *)buffer, length,
-                                 HB_MEMORY_MODE_WRITABLE,
-                                 buffer, free);
-      } else {
-        jdkFontInfo->layoutTables->entries[cacheIdx].len = length;
-        jdkFontInfo->layoutTables->entries[cacheIdx].ptr = buffer;
-      }
+  jbyteArray tableBytes = (jbyteArray)
+     env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tag);
+  if (tableBytes == NULL) {
+      return NULL;
   }
+  length = env->GetArrayLength(tableBytes);
+  buffer = calloc(length, sizeof(jbyte));
+  env->GetByteArrayRegion(tableBytes, 0, length, (jbyte*)buffer);
 
   return hb_blob_create((const char *)buffer, length,
-                         HB_MEMORY_MODE_READONLY,
-                         NULL, _free_nothing);
+                         HB_MEMORY_MODE_WRITABLE,
+                         buffer, free);
 }
 
-
+extern "C" {
 
-hb_face_t*
-hb_jdk_face_create(JDKFontInfo *jdkFontInfo,
-                   hb_destroy_func_t destroy) {
-
-    hb_face_t *face =
-         hb_face_create_for_tables(reference_table, jdkFontInfo, destroy);
-
-    return face;
+/*
+ * Class:     sun_font_SunLayoutEngine
+ * Method:    createFace
+ * Signature: (Lsun/font/Font2D;ZJJ)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_font_SunLayoutEngine_createFace(JNIEnv *env,
+                         jclass cls,
+                         jobject font2D,
+                         jboolean aat,
+                         jlong platformFontPtr) {
+#ifdef MACOSX
+    if (aat && platformFontPtr) {
+        hb_face_t *face = hb_coretext_face_create((CGFontRef)platformFontPtr);
+        return ptr_to_jlong(face);
+    }
+#endif
+    Font2DPtr *fi = (Font2DPtr*)malloc(sizeof(Font2DPtr));
+    if (!fi) {
+        return 0;
+    }
+    JavaVM* vmPtr;
+    env->GetJavaVM(&vmPtr);
+    fi->vmPtr = vmPtr;
+    fi->font2DRef = env->NewWeakGlobalRef(font2D);
+    if (!fi->font2DRef) {
+        free(fi);
+        return 0;
+    }
+    hb_face_t *face = hb_face_create_for_tables(reference_table, fi,
+                                                cleanupFontInfo);
+    return ptr_to_jlong(face);
 }
 
-static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo,
+/*
+ * Class:     sun_font_SunLayoutEngine
+ * Method:    disposeFace
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_disposeFace(JNIEnv *env,
+                        jclass cls,
+                        jlong ptr) {
+    hb_face_t* face = (hb_face_t*) jlong_to_ptr(ptr);
+    hb_face_destroy(face);
+}
+
+} // extern "C"
+
+static hb_font_t* _hb_jdk_font_create(hb_face_t* face,
+                                      JDKFontInfo *jdkFontInfo,
                                       hb_destroy_func_t destroy) {
 
     hb_font_t *font;
-    hb_face_t *face;
 
-    face = hb_jdk_face_create(jdkFontInfo, destroy);
     font = hb_font_create(face);
-    hb_face_destroy (face);
     hb_font_set_funcs (font,
                        _hb_jdk_get_font_funcs (),
                        jdkFontInfo, (hb_destroy_func_t) _do_nothing);
@@ -387,17 +424,11 @@
 }
 
 #ifdef MACOSX
-static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) {
+static hb_font_t* _hb_jdk_ct_font_create(hb_face_t* face,
+                   JDKFontInfo *jdkFontInfo) {
 
     hb_font_t *font = NULL;
-    hb_face_t *face = NULL;
-    if (jdkFontInfo->nativeFont == 0) {
-        return NULL;
-    }
-    face = hb_coretext_face_create((CGFontRef)(jdkFontInfo->nativeFont));
     font = hb_font_create(face);
-    hb_face_destroy(face);
-
     hb_font_set_scale(font,
                      HBFloatToFixed(jdkFontInfo->ptSize),
                      HBFloatToFixed(jdkFontInfo->ptSize));
@@ -405,18 +436,13 @@
 }
 #endif
 
-hb_font_t* hb_jdk_font_create(JDKFontInfo *jdkFontInfo,
+hb_font_t* hb_jdk_font_create(hb_face_t* hbFace,
+                             JDKFontInfo *jdkFontInfo,
                              hb_destroy_func_t destroy) {
-
-   hb_font_t* font = NULL;
-
 #ifdef MACOSX
-     if (jdkFontInfo->aat) {
-         font = _hb_jdk_ct_font_create(jdkFontInfo);
+     if (jdkFontInfo->aat && jdkFontInfo->nativeFont) {
+         return _hb_jdk_ct_font_create(hbFace, jdkFontInfo);
      }
 #endif
-    if (font == NULL) {
-        font = _hb_jdk_font_create(jdkFontInfo, destroy);
-    }
-    return font;
+    return _hb_jdk_font_create(hbFace, jdkFontInfo, destroy);
 }
--- a/src/java.desktop/share/native/libfontmanager/hb-jdk.h	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/libfontmanager/hb-jdk.h	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,6 @@
 #include "hb.h"
 #include <jni.h>
 #include <sunfontids.h>
-#include <fontscalerdefs.h>
 
 # ifdef __cplusplus
 extern "C" {
@@ -40,7 +39,6 @@
     jobject font2D;
     jobject fontStrike;
     long nativeFont;
-    TTLayoutTableCache *layoutTables;
     float matrix[4];
     float ptSize;
     float xPtSize;
@@ -65,7 +63,8 @@
 hb_jdk_face_create(JDKFontInfo*   jdkFontInfo,
                    hb_destroy_func_t destroy);
 hb_font_t *
-hb_jdk_font_create(JDKFontInfo*   jdkFontInfo,
+hb_jdk_font_create(hb_face_t* hbFace,
+                   JDKFontInfo*   jdkFontInfo,
                    hb_destroy_func_t destroy);
 
 
--- a/src/java.desktop/share/native/libfontmanager/sunFont.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.desktop/share/native/libfontmanager/sunFont.c	Fri May 03 14:59:32 2019 -0400
@@ -344,32 +344,3 @@
 
     (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
 }
-
-JNIEXPORT TTLayoutTableCache* newLayoutTableCache() {
-  TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
-  if (ltc) {
-    int i;
-    for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
-      ltc->entries[i].len = -1;
-    }
-    ltc->entries[0].tag = GDEF_TAG;
-    ltc->entries[1].tag = GPOS_TAG;
-    ltc->entries[2].tag = GSUB_TAG;
-    ltc->entries[3].tag = HEAD_TAG;
-    ltc->entries[4].tag = KERN_TAG;
-    ltc->entries[5].tag = MORT_TAG;
-    ltc->entries[6].tag = MORX_TAG;
-  }
-  return ltc;
-}
-
-JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) {
-  if (ltc) {
-    int i;
-    for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
-      if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);
-    }
-    if (ltc->kernPairs) free(ltc->kernPairs);
-    free(ltc);
-  }
-}
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java	Fri May 03 14:59:32 2019 -0400
@@ -186,12 +186,16 @@
       *</pre></blockquote>
       */
     private int parseIntWithTag(int tag) throws DecodeException {
-
-
         if (parseByte() != tag) {
+            // Ber could have been reset;
+            String s;
+            if (offset > 0) {
+                s = Integer.toString(buf[offset - 1] & 0xff);
+            } else {
+                s = "Empty tag";
+            }
             throw new DecodeException("Encountered ASN.1 tag " +
-                Integer.toString(buf[offset - 1] & 0xff) +
-                " (expected tag " + Integer.toString(tag) + ")");
+                s + " (expected tag " + Integer.toString(tag) + ")");
         }
 
         int len = parseLength();
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java	Fri May 03 14:59:32 2019 -0400
@@ -408,65 +408,29 @@
     /**
      * Reads a reply; waits until one is ready.
      */
-    BerDecoder readReply(LdapRequest ldr)
-            throws IOException, NamingException {
+    BerDecoder readReply(LdapRequest ldr) throws IOException, NamingException {
         BerDecoder rber;
 
-        // Track down elapsed time to workaround spurious wakeups
-        long elapsedMilli = 0;
-        long elapsedNano = 0;
-
-        while (((rber = ldr.getReplyBer()) == null) &&
-                (readTimeout <= 0 || elapsedMilli < readTimeout))
-        {
-            try {
-                // If socket closed, don't even try
-                synchronized (this) {
-                    if (sock == null) {
-                        throw new ServiceUnavailableException(host + ":" + port +
-                            "; socket closed");
-                    }
-                }
-                synchronized (ldr) {
-                    // check if condition has changed since our last check
-                    rber = ldr.getReplyBer();
-                    if (rber == null) {
-                        if (readTimeout > 0) {  // Socket read timeout is specified
-                            long beginNano = System.nanoTime();
-
-                            // will be woken up before readTimeout if reply is
-                            // available
-                            ldr.wait(readTimeout - elapsedMilli);
-                            elapsedNano += (System.nanoTime() - beginNano);
-                            elapsedMilli += elapsedNano / 1000_000;
-                            elapsedNano %= 1000_000;
-
-                        } else {
-                            // no timeout is set so we wait infinitely until
-                            // a response is received
-                            // http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
-                            ldr.wait();
-                        }
-                    } else {
-                        break;
-                    }
-                }
-            } catch (InterruptedException ex) {
-                throw new InterruptedNamingException(
-                    "Interrupted during LDAP operation");
-            }
+        try {
+            // if no timeout is set so we wait infinitely until
+            // a response is received
+            // http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
+            rber = ldr.getReplyBer(readTimeout);
+        } catch (InterruptedException ex) {
+            throw new InterruptedNamingException(
+                "Interrupted during LDAP operation");
         }
 
-        if ((rber == null) && (elapsedMilli >= readTimeout)) {
+        if (rber == null) {
             abandonRequest(ldr, null);
-            throw new NamingException("LDAP response read timed out, timeout used:"
+            throw new NamingException(
+                    "LDAP response read timed out, timeout used:"
                             + readTimeout + "ms." );
 
         }
         return rber;
     }
 
-
     ////////////////////////////////////////////////////////////////////////////
     //
     // Methods to add, find, delete, and abandon requests made to server
@@ -660,14 +624,11 @@
             if (nparent) {
                 LdapRequest ldr = pendingRequests;
                 while (ldr != null) {
-
-                    synchronized (ldr) {
-                        ldr.notify();
+                    ldr.close();
                         ldr = ldr.next;
                     }
                 }
             }
-        }
         if (nparent) {
             parent.processConnectionClosure();
         }
@@ -755,7 +716,7 @@
      * the safest thing to do is to shut it down.
      */
 
-    private Object pauseLock = new Object();  // lock for reader to wait on while paused
+    private final Object pauseLock = new Object();  // lock for reader to wait on while paused
     private boolean paused = false;           // paused state of reader
 
     /*
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapRequest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapRequest.java	Fri May 03 14:59:32 2019 -0400
@@ -29,55 +29,52 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import javax.naming.CommunicationException;
+import java.util.concurrent.TimeUnit;
 
 final class LdapRequest {
 
+    private final static BerDecoder EOF = new BerDecoder(new byte[]{}, -1, 0);
+
     LdapRequest next;   // Set/read in synchronized Connection methods
-    int msgId;          // read-only
+    final int msgId;          // read-only
 
-    private int gotten = 0;
-    private BlockingQueue<BerDecoder> replies;
-    private int highWatermark = -1;
-    private boolean cancelled = false;
-    private boolean pauseAfterReceipt = false;
-    private boolean completed = false;
-
-    LdapRequest(int msgId, boolean pause) {
-        this(msgId, pause, -1);
-    }
+    private final BlockingQueue<BerDecoder> replies;
+    private volatile boolean cancelled;
+    private volatile boolean closed;
+    private volatile boolean completed;
+    private final boolean pauseAfterReceipt;
 
     LdapRequest(int msgId, boolean pause, int replyQueueCapacity) {
         this.msgId = msgId;
         this.pauseAfterReceipt = pause;
         if (replyQueueCapacity == -1) {
-            this.replies = new LinkedBlockingQueue<BerDecoder>();
+            this.replies = new LinkedBlockingQueue<>();
         } else {
-            this.replies =
-                new LinkedBlockingQueue<BerDecoder>(replyQueueCapacity);
-            highWatermark = (replyQueueCapacity * 80) / 100; // 80% capacity
+            this.replies = new LinkedBlockingQueue<>(8 * replyQueueCapacity / 10);
         }
     }
 
-    synchronized void cancel() {
+    void cancel() {
         cancelled = true;
+        replies.offer(EOF);
+    }
 
-        // Unblock reader of pending request
-        // Should only ever have at most one waiter
-        notify();
+    synchronized void close() {
+        closed = true;
+        replies.offer(EOF);
+    }
+
+    private boolean isClosed() {
+        return closed && (replies.size() == 0 || replies.peek() == EOF);
     }
 
     synchronized boolean addReplyBer(BerDecoder ber) {
-        if (cancelled) {
+        // check the closed boolean value here as we don't want anything
+        // to be added to the queue after close() has been called.
+        if (cancelled || closed) {
             return false;
         }
 
-        // Add a new reply to the queue of unprocessed replies.
-        try {
-            replies.put(ber);
-        } catch (InterruptedException e) {
-            // ignore
-        }
-
         // peek at the BER buffer to check if it is a SearchResultDone PDU
         try {
             ber.parseSeq(null);
@@ -88,33 +85,38 @@
         }
         ber.reset();
 
-        notify(); // notify anyone waiting for reply
-        /*
-         * If a queue capacity has been set then trigger a pause when the
-         * queue has filled to 80% capacity. Later, when the queue has drained
-         * then the reader gets unpaused.
-         */
-        if (highWatermark != -1 && replies.size() >= highWatermark) {
-            return true; // trigger the pause
+        // Add a new reply to the queue of unprocessed replies.
+        try {
+            replies.put(ber);
+        } catch (InterruptedException e) {
+            // ignore
         }
+
         return pauseAfterReceipt;
     }
 
-    synchronized BerDecoder getReplyBer() throws CommunicationException {
+    BerDecoder getReplyBer(long millis) throws CommunicationException,
+                                               InterruptedException {
+        if (cancelled) {
+            throw new CommunicationException("Request: " + msgId +
+                " cancelled");
+        }
+        if (isClosed()) {
+            return null;
+        }
+
+        BerDecoder result = millis > 0 ?
+                replies.poll(millis, TimeUnit.MILLISECONDS) : replies.take();
+
         if (cancelled) {
             throw new CommunicationException("Request: " + msgId +
                 " cancelled");
         }
 
-        /*
-         * Remove a reply if the queue is not empty.
-         * poll returns null if queue is empty.
-         */
-        BerDecoder reply = replies.poll();
-        return reply;
+        return result == EOF ? null : result;
     }
 
-    synchronized boolean hasSearchCompleted() {
+    boolean hasSearchCompleted() {
         return completed;
     }
 }
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,20 +20,17 @@
 
 package com.sun.org.apache.xalan.internal.xsltc.dom;
 
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.xsltc.CollatorFactory;
 import com.sun.org.apache.xalan.internal.xsltc.DOM;
 import com.sun.org.apache.xalan.internal.xsltc.TransletException;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 import com.sun.org.apache.xml.internal.utils.StringComparable;
 import java.text.Collator;
 import java.util.Locale;
-import jdk.xml.internal.SecuritySupport;
 
 /**
  * Base class for sort records containing application specific sort keys
  *
- * @LastModified: Oct 2017
+ * @LastModified: May 2019
  */
 public abstract class NodeSortRecord {
     public static final int COMPARE_STRING     = 0;
@@ -68,8 +65,6 @@
     @Deprecated
     protected Locale _locale;
 
-    protected CollatorFactory _collatorFactory;
-
     protected SortSettings _settings;
 
     private DOM    _dom = null;
@@ -109,33 +104,8 @@
         int levels = settings.getSortOrders().length;
         _values = new Object[levels];
 
-        String colFactClassname = null;
-        try {
-            // -- W. Eliot Kimber (eliot@isogen.com)
-            colFactClassname =
-                SecuritySupport.getSystemProperty("com.sun.org.apache.xalan.internal.xsltc.COLLATOR_FACTORY");
-        }
-        catch (SecurityException e) {
-            // If we can't read the propery, just use default collator
-        }
-
-        if (colFactClassname != null) {
-            try {
-                Object candObj = ObjectFactory.findProviderClass(colFactClassname, true);
-                _collatorFactory = (CollatorFactory)candObj;
-            } catch (ClassNotFoundException e) {
-                throw new TransletException(e);
-            }
-            Locale[] locales = settings.getLocales();
-            _collators = new Collator[levels];
-            for (int i = 0; i < levels; i++){
-                _collators[i] = _collatorFactory.getCollator(locales[i]);
-            }
-            _collator = _collators[0];
-        } else {
-            _collators = settings.getCollators();
-            _collator = _collators[0];
-        }
+        _collators = settings.getCollators();
+        _collator = _collators[0];
     }
 
     /**
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AttrImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AttrImpl.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -110,6 +110,7 @@
  * @author Joe Kesselman, IBM
  * @author Andy Clark, IBM
  * @since PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  *
  */
 public class AttrImpl
@@ -140,8 +141,6 @@
     // REVISIT: we are losing the type information in DOM during serialization
     transient Object type;
 
-    protected TextImpl textNode = null;
-
     //
     // Constructors
     //
@@ -192,14 +191,14 @@
      * NON-DOM
      * set the ownerDocument of this node and its children
      */
-    void setOwnerDocument(CoreDocumentImpl doc) {
+    protected void setOwnerDocument(CoreDocumentImpl doc) {
         if (needsSyncChildren()) {
             synchronizeChildren();
         }
         super.setOwnerDocument(doc);
         if (!hasStringValue()) {
             for (ChildNode child = (ChildNode) value;
-                 child != null; child = child.nextSibling) {
+                child != null; child = child.nextSibling) {
                 child.setOwnerDocument(doc);
             }
         }
@@ -349,6 +348,8 @@
 
         Element ownerElement = getOwnerElement();
         String oldvalue = "";
+        TextImpl textNode = null;
+
         if (needsSyncData()) {
             synchronizeData();
         }
@@ -363,13 +364,7 @@
                     oldvalue = (String) value;
                     // create an actual text node as our child so
                     // that we can use it in the event
-                    if (textNode == null) {
-                        textNode = (TextImpl)
-                            ownerDocument.createTextNode((String) value);
-                    }
-                    else {
-                        textNode.data = (String) value;
-                    }
+                    textNode = (TextImpl) ownerDocument.createTextNode((String) value);
                     value = textNode;
                     textNode.isFirstChild(true);
                     textNode.previousSibling = textNode;
@@ -414,9 +409,16 @@
         // since we need to combine the remove and insert.
         isSpecified(true);
         if (ownerDocument.getMutationEvents()) {
-            // if there are any event handlers create a real node
-            internalInsertBefore(ownerDocument.createTextNode(newvalue),
-                                 null, true);
+            // if there are any event handlers create a real node or
+            // reuse the one we synthesized for the remove notifications
+            // if it exists.
+            if (textNode == null) {
+                textNode = (TextImpl) ownerDocument.createTextNode(newvalue);
+            }
+            else {
+                textNode.data = newvalue;
+            }
+            internalInsertBefore(textNode, null, true);
             hasStringValue(false);
             // notify document
             ownerDocument.modifiedAttrValue(this, oldvalue);
@@ -1034,7 +1036,7 @@
      * NodeList method: Return the Nth immediate child of this node, or
      * null if the index is out of bounds.
      * @return org.w3c.dom.Node
-     * @param Index int
+     * @param index int
      */
     public Node item(int index) {
 
@@ -1076,12 +1078,12 @@
      * Checks if a type is derived from another by restriction. See:
      * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
      *
-     * @param ancestorNS
+     * @param typeNamespaceArg
      *        The namspace of the ancestor type declaration
-     * @param ancestorName
+     * @param typeNameArg
      *        The name of the ancestor type declaration
-     * @param type
-     *        The reference type definition
+     * @param derivationMethod
+     *        The derivation method
      *
      * @return boolean True if the type is derived by restriciton for the
      *         reference type
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AttrNSImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AttrNSImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -147,30 +147,6 @@
         setName(namespaceURI, qualifiedName);
     }
 
-    /**
-     * NON-DOM: resets this node and sets specified values for the node
-     *
-     * @param ownerDocument
-     * @param namespaceURI
-     * @param qualifiedName
-     * @param localName
-     */
-    public void setValues (CoreDocumentImpl ownerDocument,
-                         String namespaceURI,
-                         String qualifiedName,
-                         String localName){
-
-        super.textNode = null;
-        super.flags = 0;
-        isSpecified(true);
-        hasStringValue(true);
-        super.setOwnerDocument(ownerDocument);
-        this.localName = localName;
-        this.namespaceURI = namespaceURI;
-        super.name = qualifiedName;
-        super.value = null;
-    }
-
     //
     // DOM2: Namespace methods
     //
@@ -314,14 +290,14 @@
      * Checks if a type is derived from another by restriction. See:
      * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
      *
-     * @param ancestorNS
+     * @param typeNamespaceArg
      *        The namspace of the ancestor type declaration
-     * @param ancestorName
+     * @param typeNameArg
      *        The name of the ancestor type declaration
-     * @param type
-     *        The reference type definition
+     * @param derivationMethod
+     *        The derivation method
      *
-     * @return boolean True if the type is derived by restriciton for the
+     * @return boolean True if the type is derived by restriction for the
      *         reference type
      */
     public boolean isDerivedFrom(String typeNamespaceArg,
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ChildNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ChildNode.java	Fri May 03 14:59:32 2019 -0400
@@ -40,8 +40,6 @@
     /** Serialization version. */
     static final long serialVersionUID = -6112455738802414002L;
 
-    transient StringBuffer fBufferStr = null;
-
     //
     // Data
     //
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,11 +20,18 @@
 package com.sun.org.apache.xerces.internal.dom;
 
 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
+import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDProcessor;
+import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDValidator;
+import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
+import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
+import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
 import com.sun.org.apache.xerces.internal.parsers.DOMParserImpl;
 import com.sun.org.apache.xerces.internal.parsers.DTDConfiguration;
 import com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration;
+import com.sun.org.apache.xerces.internal.parsers.XML11DTDConfiguration;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
+import java.lang.ref.SoftReference;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.DOMImplementation;
 import org.w3c.dom.Document;
@@ -51,21 +58,39 @@
  * @xerces.internal
  *
  * @since PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  */
+@SuppressWarnings({"rawtypes", "unchecked"}) //SoftReference array
 public class CoreDOMImplementationImpl
         implements DOMImplementation, DOMImplementationLS {
-        //
-        // Data
-        //
 
-    // validators pool
+    //
+    // Data
+    //
+
+    // validator pools
     private static final int SIZE = 2;
-    private RevalidationHandler validators[] = new RevalidationHandler[SIZE];
+
+    private SoftReference schemaValidators[] = new SoftReference[SIZE];
+    private SoftReference xml10DTDValidators[] = new SoftReference[SIZE];
+    private SoftReference xml11DTDValidators[] = new SoftReference[SIZE];
+
+    private int freeSchemaValidatorIndex = -1;
+    private int freeXML10DTDValidatorIndex = -1;
+    private int freeXML11DTDValidatorIndex = -1;
 
-    private RevalidationHandler dtdValidators[] = new RevalidationHandler[SIZE];
-    private int freeValidatorIndex = -1;
-    private int freeDTDValidatorIndex = -1;
-    private int currentSize = SIZE;
+    private int schemaValidatorsCurrentSize = SIZE;
+    private int xml10DTDValidatorsCurrentSize = SIZE;
+    private int xml11DTDValidatorsCurrentSize = SIZE;
+
+    private SoftReference xml10DTDLoaders[] = new SoftReference[SIZE];
+    private SoftReference xml11DTDLoaders[] = new SoftReference[SIZE];
+
+    private int freeXML10DTDLoaderIndex = -1;
+    private int freeXML11DTDLoaderIndex = -1;
+
+    private int xml10DTDLoaderCurrentSize = SIZE;
+    private int xml11DTDLoaderCurrentSize = SIZE;
 
     // Document and doctype counter.  Used to assign order to documents and
     // doctypes without owners, on an demand basis.   Used for
@@ -74,8 +99,8 @@
 
         // static
         /** Dom implementation singleton. */
-        static CoreDOMImplementationImpl singleton =
-                new CoreDOMImplementationImpl();
+        static final CoreDOMImplementationImpl singleton = new CoreDOMImplementationImpl();
+
         //
         // Public methods
         //
@@ -109,21 +134,25 @@
                 feature = feature.substring(1);
             }
             return (feature.equalsIgnoreCase("Core")
-                        && (anyVersion
-                            || version.equals("1.0")
-                            || version.equals("2.0")
-                            || version.equals("3.0")))
-                    || (feature.equalsIgnoreCase("XML")
-                        && (anyVersion
-                            || version.equals("1.0")
-                            || version.equals("2.0")
-                            || version.equals("3.0")))
-                    || (feature.equalsIgnoreCase("LS")
-                        && (anyVersion
-                            || version.equals("3.0")))
-                    || (feature.equalsIgnoreCase("ElementTraversal")
-                        && (anyVersion
-                            || version.equals("1.0")));
+                    && (anyVersion
+                        || version.equals("1.0")
+                        || version.equals("2.0")
+                        || version.equals("3.0")))
+                        || (feature.equalsIgnoreCase("XML")
+                    && (anyVersion
+                        || version.equals("1.0")
+                        || version.equals("2.0")
+                        || version.equals("3.0")))
+                        || (feature.equalsIgnoreCase("XMLVersion")
+                    && (anyVersion
+                        || version.equals("1.0")
+                        || version.equals("1.1")))
+                        || (feature.equalsIgnoreCase("LS")
+                    && (anyVersion
+                        || version.equals("3.0")))
+                        || (feature.equalsIgnoreCase("ElementTraversal")
+                    && (anyVersion
+                        || version.equals("1.0")));
         } // hasFeature(String,String):boolean
 
 
@@ -244,19 +273,26 @@
                                         null);
                         throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
                 }
-                CoreDocumentImpl doc = new CoreDocumentImpl(doctype);
-                Element e = doc.createElementNS(namespaceURI, qualifiedName);
-                doc.appendChild(e);
+                CoreDocumentImpl doc = createDocument(doctype);
+                // If namespaceURI and qualifiedName are null return a Document with no document element.
+                if (qualifiedName != null || namespaceURI != null) {
+                    Element e = doc.createElementNS(namespaceURI, qualifiedName);
+                    doc.appendChild(e);
+                }
                 return doc;
         }
 
+        protected CoreDocumentImpl createDocument(DocumentType doctype) {
+            return new CoreDocumentImpl(doctype);
+        }
+
         /**
          * DOM Level 3 WD - Experimental.
          */
         public Object getFeature(String feature, String version) {
             if (singleton.hasFeature(feature, version)) {
-                return singleton;
-            }
+                    return singleton;
+                }
             return null;
         }
 
@@ -304,7 +340,7 @@
      *    NOT_SUPPORTED_ERR: Raised if the requested mode or schema type is
      *   not supported.
          */
-        public LSParser createLSParser(short mode, String schemaType)
+    public LSParser createLSParser(short mode, String schemaType)
                 throws DOMException {
                 if (mode != DOMImplementationLS.MODE_SYNCHRONOUS || (schemaType !=null &&
                    !"http://www.w3.org/2001/XMLSchema".equals(schemaType) &&
@@ -318,7 +354,7 @@
                 }
                 if (schemaType != null
                         && schemaType.equals("http://www.w3.org/TR/REC-xml")) {
-                        return new DOMParserImpl(new DTDConfiguration(),
+                        return new DOMParserImpl(new XML11DTDConfiguration(),
                                 schemaType);
                 }
                 else {
@@ -328,20 +364,20 @@
                 }
         }
 
-        /**
-         * DOM Level 3 LS CR - Experimental.
-         * Create a new <code>LSSerializer</code> object.
-         * @return The newly created <code>LSSerializer</code> object.
-         * <p ><b>Note:</b>    By default, the newly created
-         * <code>LSSerializer</code> has no <code>DOMErrorHandler</code>,
-         * i.e. the value of the <code>"error-handler"</code> configuration
-         * parameter is <code>null</code>. However, implementations may
-         * provide a default error handler at creation time. In that case, the
-         * initial value of the <code>"error-handler"</code> configuration
-         * parameter on the new created <code>LSSerializer</code> contains a
-         * reference to the default error handler.
-         */
-        public LSSerializer createLSSerializer() {
+    /**
+     * DOM Level 3 LS CR - Experimental.
+     * Create a new <code>LSSerializer</code> object.
+     * @return The newly created <code>LSSerializer</code> object.
+     * <p ><b>Note:</b>    By default, the newly created
+     * <code>LSSerializer</code> has no <code>DOMErrorHandler</code>,
+     * i.e. the value of the <code>"error-handler"</code> configuration
+     * parameter is <code>null</code>. However, implementations may
+     * provide a default error handler at creation time. In that case, the
+     * initial value of the <code>"error-handler"</code> configuration
+     * parameter on the new created <code>LSSerializer</code> contains a
+     * reference to the default error handler.
+     */
+    public LSSerializer createLSSerializer() {
             return new com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl();
         }
 
@@ -358,68 +394,217 @@
         // Protected methods
         //
         /** NON-DOM: retrieve validator. */
-        synchronized RevalidationHandler getValidator(String schemaType) {
-                // REVISIT: implement retrieving DTD validator
+        synchronized RevalidationHandler getValidator(String schemaType, String xmlVersion) {
         if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
             // create new validator - we should not attempt
             // to restrict the number of validation handlers being
             // requested
-            if(freeValidatorIndex < 0) {
-                return new com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator();
+            while (freeSchemaValidatorIndex >= 0) {
+                // return first available validator
+                SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
+                RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                if (holder != null && holder.handler != null) {
+                    RevalidationHandler val = holder.handler;
+                    holder.handler = null;
+                    --freeSchemaValidatorIndex;
+                    return val;
+                }
+                schemaValidators[freeSchemaValidatorIndex--] = null;
             }
-            // return first available validator
-            RevalidationHandler val = validators[freeValidatorIndex];
-            validators[freeValidatorIndex--] = null;
-            return val;
+            return new XMLSchemaValidator();
         }
         else if(schemaType == XMLGrammarDescription.XML_DTD) {
-            if(freeDTDValidatorIndex < 0) {
-                return new com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator();
+            // return an instance of XML11DTDValidator
+            if ("1.1".equals(xmlVersion)) {
+                while (freeXML11DTDValidatorIndex >= 0) {
+                    // return first available validator
+                    SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
+                    RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                    if (holder != null && holder.handler != null) {
+                        RevalidationHandler val = holder.handler;
+                        holder.handler = null;
+                        --freeXML11DTDValidatorIndex;
+                        return val;
+                    }
+                    xml11DTDValidators[freeXML11DTDValidatorIndex--] = null;
+                }
+                return new XML11DTDValidator();
             }
-            // return first available validator
-            RevalidationHandler val = dtdValidators[freeDTDValidatorIndex];
-            dtdValidators[freeDTDValidatorIndex--] = null;
-            return val;
+            // return an instance of XMLDTDValidator
+            else {
+                while (freeXML10DTDValidatorIndex >= 0) {
+                    // return first available validator
+                    SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
+                    RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                    if (holder != null && holder.handler != null) {
+                        RevalidationHandler val = holder.handler;
+                        holder.handler = null;
+                        --freeXML10DTDValidatorIndex;
+                        return val;
+                    }
+                    xml10DTDValidators[freeXML10DTDValidatorIndex--] = null;
+                }
+                return new XMLDTDValidator();
+            }
         }
         return null;
         }
 
         /** NON-DOM: release validator */
-        synchronized void releaseValidator(String schemaType,
-                                         RevalidationHandler validator) {
-       // REVISIT: implement support for DTD validators as well
-       if(schemaType == XMLGrammarDescription.XML_SCHEMA) {
-           ++freeValidatorIndex;
-           if (validators.length == freeValidatorIndex ){
-                // resize size of the validators
-                currentSize+=SIZE;
-                RevalidationHandler newarray[] =  new RevalidationHandler[currentSize];
-                System.arraycopy(validators, 0, newarray, 0, validators.length);
-                validators = newarray;
-           }
-           validators[freeValidatorIndex]=validator;
-       }
-       else if(schemaType == XMLGrammarDescription.XML_DTD) {
-           ++freeDTDValidatorIndex;
-           if (dtdValidators.length == freeDTDValidatorIndex ){
-                // resize size of the validators
-                currentSize+=SIZE;
-                RevalidationHandler newarray[] =  new RevalidationHandler[currentSize];
-                System.arraycopy(dtdValidators, 0, newarray, 0, dtdValidators.length);
-                dtdValidators = newarray;
-           }
-           dtdValidators[freeDTDValidatorIndex]=validator;
-       }
+        synchronized void releaseValidator(String schemaType, String xmlVersion,
+                RevalidationHandler validator) {
+            if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
+                ++freeSchemaValidatorIndex;
+                if (schemaValidators.length == freeSchemaValidatorIndex) {
+                    // resize size of the validators
+                    schemaValidatorsCurrentSize += SIZE;
+                    SoftReference newarray[] =  new SoftReference[schemaValidatorsCurrentSize];
+                    System.arraycopy(schemaValidators, 0, newarray, 0, schemaValidators.length);
+                    schemaValidators = newarray;
+                }
+                SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
+                if (ref != null) {
+                    RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                    if (holder != null) {
+                        holder.handler = validator;
+                        return;
+                    }
+                }
+                schemaValidators[freeSchemaValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+            }
+            else if (schemaType == XMLGrammarDescription.XML_DTD) {
+                // release an instance of XML11DTDValidator
+                if ("1.1".equals(xmlVersion)) {
+                    ++freeXML11DTDValidatorIndex;
+                    if (xml11DTDValidators.length == freeXML11DTDValidatorIndex) {
+                        // resize size of the validators
+                        xml11DTDValidatorsCurrentSize += SIZE;
+                        SoftReference [] newarray = new SoftReference[xml11DTDValidatorsCurrentSize];
+                        System.arraycopy(xml11DTDValidators, 0, newarray, 0, xml11DTDValidators.length);
+                        xml11DTDValidators = newarray;
+                    }
+                    SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
+                    if (ref != null) {
+                        RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                        if (holder != null) {
+                            holder.handler = validator;
+                            return;
+                        }
+                    }
+                    xml11DTDValidators[freeXML11DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+                }
+                // release an instance of XMLDTDValidator
+                else {
+                    ++freeXML10DTDValidatorIndex;
+                    if (xml10DTDValidators.length == freeXML10DTDValidatorIndex) {
+                        // resize size of the validators
+                        xml10DTDValidatorsCurrentSize += SIZE;
+                        SoftReference [] newarray = new SoftReference[xml10DTDValidatorsCurrentSize];
+                        System.arraycopy(xml10DTDValidators, 0, newarray, 0, xml10DTDValidators.length);
+                        xml10DTDValidators = newarray;
+                    }
+                    SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
+                    if (ref != null) {
+                        RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+                        if (holder != null) {
+                            holder.handler = validator;
+                            return;
+                        }
+                    }
+                    xml10DTDValidators[freeXML10DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+                }
+            }
         }
 
-       /** NON-DOM:  increment document/doctype counter */
-       protected synchronized int assignDocumentNumber() {
-            return ++docAndDoctypeCounter;
-       }
-       /** NON-DOM:  increment document/doctype counter */
-       protected synchronized int assignDocTypeNumber() {
-            return ++docAndDoctypeCounter;
-       }
+    /** NON-DOM: retrieve DTD loader */
+    synchronized final XMLDTDLoader getDTDLoader(String xmlVersion) {
+        // return an instance of XML11DTDProcessor
+        if ("1.1".equals(xmlVersion)) {
+            while (freeXML11DTDLoaderIndex >= 0) {
+                // return first available DTD loader
+                SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
+                XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+                if (holder != null && holder.loader != null) {
+                    XMLDTDLoader val = holder.loader;
+                    holder.loader = null;
+                    --freeXML11DTDLoaderIndex;
+                    return val;
+                }
+                xml11DTDLoaders[freeXML11DTDLoaderIndex--] = null;
+            }
+            return new XML11DTDProcessor();
+        }
+        // return an instance of XMLDTDLoader
+        else {
+            while (freeXML10DTDLoaderIndex >= 0) {
+                // return first available DTD loader
+                SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
+                XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+                if (holder != null && holder.loader != null) {
+                    XMLDTDLoader val = holder.loader;
+                    holder.loader = null;
+                    --freeXML10DTDLoaderIndex;
+                    return val;
+                }
+                xml10DTDLoaders[freeXML10DTDLoaderIndex--] = null;
+            }
+            return new XMLDTDLoader();
+        }
+    }
+
+    /** NON-DOM: release DTD loader */
+    synchronized final void releaseDTDLoader(String xmlVersion, XMLDTDLoader loader) {
+        // release an instance of XMLDTDLoader
+        if ("1.1".equals(xmlVersion)) {
+            ++freeXML11DTDLoaderIndex;
+            if (xml11DTDLoaders.length == freeXML11DTDLoaderIndex) {
+                // resize size of the DTD loaders
+                xml11DTDLoaderCurrentSize += SIZE;
+                SoftReference [] newarray = new SoftReference[xml11DTDLoaderCurrentSize];
+                System.arraycopy(xml11DTDLoaders, 0, newarray, 0, xml11DTDLoaders.length);
+                xml11DTDLoaders = newarray;
+            }
+            SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
+            if (ref != null) {
+                XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+                if (holder != null) {
+                    holder.loader = loader;
+                    return;
+                }
+            }
+            xml11DTDLoaders[freeXML11DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
+        }
+        // release an instance of XMLDTDLoader
+        else {
+            ++freeXML10DTDLoaderIndex;
+            if (xml10DTDLoaders.length == freeXML10DTDLoaderIndex) {
+                // resize size of the DTD loaders
+                xml10DTDLoaderCurrentSize += SIZE;
+                SoftReference [] newarray = new SoftReference[xml10DTDLoaderCurrentSize];
+                System.arraycopy(xml10DTDLoaders, 0, newarray, 0, xml10DTDLoaders.length);
+                xml10DTDLoaders = newarray;
+            }
+            SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
+            if (ref != null) {
+                XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+                if (holder != null) {
+                    holder.loader = loader;
+                    return;
+                }
+            }
+            xml10DTDLoaders[freeXML10DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
+        }
+    }
+
+    /** NON-DOM:  increment document/doctype counter */
+    protected synchronized int assignDocumentNumber() {
+        return ++docAndDoctypeCounter;
+    }
+
+    /** NON-DOM:  increment document/doctype counter */
+    protected synchronized int assignDocTypeNumber() {
+        return ++docAndDoctypeCounter;
+    }
 
     /* DOM Level 3 LS CR - Experimental.
      *
@@ -427,11 +612,33 @@
      * <code>LSOutput.characterStream</code>,
      * <code>LSOutput.byteStream</code>, <code>LSOutput.systemId</code>,
      * <code>LSOutput.encoding</code> are null.
+     * @return  The newly created output object.
+    */
+    public LSOutput createLSOutput() {
+        return new DOMOutputImpl();
+    }
 
-     * @return  The newly created output object.
+    /**
+     * A holder for RevalidationHandlers. This allows us to reuse
+     * SoftReferences which haven't yet been cleared by the garbage
+     * collector.
      */
-       public LSOutput createLSOutput() {
-           return new DOMOutputImpl();
-       }
+    static final class RevalidationHandlerHolder {
+        RevalidationHandlerHolder(RevalidationHandler handler) {
+            this.handler = handler;
+        }
+        RevalidationHandler handler;
+    }
+
+    /**
+     * A holder for XMLDTDLoaders. This allows us to reuse SoftReferences
+     * which haven't yet been cleared by the garbage collector.
+     */
+    static final class XMLDTDLoaderHolder {
+        XMLDTDLoaderHolder(XMLDTDLoader loader) {
+            this.loader = loader;
+        }
+        XMLDTDLoader loader;
+    }
 
 } // class DOMImplementationImpl
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMConfigurationImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -32,7 +32,6 @@
 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
 import com.sun.org.apache.xerces.internal.util.PropertyState;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
-import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
@@ -52,6 +51,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.StringTokenizer;
 import javax.xml.XMLConstants;
 import javax.xml.catalog.CatalogFeatures;
 import jdk.xml.internal.JdkXmlUtils;
@@ -70,7 +70,7 @@
  *
  * @author Elena Litani, IBM
  * @author Neeraj Bajaj, Sun Microsystems.
- * @LastModified: Oct 2017
+ * @LastModified: Apr 2019
  */
 public class DOMConfigurationImpl extends ParserConfigurationSettings
     implements XMLParserConfiguration, DOMConfiguration {
@@ -79,6 +79,9 @@
     // Constants
     //
 
+    protected static final String XML11_DATATYPE_VALIDATOR_FACTORY =
+        "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
+
     // feature identifiers
 
     /** Feature identifier: validation. */
@@ -101,12 +104,41 @@
     protected static final String NORMALIZE_DATA =
         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
 
+    /** Feature identifier: send element default value via characters() */
+    protected static final String SCHEMA_ELEMENT_DEFAULT =
+        Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
+
     /** sending psvi in the pipeline */
     protected static final String SEND_PSVI =
         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
 
-    protected final static String DTD_VALIDATOR_FACTORY_PROPERTY =
-        Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
+    /** Feature: generate synthetic annotations */
+    protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
+        Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
+
+    /** Feature identifier: validate annotations */
+    protected static final String VALIDATE_ANNOTATIONS =
+        Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
+
+    /** Feature identifier: honour all schemaLocations */
+    protected static final String HONOUR_ALL_SCHEMALOCATIONS =
+        Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
+
+    /** Feature identifier: use grammar pool only */
+    protected static final String USE_GRAMMAR_POOL_ONLY =
+        Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
+
+    /** Feature identifier: load external DTD. */
+    protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
+        Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
+
+    /** Feature identifier: balance syntax trees. */
+    protected static final String BALANCE_SYNTAX_TREES =
+        Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
+
+    /** Feature identifier: warn on duplicate attribute definition. */
+    protected static final String WARN_ON_DUPLICATE_ATTDEF =
+        Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
 
     /** Feature identifier: namespace growth */
     protected static final String NAMESPACE_GROWTH =
@@ -133,9 +165,9 @@
     protected static final String SYMBOL_TABLE =
         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 
-    /** Property id: Grammar pool*/
+    /** Property id: Grammar pool. */
     protected static final String GRAMMAR_POOL =
-    Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+        Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 
     /** Property identifier: error handler. */
     protected static final String ERROR_HANDLER =
@@ -147,15 +179,31 @@
 
     /** Property identifier: JAXP schema language / DOM schema-type. */
     protected static final String JAXP_SCHEMA_LANGUAGE =
-    Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
+        Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 
     /** Property identifier: JAXP schema source/ DOM schema-location. */
     protected static final String JAXP_SCHEMA_SOURCE =
-    Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
+        Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
+
+    /** Property identifier: DTD validator. */
+    protected final static String DTD_VALIDATOR_PROPERTY =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
+
+    /** Property identifier: datatype validator factory. */
+    protected static final String DTD_VALIDATOR_FACTORY_PROPERTY =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
 
     protected static final String VALIDATION_MANAGER =
         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 
+    /** Property identifier: schema location. */
+    protected static final String SCHEMA_LOCATION =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
+
+    /** Property identifier: no namespace schema location. */
+    protected static final String SCHEMA_NONS_LOCATION =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
+
     /** Property identifier: Schema DV Factory */
     protected static final String SCHEMA_DV_FACTORY =
         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
@@ -209,8 +257,18 @@
     protected final DOMErrorHandlerWrapper fErrorHandlerWrapper =
                 new DOMErrorHandlerWrapper();
 
+    /** Current Datatype validator factory. */
+    protected DTDDVFactory fCurrentDVFactory;
+
+    /** The XML 1.0 Datatype validator factory. */
+    protected DTDDVFactory fDatatypeValidatorFactory;
+
+    /** The XML 1.1 Datatype validator factory. **/
+    protected DTDDVFactory fXML11DatatypeFactory;
+
     // private data
 
+    private String fSchemaLocation = null;
     private DOMStringList fRecognizedParameters;
 
 
@@ -256,7 +314,16 @@
             SCHEMA_FULL_CHECKING,
             DYNAMIC_VALIDATION,
             NORMALIZE_DATA,
+            SCHEMA_ELEMENT_DEFAULT,
             SEND_PSVI,
+            GENERATE_SYNTHETIC_ANNOTATIONS,
+            VALIDATE_ANNOTATIONS,
+            HONOUR_ALL_SCHEMALOCATIONS,
+            USE_GRAMMAR_POOL_ONLY,
+            DISALLOW_DOCTYPE_DECL_FEATURE,
+            BALANCE_SYNTAX_TREES,
+            WARN_ON_DUPLICATE_ATTDEF,
+            PARSER_SETTINGS,
             NAMESPACE_GROWTH,
             TOLERATE_DUPLICATES,
             XMLConstants.USE_CATALOG,
@@ -270,9 +337,19 @@
         setFeature(SCHEMA_FULL_CHECKING, false);
         setFeature(DYNAMIC_VALIDATION, false);
         setFeature(NORMALIZE_DATA, false);
+        setFeature(SCHEMA_ELEMENT_DEFAULT, false);
         setFeature(XERCES_NAMESPACES, true);
         setFeature(SEND_PSVI, true);
+        setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false);
+        setFeature(VALIDATE_ANNOTATIONS, false);
+        setFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
+        setFeature(USE_GRAMMAR_POOL_ONLY, false);
+        setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, false);
+        setFeature(BALANCE_SYNTAX_TREES, false);
+        setFeature(WARN_ON_DUPLICATE_ATTDEF, false);
+        setFeature(PARSER_SETTINGS, true);
         setFeature(NAMESPACE_GROWTH, false);
+        setFeature(TOLERATE_DUPLICATES, false);
         setFeature(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT);
         setFeature(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
 
@@ -288,6 +365,9 @@
             GRAMMAR_POOL,
             JAXP_SCHEMA_SOURCE,
             JAXP_SCHEMA_LANGUAGE,
+            SCHEMA_LOCATION,
+            SCHEMA_NONS_LOCATION,
+            DTD_VALIDATOR_PROPERTY,
             DTD_VALIDATOR_FACTORY_PROPERTY,
             SCHEMA_DV_FACTORY,
             SECURITY_MANAGER,
@@ -321,7 +401,10 @@
         setProperty(ERROR_REPORTER, fErrorReporter);
         addComponent(fErrorReporter);
 
-        setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, DTDDVFactory.getInstance());
+        fDatatypeValidatorFactory = DTDDVFactory.getInstance();
+        fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
+        fCurrentDVFactory = fDatatypeValidatorFactory;
+        setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
 
         XMLEntityManager manager =  new XMLEntityManager();
         setProperty(ENTITY_MANAGER, manager);
@@ -348,8 +431,7 @@
         if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) {
             MessageFormatter xmft = null;
             try {
-               xmft = (MessageFormatter)(
-                    ObjectFactory.newInstance("com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter", true));
+               xmft = new com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter();
             } catch (Exception exception){
             }
 
@@ -396,8 +478,8 @@
      * has ended.  If a client application wants to terminate
      * parsing early, it should throw an exception.
      *
-     * @param source The input source for the top-level of the
-     *               XML document.
+     * @param inputSource The input source for the top-level of the
+     *                    XML document.
      *
      * @exception XNIException Any XNI exception, possibly wrapping
      *                         another exception.
@@ -462,9 +544,7 @@
      *                 uninstall the currently installed resolver.
      */
     public void setEntityResolver(XMLEntityResolver resolver) {
-        if (resolver !=null) {
-            fProperties.put(ENTITY_RESOLVER, resolver);
-        }
+        fProperties.put(ENTITY_RESOLVER, resolver);
     } // setEntityResolver(XMLEntityResolver)
 
     /**
@@ -514,6 +594,26 @@
     } // getErrorHandler():XMLErrorHandler
 
     /**
+     * Returns the state of a feature.
+     *
+     * @param featureId The feature identifier.
+     * @return true if the feature is supported
+     *
+     * @throws XMLConfigurationException Thrown for configuration error.
+     *                                   In general, components should
+     *                                   only throw this exception if
+     *                                   it is <strong>really</strong>
+     *                                   a critical error.
+     */
+    public boolean getFeature(String featureId)
+        throws XMLConfigurationException {
+        if (featureId.equals(PARSER_SETTINGS)) {
+            return true;
+        }
+        return super.getFeature(featureId);
+    }
+
+    /**
      * Set the state of a feature.
      *
      * Set the state of any feature in a SAX2 parser.  The parser
@@ -576,8 +676,8 @@
 
         // REVISIT: Recognizes DOM L3 default features only.
         //          Does not yet recognize Xerces features.
-                if(value instanceof Boolean){
-                        boolean state = ((Boolean)value).booleanValue();
+        if(value instanceof Boolean){
+            boolean state = ((Boolean)value).booleanValue();
 
             if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
                 features = (short) (state ? features | COMMENTS : features & ~COMMENTS);
@@ -625,22 +725,12 @@
                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
                     ) {
                 if (state) { // true is not supported
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "FEATURE_NOT_SUPPORTED",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+                    throw newFeatureNotSupportedError(name);
                 }
             }
                         else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
                 if (!state) { // false is not supported
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "FEATURE_NOT_SUPPORTED",
-                            new Object[] { name });
-                   throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+                    throw newFeatureNotSupportedError(name);
                 }
             }
             else if (name.equalsIgnoreCase(SEND_PSVI) ){
@@ -648,12 +738,7 @@
                 // because in this case we won't be able to retrieve element
                 // default value.
                 if (!state) { // false is not supported
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "FEATURE_NOT_SUPPORTED",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+                    throw newFeatureNotSupportedError(name);
                 }
             }
             else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){
@@ -673,23 +758,16 @@
 
         }
 
-                if (!found || !(value instanceof Boolean))  { // set properties
-                        found = true;
+        if (!found || !(value instanceof Boolean))  { // set properties
+                found = true;
 
             if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
                 if (value instanceof DOMErrorHandler || value == null) {
                     fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value);
                     setErrorHandler(fErrorHandlerWrapper);
                 }
-
                 else {
-                    // REVISIT: type mismatch
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
             }
             else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
@@ -700,36 +778,45 @@
                     catch (XMLConfigurationException e) {}
                 }
                 else {
-                    // REVISIT: type mismatch
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
-
             }
             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
                 if (value instanceof String || value == null) {
                     try {
-                        // map DOM schema-location to JAXP schemaSource property
-                        setProperty(
-                            Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
-                            value);
+                        if (value == null) {
+                            fSchemaLocation = null;
+                            setProperty (
+                                Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+                                null);
+                        }
+                        else {
+                            fSchemaLocation = (String) value;
+                            // map DOM schema-location to JAXP schemaSource property
+                            // tokenize location string
+                            StringTokenizer t = new StringTokenizer(fSchemaLocation, " \n\t\r");
+                            if (t.hasMoreTokens()) {
+                                List<String> locations = new ArrayList<>();
+                                locations.add(t.nextToken());
+                                while (t.hasMoreTokens()) {
+                                    locations.add (t.nextToken());
+                                }
+                                setProperty (
+                                    Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+                                    locations.toArray(new String[locations.size()]));
+                            }
+                            else {
+                                setProperty (
+                                    Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+                                    new String [] {(String) value});
+                            }
+                        }
                     }
                     catch (XMLConfigurationException e) {}
                 }
                 else {
-                    // REVISIT: type mismatch
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
-
             }
             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
                 if (value instanceof String || value == null) {
@@ -754,57 +841,43 @@
                     catch (XMLConfigurationException e) {}
                 }
                 else {
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
-
             }
-            else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
+            else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+                if (value instanceof XMLEntityResolver || value == null) {
+                    try {
+                        setEntityResolver((XMLEntityResolver) value);
+                    }
+                    catch (XMLConfigurationException e) {}
+                }
+                else {
+                    throw newTypeMismatchError(name);
+                }
+            }
+            else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
                 // Xerces Symbol Table
                 if (value instanceof SymbolTable){
                     setProperty(SYMBOL_TABLE, value);
                 }
                 else {
-                    // REVISIT: type mismatch
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
             }
-            else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
-                if (value instanceof XMLGrammarPool){
+            else if (name.equalsIgnoreCase (GRAMMAR_POOL)) {
+                if (value instanceof XMLGrammarPool || value == null) {
                     setProperty(GRAMMAR_POOL, value);
                 }
                 else {
-                    // REVISIT: type mismatch
-                    String msg =
-                        DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "TYPE_MISMATCH_ERR",
-                            new Object[] { name });
-                    throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+                    throw newTypeMismatchError(name);
                 }
-
             }
-            else {
+                else {
                 // REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
                 //parameter is not recognized
-                String msg =
-                    DOMMessageFormatter.formatMessage(
-                        DOMMessageFormatter.DOM_DOMAIN,
-                        "FEATURE_NOT_FOUND",
-                        new Object[] { name });
-                throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+                throw newFeatureNotFoundError(name);
             }
         }
-
     }
 
 
@@ -878,23 +951,23 @@
                         return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
                 }
                 else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
-                        return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE);
+            return fSchemaLocation;
                 }
-        else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
+        else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+            return getEntityResolver();
+        }
+        else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
             return getProperty(SYMBOL_TABLE);
         }
-        else if (name.equalsIgnoreCase(GRAMMAR_POOL)){
+        else if (name.equalsIgnoreCase(GRAMMAR_POOL)) {
             return getProperty(GRAMMAR_POOL);
         }
+        else if (name.equalsIgnoreCase(SECURITY_MANAGER)) {
+            return getProperty(SECURITY_MANAGER);
+        }
                 else {
-                        String msg =
-                                DOMMessageFormatter.formatMessage(
-                                        DOMMessageFormatter.DOM_DOMAIN,
-                                        "FEATURE_NOT_FOUND",
-                                        new Object[] { name });
-                        throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+                    throw newFeatureNotFoundError(name);
                 }
-
         }
 
     /**
@@ -966,15 +1039,19 @@
         }
         else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
             // REVISIT: should null value be supported?
-            //as of now we are only supporting W3C XML Schema
-            return ( (value instanceof String) && value.equals(Constants.NS_XMLSCHEMA) ) ? true : false ;
+            // as of now we are only supporting W3C XML Schema and DTD.
+            return ((value instanceof String) &&
+                    (value.equals(Constants.NS_XMLSCHEMA) || value.equals(Constants.NS_DTD))) ? true : false;
         }
-        else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
+        else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+            return (value instanceof XMLEntityResolver) ? true : false;
+        }
+        else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
             // Xerces Symbol Table
-            return (value instanceof SymbolTable) ? true : false ;
+            return (value instanceof SymbolTable) ? true : false;
         }
-        else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
-            return (value instanceof XMLGrammarPool) ? true : false ;
+        else if (name.equalsIgnoreCase (GRAMMAR_POOL)) {
+            return (value instanceof XMLGrammarPool) ? true : false;
         }
         else {
             //false if the parameter is not recognized or the requested value is not supported.
@@ -991,46 +1068,49 @@
      * can be set by the application. Note that this list can also contain
      * parameter names defined outside this specification.
      */
-    public DOMStringList getParameterNames() {
-        if (fRecognizedParameters == null){
+        public DOMStringList getParameterNames() {
+            if (fRecognizedParameters == null){
             List<String> parameters = new ArrayList<>();
 
-            //Add DOM recognized parameters
-            //REVISIT: Would have been nice to have a list of
-            //recognized paramters.
-            parameters.add(Constants.DOM_COMMENTS);
-            parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
-            parameters.add(Constants.DOM_CDATA_SECTIONS);
-            parameters.add(Constants.DOM_ENTITIES);
-            parameters.add(Constants.DOM_SPLIT_CDATA);
-            parameters.add(Constants.DOM_NAMESPACES);
-            parameters.add(Constants.DOM_VALIDATE);
+                //Add DOM recognized parameters
+                //REVISIT: Would have been nice to have a list of
+                //recognized paramters.
+                parameters.add(Constants.DOM_COMMENTS);
+                parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
+                parameters.add(Constants.DOM_CDATA_SECTIONS);
+                parameters.add(Constants.DOM_ENTITIES);
+                parameters.add(Constants.DOM_SPLIT_CDATA);
+                parameters.add(Constants.DOM_NAMESPACES);
+                parameters.add(Constants.DOM_VALIDATE);
 
-            parameters.add(Constants.DOM_INFOSET);
-            parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
-            parameters.add(Constants.DOM_CANONICAL_FORM);
-            parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
-            parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
-            parameters.add(Constants.DOM_WELLFORMED);
+                parameters.add(Constants.DOM_INFOSET);
+                parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
+                parameters.add(Constants.DOM_CANONICAL_FORM);
+                parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
+                parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
+                parameters.add(Constants.DOM_WELLFORMED);
 
-            parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
-            parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
+                parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
+                parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
 
-            parameters.add(Constants.DOM_ERROR_HANDLER);
-            parameters.add(Constants.DOM_SCHEMA_TYPE);
-            parameters.add(Constants.DOM_SCHEMA_LOCATION);
-            parameters.add(Constants.DOM_RESOURCE_RESOLVER);
+                parameters.add(Constants.DOM_ERROR_HANDLER);
+                parameters.add(Constants.DOM_SCHEMA_TYPE);
+                parameters.add(Constants.DOM_SCHEMA_LOCATION);
+                parameters.add(Constants.DOM_RESOURCE_RESOLVER);
 
-            //Add recognized xerces features and properties
-            parameters.add(GRAMMAR_POOL);
-            parameters.add(SYMBOL_TABLE);
-            parameters.add(SEND_PSVI);
+                //Add recognized xerces features and properties
+                parameters.add(ENTITY_RESOLVER);
+                parameters.add(GRAMMAR_POOL);
+                parameters.add(SECURITY_MANAGER);
+                parameters.add(SYMBOL_TABLE);
+                parameters.add(SEND_PSVI);
 
-            fRecognizedParameters = new DOMStringListImpl(parameters);
-        }
+                fRecognizedParameters = new DOMStringListImpl(parameters);
 
-        return fRecognizedParameters;
-    }//getParameterNames
+            }
+
+            return fRecognizedParameters;
+        }//getParameterNames
 
     //
     // Protected methods
@@ -1061,6 +1141,7 @@
      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
      *            requested feature is not known or supported.
      */
+    @Override
     protected PropertyState checkProperty(String propertyId)
         throws XMLConfigurationException {
 
@@ -1115,4 +1196,44 @@
         return new ValidationManager();
     }
 
-} // class XMLParser
+    protected final void setDTDValidatorFactory(String version) {
+        if ("1.1".equals(version)) {
+            if (fCurrentDVFactory != fXML11DatatypeFactory) {
+                fCurrentDVFactory = fXML11DatatypeFactory;
+                setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
+            }
+        }
+        else if (fCurrentDVFactory != fDatatypeValidatorFactory) {
+            fCurrentDVFactory = fDatatypeValidatorFactory;
+            setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
+        }
+    }
+
+    private static DOMException newFeatureNotSupportedError(String name) {
+        String msg =
+            DOMMessageFormatter.formatMessage(
+                DOMMessageFormatter.DOM_DOMAIN,
+                "FEATURE_NOT_SUPPORTED",
+                new Object[] { name });
+        return new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+    }
+
+    private static DOMException newFeatureNotFoundError(String name) {
+        String msg =
+            DOMMessageFormatter.formatMessage(
+                DOMMessageFormatter.DOM_DOMAIN,
+                "FEATURE_NOT_FOUND",
+                new Object[] { name });
+        return new DOMException(DOMException.NOT_FOUND_ERR, msg);
+    }
+
+    private static DOMException newTypeMismatchError(String name) {
+        String msg =
+            DOMMessageFormatter.formatMessage(
+                DOMMessageFormatter.DOM_DOMAIN,
+                "TYPE_MISMATCH_ERR",
+                new Object[] { name });
+        return new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+    }
+
+} // class DOMConfigurationImpl
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -22,21 +22,17 @@
 
 
 
-import com.sun.org.apache.xerces.internal.dom.AbortException;
 import com.sun.org.apache.xerces.internal.impl.Constants;
 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
-import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar;
-import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription;
+import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
-import com.sun.org.apache.xerces.internal.parsers.XMLGrammarPreparser;
 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.util.XML11Char;
 import com.sun.org.apache.xerces.internal.util.XMLChar;
-import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl;
 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
 import com.sun.org.apache.xerces.internal.xni.Augmentations;
 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
@@ -48,15 +44,12 @@
 import com.sun.org.apache.xerces.internal.xni.XMLString;
 import com.sun.org.apache.xerces.internal.xni.XNIException;
 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
-import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
 import java.io.IOException;
-import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;
@@ -96,7 +89,7 @@
  *
  * @author Elena Litani, IBM
  * @author Neeraj Bajaj, Sun Microsystems, inc.
- * @LastModified: Nov 2017
+ * @LastModified: Apr 2019
  */
 public class DOMNormalizer implements XMLDocumentHandler {
 
@@ -155,7 +148,7 @@
 
     /** for setting the PSVI */
     protected Node fCurrentNode = null;
-    private QName fAttrQName = new QName();
+    private final QName fAttrQName = new QName();
 
     // attribute value normalization
     final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
@@ -163,8 +156,11 @@
     //DTD validator
     private XMLDTDValidator fDTDValidator;
 
-    //Check if element content is all "ignorable whitespace"
-    private boolean allWhitespace = false;
+    /** Empty string to pass to the validator. **/
+    public static final XMLString EMPTY_STRING = new XMLString();
+
+    // Check if element content is all "ignorable whitespace"
+    private boolean fAllWhitespace = false;
 
     // Constructor
     //
@@ -177,24 +173,30 @@
      * Normalizes document.
      * Note: reset() must be called before this method.
      */
-        protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) {
+    protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) {
 
-                fDocument = document;
-                fConfiguration = config;
+        fDocument = document;
+        fConfiguration = config;
+        fAllWhitespace = false;
+        fNamespaceValidation = false;
 
-                // intialize and reset DOMNormalizer component
-                //
-                fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
-                // reset namespace context
-                fNamespaceContext.reset();
-                fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING);
+        String xmlVersion = fDocument.getXmlVersion();
+        String schemaType = null;
+        String [] schemaLocations = null;
 
-                if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
+        // intialize and reset DOMNormalizer component
+        //
+        fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
+        // reset namespace context
+        fNamespaceContext.reset();
+        fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
+
+        if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
             String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
 
-            if(schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
-                        fValidationHandler =
-                                CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_SCHEMA);
+            if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
+                schemaType = XMLGrammarDescription.XML_SCHEMA;
+                fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
                 fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true);
                 fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true);
                 // report fatal error on DOM Level 1 nodes
@@ -203,49 +205,74 @@
                 // check if we need to fill in PSVI
                 fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false;
             }
+            else {
+                schemaType = XMLGrammarDescription.XML_DTD;
+                if (schemaLang != null) {
+                    schemaLocations = (String []) fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
+                }
+                fConfiguration.setDTDValidatorFactory(xmlVersion);
+                fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
+                fPSVI = false;
+            }
 
-                        fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
+            fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
 
             // reset ID table
             fDocument.clearIdentifiers();
 
-            if(fValidationHandler != null)
-            // reset schema validator
+            if (fValidationHandler != null) {
+                // reset the validation handler
                 ((XMLComponent) fValidationHandler).reset(fConfiguration);
-
-                }
-
-                fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
-                if (fValidationHandler != null) {
-                        fValidationHandler.setDocumentHandler(this);
-                        fValidationHandler.startDocument(
-                    new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
-                                                -1, -1 ), fDocument.encoding, fNamespaceContext, null);
-
-                }
-                try {
-                        Node kid, next;
-                        for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
-                                next = kid.getNextSibling();
-                                kid = normalizeNode(kid);
-                                if (kid != null) { // don't advance
-                                        next = kid;
-                                }
-                        }
-
-                        // release resources
-                        if (fValidationHandler != null) {
-                                fValidationHandler.endDocument(null);
-                                CoreDOMImplementationImpl.singleton.releaseValidator(
-                                        XMLGrammarDescription.XML_SCHEMA, fValidationHandler);
-                                fValidationHandler = null;
-                        }
-                } catch (AbortException e) {
-                    return;
-                }
-
+            }
+        }
+        else {
+            fValidationHandler = null;
         }
 
+        fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
+        if (fValidationHandler != null) {
+            fValidationHandler.setDocumentHandler(this);
+            fValidationHandler.startDocument(
+                    new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
+                            -1, -1 ), fDocument.encoding, fNamespaceContext, null);
+            fValidationHandler.xmlDecl(fDocument.getXmlVersion(),
+                    fDocument.getXmlEncoding(), fDocument.getXmlStandalone() ? "yes" : "no", null);
+        }
+        try {
+            if (schemaType == XMLGrammarDescription.XML_DTD) {
+                processDTD(xmlVersion, schemaLocations != null ? schemaLocations[0] : null);
+            }
+
+            Node kid, next;
+            for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
+                next = kid.getNextSibling();
+                kid = normalizeNode(kid);
+                if (kid != null) { // don't advance
+                    next = kid;
+                }
+            }
+
+            // release resources
+            if (fValidationHandler != null) {
+                fValidationHandler.endDocument(null);
+                fValidationHandler.setDocumentHandler(null);
+                CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
+                fValidationHandler = null;
+            }
+        }
+        catch (RuntimeException e) {
+            // release resources
+            if (fValidationHandler != null) {
+                fValidationHandler.setDocumentHandler(null);
+                CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
+                fValidationHandler = null;
+            }
+            if (e instanceof AbortException) {
+                return; // processing aborted by the user
+            }
+            throw e; // otherwise re-throw.
+        }
+    }
 
     /**
      *
@@ -273,16 +300,7 @@
                 if (DEBUG_ND) {
                     System.out.println("==>normalizeNode:{doctype}");
                 }
-                DocumentTypeImpl docType = (DocumentTypeImpl)node;
-                fDTDValidator = (XMLDTDValidator)CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_DTD);
-                fDTDValidator.setDocumentHandler(this);
-                fConfiguration.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, createGrammarPool(docType));
-                fDTDValidator.reset(fConfiguration);
-                fDTDValidator.startDocument(
-                        new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
-                            -1, -1 ), fDocument.encoding, fNamespaceContext, null);
-                fDTDValidator.doctypeDecl(docType.getName(), docType.getPublicId(), docType.getSystemId(), null);
-                //REVISIT: well-formness encoding info
+                // REVISIT: well-formedness encoding info
                 break;
             }
 
@@ -297,7 +315,7 @@
                     if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
                             fDocument.isXMLVersionChanged()){
                         if (fNamespaceValidation){
-                            wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version()) ;
+                            wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version());
                         }
                         else {
                             wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
@@ -329,13 +347,21 @@
                     // remove default attributes
                     namespaceFixUp(elem, attributes);
 
-                    if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0 && attributes != null ) {
-                        for (int i = 0; i < attributes.getLength(); ++i) {
-                            Attr att = (Attr)attributes.getItem(i);
-                            if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
-                                XMLSymbols.PREFIX_XMLNS.equals(att.getName())) {
-                                elem.removeAttributeNode(att);
-                                --i;
+                    if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
+                        // Namespace declarations may have been added by namespace fix-up. Need
+                        // to fetch the AttributeMap again if it contained no attributes prior
+                        // to namespace fix-up.
+                        if (attributes == null) {
+                            attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
+                        }
+                        if (attributes != null) {
+                            for (int i = 0; i < attributes.getLength(); ++i) {
+                                Attr att = (Attr)attributes.getItem(i);
+                                if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
+                                        XMLSymbols.PREFIX_XMLNS.equals(att.getName())) {
+                                    elem.removeAttributeNode(att);
+                                    --i;
+                                }
                             }
                         }
                     }
@@ -347,16 +373,21 @@
                             //removeDefault(attr, attributes);
                             attr.normalize();
                             if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
-                                    isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version());
-                                if (fDocument.isXMLVersionChanged()){
-                                    wellformed=CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
-                                    if (!wellformed){
-                                                            String msg = DOMMessageFormatter.formatMessage(
-                                                              DOMMessageFormatter.DOM_DOMAIN,
-                                                              "wf-invalid-character-in-node-name",
-                                                               new Object[]{"Attr",node.getNodeName()});
-                                                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
-                                                                "wf-invalid-character-in-node-name");
+                                    isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, attr.getValue(), fDocument.isXML11Version());
+                                if (fDocument.isXMLVersionChanged()) {
+                                    if (fNamespaceValidation){
+                                        wellformed = CoreDocumentImpl.isValidQName(node.getPrefix(), node.getLocalName(), fDocument.isXML11Version());
+                                    }
+                                    else {
+                                        wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), fDocument.isXML11Version());
+                                    }
+                                    if (!wellformed) {
+                                        String msg = DOMMessageFormatter.formatMessage(
+                                          DOMMessageFormatter.DOM_DOMAIN,
+                                          "wf-invalid-character-in-node-name",
+                                           new Object[]{"Attr",node.getNodeName()});
+                                        reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+                                            "wf-invalid-character-in-node-name");
                                     }
                                 }
                             }
@@ -379,26 +410,12 @@
                     fValidationHandler.startElement(fQName, fAttrProxy, null);
                 }
 
-                if (fDTDValidator != null) {
-                    // REVISIT: possible solutions to discard default content are:
-                    //         either we pass some flag to XML Schema validator
-                    //         or rely on the PSVI information.
-                    fAttrProxy.setAttributes(attributes, fDocument, elem);
-                    updateQName(elem, fQName); // updates global qname
-                    // set error node in the dom error wrapper
-                    // so if error occurs we can report an error node
-                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
-                    fCurrentNode = node;
-                    // call re-validation handler
-                    fDTDValidator.startElement(fQName, fAttrProxy, null);
-                }
-
                 // normalize children
                 Node kid, next;
                 for (kid = elem.getFirstChild(); kid != null; kid = next) {
                     next = kid.getNextSibling();
                     kid = normalizeNode(kid);
-                    if (kid !=null) {
+                    if (kid != null) {
                         next = kid;  // don't advance
                     }
                 }
@@ -412,7 +429,6 @@
 
                 }
 
-
                 if (fValidationHandler != null) {
                     updateQName(elem, fQName); // updates global qname
                     //
@@ -423,16 +439,6 @@
                     fValidationHandler.endElement(fQName, null);
                 }
 
-                if (fDTDValidator != null) {
-                    updateQName(elem, fQName); // updates global qname
-                    //
-                    // set error node in the dom error wrapper
-                    // so if error occurs we can report an error node
-                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
-                    fCurrentNode = node;
-                    fDTDValidator.endElement(fQName, null);
-                }
-
                 // pop namespace context
                 fNamespaceContext.popContext();
 
@@ -465,6 +471,13 @@
                         // of the document
                         isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version());
                     }
+                    if (fValidationHandler != null) {
+                        // Don't bother filling an XMLString with the text of the comment.
+                        // We only send the comment event to the validator handler so that
+                        // when  the schema-type is DTD an error will be reported for a
+                        // comment appearing in EMPTY content.
+                        fValidationHandler.comment(EMPTY_STRING, null);
+                    }
                 }//end-else if comment node is not to be removed.
                                 break;
             }
@@ -531,16 +544,6 @@
                     fValidationHandler.characterData(node.getNodeValue(), null);
                     fValidationHandler.endCDATA(null);
                 }
-
-                if (fDTDValidator != null) {
-                    // set error node in the dom error wrapper
-                    // so if error occurs we can report an error node
-                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
-                    fCurrentNode = node;
-                    fDTDValidator.startCDATA(null);
-                    fDTDValidator.characterData(node.getNodeValue(), null);
-                    fDTDValidator.endCDATA(null);
-                }
                 String value = node.getNodeValue();
 
                 if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
@@ -605,42 +608,37 @@
 
                     short nextType = (next != null)?next.getNodeType():-1;
                     if (nextType == -1 || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 &&
-                           nextType == Node.ENTITY_NODE) ||
-                          ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 &&
-                           nextType == Node.COMMENT_NODE) ||
-                          ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) &&
-                          nextType == Node.CDATA_SECTION_NODE)) {
-                              if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){
-                                  isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
-                              }
-                              if (fValidationHandler != null) {
-                                     fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
-                                     fCurrentNode = node;
-                                     fValidationHandler.characterData(node.getNodeValue(), null);
-                                     if (DEBUG_ND) {
-                                         System.out.println("=====>characterData(),"+nextType);
-
-                                     }
-                              }
-                              if (fDTDValidator != null) {
-                                  fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
-                                  fCurrentNode = node;
-                                  fDTDValidator.characterData(node.getNodeValue(), null);
-                                  if (DEBUG_ND) {
-                                      System.out.println("=====>characterData(),"+nextType);
-
-                                  }
-                                  if(allWhitespace) {
-                                      allWhitespace = false;
-                                      ((TextImpl)node).setIgnorableWhitespace(true);
-                                  }
-                              }
+                            nextType == Node.ENTITY_NODE) ||
+                            ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 &&
+                                    nextType == Node.COMMENT_NODE) ||
+                                    ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) &&
+                                    nextType == Node.CDATA_SECTION_NODE)) {
+                        if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){
+                            isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
+                        }
+                        if (fValidationHandler != null) {
+                            fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
+                            fCurrentNode = node;
+                            fValidationHandler.characterData(node.getNodeValue(), null);
+                            if (!fNamespaceValidation) {
+                                if (fAllWhitespace) {
+                                    fAllWhitespace = false;
+                                    ((TextImpl)node).setIgnorableWhitespace(true);
+                                }
+                                else {
+                                    ((TextImpl)node).setIgnorableWhitespace(false);
+                                }
+                            }
+                            if (DEBUG_ND) {
+                                System.out.println("=====>characterData(),"+nextType);
+                            }
+                        }
                     }
                     else {
-                            if (DEBUG_ND) {
-                                System.out.println("=====>don't send characters(),"+nextType);
+                        if (DEBUG_ND) {
+                            System.out.println("=====>don't send characters(),"+nextType);
 
-                            }
+                        }
                     }
                 }
                 break;
@@ -674,42 +672,66 @@
                 //which may not be valid XML character
                 isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version());
             }
+
+            if (fValidationHandler != null) {
+                // Don't bother filling an XMLString with the data section of the
+                // processing instruction. We only send the processing instruction
+                // event to the validator handler so that when the schema-type is
+                // DTD an error will be reported for a processing instruction
+                // appearing in EMPTY content.
+                fValidationHandler.processingInstruction(((ProcessingInstruction) node).getTarget(), EMPTY_STRING, null);
+            }
         }//end case Node.PROCESSING_INSTRUCTION_NODE
 
         }//end of switch
         return null;
     }//normalizeNode
 
-    private XMLGrammarPool createGrammarPool(DocumentTypeImpl docType) {
-
-        XMLGrammarPoolImpl pool = new XMLGrammarPoolImpl();
+    private void processDTD(String xmlVersion, String schemaLocation) {
 
-        XMLGrammarPreparser preParser = new XMLGrammarPreparser(fSymbolTable);
-        preParser.registerPreparser(XMLGrammarDescription.XML_DTD, null);
-        preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true);
-        preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, true);
-        preParser.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, pool);
+        String rootName = null;
+        String publicId = null;
+        String systemId = schemaLocation;
+        String baseSystemId = fDocument.getDocumentURI();
+        String internalSubset = null;
 
-        String internalSubset = docType.getInternalSubset();
-        XMLInputSource is = new XMLInputSource(docType.getPublicId(), docType.getSystemId(), null, false);
-
-        if(internalSubset != null)
-            is.setCharacterStream(new StringReader(internalSubset));
-        try {
-            DTDGrammar g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is);
-            ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName());
-            is.setCharacterStream(null);
-            g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is);
-            ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName());
-
-        } catch (XNIException e) {
-        } catch (IOException e) {
+        DocumentType docType = fDocument.getDoctype();
+        if (docType != null) {
+            rootName = docType.getName();
+            publicId = docType.getPublicId();
+            if (systemId == null || systemId.length() == 0) {
+                systemId = docType.getSystemId();
+            }
+            internalSubset = docType.getInternalSubset();
+        }
+        // If the DOM doesn't have a DocumentType node we may still
+        // be able to fetch a DTD if the application provided a URI
+        else {
+            Element elem = fDocument.getDocumentElement();
+            if (elem == null) return;
+            rootName = elem.getNodeName();
+            if (systemId == null || systemId.length() == 0) return;
         }
 
-        return pool;
-    }
-
-
+        XMLDTDLoader loader = null;
+        try {
+            fValidationHandler.doctypeDecl(rootName, publicId, systemId, null);
+            loader = CoreDOMImplementationImpl.singleton.getDTDLoader(xmlVersion);
+            loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
+            loader.setEntityResolver(fConfiguration.getEntityResolver());
+            loader.setErrorHandler(fConfiguration.getErrorHandler());
+            loader.loadGrammarWithContext((XMLDTDValidator) fValidationHandler, rootName,
+                    publicId, systemId, baseSystemId, internalSubset);
+        }
+        // REVISIT: Should probably report this exception to the error handler.
+        catch (IOException e) {
+        }
+        finally {
+            if (loader != null) {
+                CoreDOMImplementationImpl.singleton.releaseDTDLoader(xmlVersion, loader);
+            }
+        }
+    } // processDTD(String, String)
 
     protected final void expandEntityRef (Node parent, Node reference){
         Node kid, next;
@@ -740,30 +762,15 @@
         //
         // ------------------------------------
 
-        String value, name, uri, prefix;
+        String value, uri, prefix;
         if (attributes != null) {
 
             // Record all valid local declarations
             for (int k = 0; k < attributes.getLength(); ++k) {
                 Attr attr = (Attr)attributes.getItem(k);
-
-                //do the name check only when version of the document was changed &
-                //application has set the value of well-formed features to true
-                if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
-                    fDocument.isXMLVersionChanged()) {
-                    //checkQName does checking based on the version of the document
-                    fDocument.checkQName(attr.getPrefix() , attr.getLocalName()) ;
-                }
-
                 uri = attr.getNamespaceURI();
                 if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
                     // namespace attribute
-
-                    // "namespace-declarations" == false; Discard all namespace declaration attributes
-                    if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
-                        continue;
-                    }
-
                     value = attr.getNodeValue();
                     if (value == null) {
                         value=XMLSymbols.EMPTY_STRING;
@@ -798,7 +805,7 @@
                         } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol)  -- xmlns
                             // empty prefix is always bound ("" or some string)
                             value = fSymbolTable.addSymbol(value);
-                            fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value);
+                            fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? value : null);
                             //removeDefault (attr, attributes);
                             continue;
                         }
@@ -826,12 +833,7 @@
 
         uri = element.getNamespaceURI();
         prefix = element.getPrefix();
-
-        // "namespace-declarations" == false? Discard all namespace declaration attributes
-        if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
-            // no namespace declaration == no namespace URI, semantics are to keep prefix
-            uri = null;
-        } else if (uri != null) {  // Element has a namespace
+        if (uri != null) {  // Element has a namespace
             uri = fSymbolTable.addSymbol(uri);
             prefix = (prefix == null ||
                       prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
@@ -870,8 +872,8 @@
                     // undeclare default namespace declaration (before that element
                     // bound to non-zero length uir), but adding xmlns="" decl
                     addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element);
-                    fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING);
-                    fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING);
+                    fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, null);
+                    fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
                 }
             }
         }
@@ -894,12 +896,35 @@
                 // normalize attribute value
                 attr.normalize();
                 value = attr.getValue();
-                name = attr.getNodeName();
                 uri = attr.getNamespaceURI();
 
                 // make sure that value is never null.
                 if (value == null) {
-                    value=XMLSymbols.EMPTY_STRING;
+                    value = XMLSymbols.EMPTY_STRING;
+                }
+
+                //---------------------------------------
+                // check if value of the attribute is namespace well-formed
+                //---------------------------------------
+                if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
+                    isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, value, fDocument.isXML11Version());
+                    if (fDocument.isXMLVersionChanged()) {
+                        boolean wellformed;
+                        if (fNamespaceValidation){
+                            wellformed = CoreDocumentImpl.isValidQName(attr.getPrefix(), attr.getLocalName(), fDocument.isXML11Version());
+                        }
+                        else {
+                            wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), fDocument.isXML11Version());
+                        }
+                        if (!wellformed) {
+                            String msg = DOMMessageFormatter.formatMessage(
+                                    DOMMessageFormatter.DOM_DOMAIN,
+                                    "wf-invalid-character-in-node-name",
+                                    new Object[]{"Attr", attr.getNodeName()});
+                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+                            "wf-invalid-character-in-node-name");
+                        }
+                    }
                 }
 
                 if (uri != null) {  // attribute has namespace !=null
@@ -916,23 +941,6 @@
                     if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
                         continue;
                     }
-                    //---------------------------------------
-                    // check if value of the attribute is namespace well-formed
-                    //---------------------------------------
-                    if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
-                            isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version());
-                            if (fDocument.isXMLVersionChanged()){
-                                boolean wellformed=CoreDocumentImpl.isXMLName(attr.getNodeName() , fDocument.isXML11Version());
-                                if (!wellformed){
-                                                        String msg = DOMMessageFormatter.formatMessage(
-                                                            DOMMessageFormatter.DOM_DOMAIN,
-                                                            "wf-invalid-character-in-node-name",
-                                                            new Object[]{"Attribute", attr.getNodeName()});
-                                        reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
-                                            "wf-invalid-character-in-node-name");
-                                }
-                        }
-                    }
 
                     // ---------------------------------------
                     // remove default attributes
@@ -948,7 +956,6 @@
                     // reset id-attributes
                     ((AttrImpl)attr).setIdAttribute(false);
 
-
                     uri = fSymbolTable.addSymbol(uri);
 
                     // find if for this prefix a URI was already declared
@@ -962,7 +969,6 @@
                         // conflict: attribute has a prefix that conficlicts with a binding
                         //           already active in scope
 
-                        name  = attr.getNodeName();
                         // Find if any prefix for attributes namespace URI is available
                         // in the scope
                         String declaredPrefix = fNamespaceContext.getPrefix(uri);
@@ -1447,8 +1453,8 @@
         protected CoreDocumentImpl fDocument;
         protected ElementImpl fElement;
 
-        protected final Vector<Augmentations> fAugmentations = new Vector<>(5);
-
+        protected Vector<String> fDTDTypes = new Vector<>(5);
+        protected Vector<Augmentations> fAugmentations = new Vector<>(5);
 
         public void setAttributes(AttributeMap attributes, CoreDocumentImpl doc, ElementImpl elem) {
             fDocument = doc;
@@ -1456,7 +1462,7 @@
             fElement = elem;
             if (attributes != null) {
                 int length = attributes.getLength();
-
+                fDTDTypes.setSize(length);
                 fAugmentations.setSize(length);
                 // REVISIT: this implementation does not store any value in augmentations
                 //          and basically not keeping augs in parallel to attributes map
@@ -1464,34 +1470,37 @@
                 for (int i = 0; i < length; i++) {
                     fAugmentations.setElementAt(new AugmentationsImpl(), i);
                 }
-            } else {
+            }
+            else {
+                fDTDTypes.setSize(0);
                 fAugmentations.setSize(0);
             }
         }
 
 
-                /**
+        /**
          * This method adds default declarations
                  * @see com.sun.org.apache.xerces.internal.xni.XMLAttributes#addAttribute(QName, String, String)
-                 */
-                public int addAttribute(QName qname, String attrType, String attrValue) {
-                        int index = fElement.getXercesAttribute(qname.uri, qname.localpart);
-                        // add defaults to the tree
-                        if (index < 0) {
+         */
+        public int addAttribute(QName qname, String attrType, String attrValue) {
+            int index = fElement.getXercesAttribute(qname.uri, qname.localpart);
+            // add defaults to the tree
+            if (index < 0) {
                 // the default attribute was removed by a user and needed to
                 // be added back
-                                AttrImpl attr = (AttrImpl)
-                                        ((CoreDocumentImpl) fElement.getOwnerDocument()).createAttributeNS(
-                                                qname.uri,
-                                                qname.rawname,
-                                                qname.localpart);
+                AttrImpl attr = (AttrImpl)
+                    ((CoreDocumentImpl) fElement.getOwnerDocument()).createAttributeNS(
+                        qname.uri,
+                        qname.rawname,
+                        qname.localpart);
                 // REVISIT: the following should also update ID table
                 attr.setNodeValue(attrValue);
                 index = fElement.setXercesAttributeNode(attr);
+                fDTDTypes.insertElementAt(attrType, index);
                 fAugmentations.insertElementAt(new AugmentationsImpl(), index);
                 attr.setSpecified(false);
-                        }
-                        else {
+            }
+            else {
                 // default attribute is in the tree
                 // we don't need to do anything since prefix was already fixed
                 // at the namespace fixup time and value must be same value, otherwise
@@ -1500,7 +1509,7 @@
 
             }
             return index;
-                }
+        }
 
 
         public void removeAllAttributes(){
@@ -1523,41 +1532,58 @@
             return -1;
         }
 
-        public int getIndex(String uri, String localPart){
+        public int getIndex(String uri, String localPart) {
             // REVISIT: implement
             return -1;
         }
 
-        public void setName(int attrIndex, QName attrName){
+        public void setName(int attrIndex, QName attrName) {
             // REVISIT: implement
         }
 
-        public void getName(int attrIndex, QName attrName){
-            if (fAttributes !=null) {
+        public void getName(int attrIndex, QName attrName) {
+            if (fAttributes != null) {
                 updateQName((Node)fAttributes.getItem(attrIndex), attrName);
             }
         }
 
-        public String getPrefix(int index){
-            // REVISIT: implement
+        public String getPrefix(int index) {
+            if (fAttributes != null) {
+                Node node = (Node) fAttributes.getItem(index);
+                String prefix = node.getPrefix();
+                prefix = (prefix != null && prefix.length() != 0) ? fSymbolTable.addSymbol(prefix) : null;
+                return prefix;
+            }
+            return null;
+        }
+
+        public String getURI(int index) {
+            if (fAttributes != null) {
+                Node node = (Node) fAttributes.getItem(index);
+                String namespace = node.getNamespaceURI();
+                namespace = (namespace != null) ? fSymbolTable.addSymbol(namespace) : null;
+                return namespace;
+            }
             return null;
         }
 
 
-        public String getURI(int index){
-            // REVISIT: implement
+        public String getLocalName(int index) {
+            if (fAttributes != null) {
+                Node node = (Node) fAttributes.getItem(index);
+                String localName = node.getLocalName();
+                localName = (localName != null) ? fSymbolTable.addSymbol(localName) : null;
+                return localName;
+            }
             return null;
         }
 
-
-        public String getLocalName(int index){
-            // REVISIT: implement
-            return null;
-        }
-
-
-        public String getQName(int index){
-            // REVISIT: implement
+        public String getQName(int index) {
+            if (fAttributes != null) {
+                Node node = (Node) fAttributes.getItem(index);
+                String rawname = fSymbolTable.addSymbol(node.getNodeName());
+                return rawname;
+            }
             return null;
         }
 
@@ -1566,27 +1592,31 @@
             return null;
         }
 
-        public void setType(int attrIndex, String attrType){
-            // REVISIT: implement
+        public void setType(int attrIndex, String attrType) {
+            fDTDTypes.setElementAt(attrType, attrIndex);
         }
 
+        public String getType(int index) {
+            String type = fDTDTypes.elementAt(index);
+            return (type != null) ? getReportableType(type) : "CDATA";
+        }
 
-        public String getType(int index){
+        public String getType(String qName) {
             return "CDATA";
         }
 
-
-        public String getType(String qName){
+        public String getType(String uri, String localName) {
             return "CDATA";
         }
 
-
-        public String getType(String uri, String localName){
-            return "CDATA";
+        private String getReportableType(String type) {
+            if (type.charAt(0) == '(') {
+                return "NMTOKEN";
+            }
+            return type;
         }
 
-
-        public void setValue(int attrIndex, String attrValue){
+        public void setValue(int attrIndex, String attrValue) {
             // REVISIT: is this desired behaviour?
             // The values are updated in the case datatype-normalization is turned on
             // in this case we need to make sure that specified attributes stay specified
@@ -1609,13 +1639,11 @@
 
         }
 
-
         public String getValue(String qName){
             // REVISIT: implement
             return null;
         }
 
-
         public String getValue(String uri, String localName){
             if (fAttributes != null) {
                 Node node =  fAttributes.getNamedItemNS(uri, localName);
@@ -1624,19 +1652,16 @@
             return null;
         }
 
-
         public void setNonNormalizedValue(int attrIndex, String attrValue){
             // REVISIT: implement
 
         }
 
-
         public String getNonNormalizedValue(int attrIndex){
             // REVISIT: implement
             return null;
         }
 
-
         public void setSpecified(int attrIndex, boolean specified){
             AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex);
             attr.setSpecified(specified);
@@ -1788,58 +1813,85 @@
      * @exception XNIException
      *                   Thrown by handler to signal an error.
      */
-        public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
-                throws XNIException {
-                Element currentElement = (Element) fCurrentNode;
-                int attrCount = attributes.getLength();
+    public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
+        throws XNIException {
+        Element currentElement = (Element) fCurrentNode;
+        int attrCount = attributes.getLength();
         if (DEBUG_EVENTS) {
             System.out.println("==>startElement: " +element+
-            " attrs.length="+attrCount);
+                    " attrs.length="+attrCount);
         }
 
-                for (int i = 0; i < attrCount; i++) {
-                        attributes.getName(i, fAttrQName);
-                        Attr attr = null;
+        for (int i = 0; i < attrCount; i++) {
+            attributes.getName(i, fAttrQName);
+            Attr attr = null;
 
-                        attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
+            attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
+            if (attr == null) {
+                // Must be a non-namespace aware DOM Level 1 node.
+                attr = currentElement.getAttributeNode(fAttrQName.rawname);
+            }
             AttributePSVI attrPSVI =
-                                (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
+                (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
 
-                        if (attrPSVI != null) {
+            if (attrPSVI != null) {
                 //REVISIT: instead we should be using augmentations:
                 // to set/retrieve Id attributes
                 XSTypeDefinition decl = attrPSVI.getMemberTypeDefinition();
                 boolean id = false;
-                if (decl != null){
+                if (decl != null) {
                     id = ((XSSimpleType)decl).isIDType();
-                } else{
+                }
+                else {
                     decl = attrPSVI.getTypeDefinition();
-                    if (decl !=null){
-                       id = ((XSSimpleType)decl).isIDType();
+                    if (decl != null) {
+                        id = ((XSSimpleType)decl).isIDType();
                     }
                 }
-                if (id){
+                if (id) {
                     ((ElementImpl)currentElement).setIdAttributeNode(attr, true);
                 }
 
-                                if (fPSVI) {
-                                        ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
-                                }
-                                if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
-                                        // datatype-normalization
-                                        // NOTE: The specified value MUST be set after we set
-                                        //       the node value because that turns the "specified"
-                                        //       flag to "true" which may overwrite a "false"
-                                        //       value from the attribute list.
-                                        boolean specified = attr.getSpecified();
-                                        attr.setValue(attrPSVI.getSchemaValue().getNormalizedValue());
-                                        if (!specified) {
-                                                ((AttrImpl) attr).setSpecified(specified);
-                                        }
-                                }
+                if (fPSVI) {
+                    ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
+                }
+
+                // Updating the TypeInfo for this attribute.
+                ((AttrImpl) attr).setType(decl);
+
+                if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
+                    // datatype-normalization
+                    // NOTE: The specified value MUST be set after we set
+                    //       the node value because that turns the "specified"
+                    //       flag to "true" which may overwrite a "false"
+                    //       value from the attribute list.
+                    final String normalizedValue = attrPSVI.getSchemaValue().getNormalizedValue();
+                    if (normalizedValue != null) {
+                        boolean specified = attr.getSpecified();
+                        attr.setValue(normalizedValue);
+                        if (!specified) {
+                            ((AttrImpl) attr).setSpecified(specified);
                         }
+                    }
                 }
+            }
+            else { // DTD
+                String type = null;
+                boolean isDeclared = Boolean.TRUE.equals(attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_DECLARED));
+                // For DOM Level 3 TypeInfo, the type name must
+                // be null if this attribute has not been declared
+                // in the DTD.
+                if (isDeclared) {
+                    type = attributes.getType(i);
+                    if ("ID".equals (type)) {
+                        ((ElementImpl) currentElement).setIdAttributeNode(attr, true);
+                    }
+                }
+                // Updating the TypeInfo for this attribute.
+                ((AttrImpl) attr).setType(type);
+            }
         }
+    }
 
 
     /**
@@ -1948,7 +2000,7 @@
      *                   Thrown by handler to signal an error.
      */
     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{
-        allWhitespace = true;
+        fAllWhitespace = true;
     }
 
     /**
@@ -1960,38 +2012,51 @@
      * @exception XNIException
      *                   Thrown by handler to signal an error.
      */
-        public void endElement(QName element, Augmentations augs) throws XNIException {
-                if (DEBUG_EVENTS) {
-                        System.out.println("==>endElement: " + element);
-                }
+    public void endElement(QName element, Augmentations augs) throws XNIException {
+        if (DEBUG_EVENTS) {
+            System.out.println("==>endElement: " + element);
+        }
 
-        if(augs != null) {
-                ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
-                if (elementPSVI != null) {
-                        ElementImpl elementNode = (ElementImpl) fCurrentNode;
-                        if (fPSVI) {
-                                ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
-                        }
-                        // include element default content (if one is available)
-                        String normalizedValue = elementPSVI.getSchemaValue().getNormalizedValue();
-                        if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
+        if (augs != null) {
+            ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
+            if (elementPSVI != null) {
+                ElementImpl elementNode = (ElementImpl) fCurrentNode;
+                if (fPSVI) {
+                    ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
+                }
+                // Updating the TypeInfo for this element.
+                if (elementNode instanceof ElementNSImpl) {
+                    XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
+                    if (type == null) {
+                        type = elementPSVI.getTypeDefinition();
+                    }
+                    ((ElementNSImpl) elementNode).setType(type);
+                }
+                // include element default content (if one is available)
+                String normalizedValue = elementPSVI.getSchemaValue().getNormalizedValue();
+                if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
                     if (normalizedValue !=null)
-                                    elementNode.setTextContent(normalizedValue);
-                        }
-                        else {
-                                // NOTE: this is a hack: it is possible that DOM had an empty element
-                                // and validator sent default value using characters(), which we don't
-                                // implement. Thus, here we attempt to add the default value.
-                                String text = elementNode.getTextContent();
-                                if (text.length() == 0) {
-                                        // default content could be provided
+                        elementNode.setTextContent(normalizedValue);
+                }
+                else {
+                    // NOTE: this is a hack: it is possible that DOM had an empty element
+                    // and validator sent default value using characters(), which we don't
+                    // implement. Thus, here we attempt to add the default value.
+                    String text = elementNode.getTextContent();
+                    if (text.length() == 0) {
+                        // default content could be provided
                         if (normalizedValue !=null)
                             elementNode.setTextContent(normalizedValue);
-                                }
-                        }
+                    }
                 }
+                return;
+            }
         }
+        // DTD; elements have no type.
+        if (fCurrentNode instanceof ElementNSImpl) {
+            ((ElementNSImpl) fCurrentNode).setType(null);
         }
+    }
 
 
     /**
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DeferredDocumentImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DeferredDocumentImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -69,7 +69,7 @@
     // protected
 
     /** Chunk shift. */
-    protected static final int CHUNK_SHIFT = 8;           // 2^8 = 256
+    protected static final int CHUNK_SHIFT = 11;           // 2^11 = 2k
 
     /** Chunk size. */
     protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
@@ -78,7 +78,7 @@
     protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
 
     /** Initial chunk size. */
-    protected static final int INITIAL_CHUNK_COUNT = (1 << (13 - CHUNK_SHIFT));   // 32
+    protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT));   // 2^16 = 64k
 
     //
     // Data
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentTypeImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DocumentTypeImpl.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -56,6 +56,7 @@
  * @author Joe Kesselman, IBM
  * @author Andy Clark, IBM
  * @since  PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  */
 public class DocumentTypeImpl
     extends ParentNode
@@ -324,7 +325,7 @@
                 Node entNode2 =
                     argEntities.getNamedItem(entNode1.getNodeName());
 
-                if (!((NodeImpl) entNode1).isEqualNode((NodeImpl) entNode2))
+                if (!((NodeImpl) entNode1).isEqualNode(entNode2))
                     return false;
             }
         }
@@ -344,7 +345,7 @@
                 Node noteNode2 =
                     argNotations.getNamedItem(noteNode1.getNodeName());
 
-                if (!((NodeImpl) noteNode1).isEqualNode((NodeImpl) noteNode2))
+                if (!((NodeImpl) noteNode1).isEqualNode(noteNode2))
                     return false;
             }
         }
@@ -357,7 +358,7 @@
      * NON-DOM
      * set the ownerDocument of this node and its children
      */
-    void setOwnerDocument(CoreDocumentImpl doc) {
+    protected void setOwnerDocument(CoreDocumentImpl doc) {
         super.setOwnerDocument(doc);
         entities.setOwnerDocument(doc);
         notations.setOwnerDocument(doc);
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,5 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -55,38 +54,33 @@
  * @author Andy Clark, IBM
  * @author Ralf Pfeiffer, IBM
  * @since PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  */
 public class ElementImpl
-        extends ParentNode
-        implements Element, ElementTraversal, TypeInfo {
+    extends ParentNode
+    implements Element, ElementTraversal, TypeInfo {
 
     //
     // Constants
     //
-    /**
-     * Serialization version.
-     */
+
+    /** Serialization version. */
     static final long serialVersionUID = 3717253516652722278L;
     //
     // Data
     //
 
-    /**
-     * Element name.
-     */
+    /** Element name. */
     protected String name;
 
-    /**
-     * Attributes.
-     */
+    /** Attributes. */
     protected AttributeMap attributes;
 
     //
     // Constructors
     //
-    /**
-     * Factory constructor.
-     */
+
+    /** Factory constructor. */
     public ElementImpl(CoreDocumentImpl ownerDoc, String name) {
         super(ownerDoc);
         this.name = name;
@@ -94,8 +88,7 @@
     }
 
     // for ElementNSImpl
-    protected ElementImpl() {
-    }
+    protected ElementImpl() {}
 
     // Support for DOM Level 3 renameNode method.
     // Note: This only deals with part of the pb. CoreDocumentImpl
@@ -109,9 +102,9 @@
             if (colon1 != -1) {
                 String msg
                         = DOMMessageFormatter.formatMessage(
-                                DOMMessageFormatter.DOM_DOMAIN,
-                                "NAMESPACE_ERR",
-                                null);
+                            DOMMessageFormatter.DOM_DOMAIN,
+                            "NAMESPACE_ERR",
+                            null);
                 throw new DOMException(DOMException.NAMESPACE_ERR, msg);
             }
             if (!CoreDocumentImpl.isXMLName(name, ownerDocument.isXML11Version())) {
@@ -287,7 +280,7 @@
         if (attributes == null) {
             return "";
         }
-        Attr attr = (Attr) (attributes.getNamedItem(name));
+        Attr attr = (Attr)(attributes.getNamedItem(name));
         return (attr == null) ? "" : attr.getValue();
 
     } // getAttribute(String):String
@@ -307,7 +300,7 @@
         if (attributes == null) {
             return null;
         }
-        return (Attr) attributes.getNamedItem(name);
+        return (Attr)attributes.getNamedItem(name);
 
     } // getAttributeNode(String):Attr
 
@@ -453,7 +446,7 @@
      * readonly.
      */
     public Attr removeAttributeNode(Attr oldAttr)
-            throws DOMException {
+        throws DOMException {
 
         if (ownerDocument.errorChecking && isReadOnly()) {
             String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
@@ -491,36 +484,35 @@
      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
      * readonly.
      */
-    public void setAttribute(String name, String value) {
+        public void setAttribute(String name, String value) {
 
-        if (ownerDocument.errorChecking && isReadOnly()) {
-            String msg
-                    = DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "NO_MODIFICATION_ALLOWED_ERR",
-                            null);
-            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
-        }
+                if (ownerDocument.errorChecking && isReadOnly()) {
+                    String msg = DOMMessageFormatter.formatMessage(
+                                        DOMMessageFormatter.DOM_DOMAIN,
+                                        "NO_MODIFICATION_ALLOWED_ERR",
+                                        null);
+                    throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+                }
 
-        if (needsSyncData()) {
-            synchronizeData();
-        }
+                if (needsSyncData()) {
+                        synchronizeData();
+                }
 
-        Attr newAttr = getAttributeNode(name);
-        if (newAttr == null) {
-            newAttr = getOwnerDocument().createAttribute(name);
+                Attr newAttr = getAttributeNode(name);
+                if (newAttr == null) {
+                        newAttr = getOwnerDocument().createAttribute(name);
 
-            if (attributes == null) {
-                attributes = new AttributeMap(this, null);
-            }
+                        if (attributes == null) {
+                                attributes = new AttributeMap(this, null);
+                        }
 
-            newAttr.setNodeValue(value);
-            attributes.setNamedItem(newAttr);
-        } else {
-            newAttr.setNodeValue(value);
-        }
+                        newAttr.setNodeValue(value);
+                        attributes.setNamedItem(newAttr);
+                } else {
+                        newAttr.setNodeValue(value);
+                }
 
-    } // setAttribute(String,String)
+        } // setAttribute(String,String)
 
     /**
      * Add a new attribute/value pair, or replace the value of the existing
@@ -546,13 +538,13 @@
             if (isReadOnly()) {
                 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                 throw new DOMException(
-                        DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                        msg);
+                                     DOMException.NO_MODIFICATION_ALLOWED_ERR,
+                                     msg);
             }
 
             if (newAttr.getOwnerDocument() != ownerDocument) {
                 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
-                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+                    throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
             }
         }
 
@@ -589,7 +581,7 @@
             return "";
         }
 
-        Attr attr = (Attr) (attributes.getNamedItemNS(namespaceURI, localName));
+        Attr attr = (Attr)(attributes.getNamedItemNS(namespaceURI, localName));
         return (attr == null) ? "" : attr.getValue();
 
     } // getAttributeNS(String,String):String
@@ -633,41 +625,38 @@
      * @since WD-DOM-Level-2-19990923
      */
     public void setAttributeNS(String namespaceURI, String qualifiedName,
-            String value) {
-        if (ownerDocument.errorChecking && isReadOnly()) {
-            String msg
-                    = DOMMessageFormatter.formatMessage(
-                            DOMMessageFormatter.DOM_DOMAIN,
-                            "NO_MODIFICATION_ALLOWED_ERR",
-                            null);
-            throw new DOMException(
-                    DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                    msg);
-        }
-        if (needsSyncData()) {
-            synchronizeData();
-        }
-        int index = qualifiedName.indexOf(':');
-        String prefix, localName;
-        if (index < 0) {
-            prefix = null;
-            localName = qualifiedName;
-        } else {
-            prefix = qualifiedName.substring(0, index);
-            localName = qualifiedName.substring(index + 1);
-        }
-        Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
-        if (newAttr == null) {
+                                          String value) {
+                if (ownerDocument.errorChecking && isReadOnly()) {
+                    String msg = DOMMessageFormatter.formatMessage(
+                                        DOMMessageFormatter.DOM_DOMAIN,
+                                        "NO_MODIFICATION_ALLOWED_ERR",
+                                        null);
+                    throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+                }
+                if (needsSyncData()) {
+                        synchronizeData();
+                }
+                int index = qualifiedName.indexOf(':');
+                String prefix, localName;
+                if (index < 0) {
+                        prefix = null;
+                        localName = qualifiedName;
+                } else {
+                        prefix = qualifiedName.substring(0, index);
+                        localName = qualifiedName.substring(index + 1);
+                }
+                Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
+                if (newAttr == null) {
             // REVISIT: this is not efficient, we are creating twice the same
             //          strings for prefix and localName.
-            newAttr = getOwnerDocument().createAttributeNS(
-                    namespaceURI,
-                    qualifiedName);
-            if (attributes == null) {
-                attributes = new AttributeMap(this, null);
-            }
-            newAttr.setNodeValue(value);
-            attributes.setNamedItemNS(newAttr);
+                        newAttr = getOwnerDocument().createAttributeNS(
+                                        namespaceURI,
+                                        qualifiedName);
+                        if (attributes == null) {
+                                attributes = new AttributeMap(this, null);
+                        }
+                        newAttr.setNodeValue(value);
+                        attributes.setNamedItemNS(newAttr);
                 }
                 else {
             if (newAttr instanceof AttrNSImpl){
@@ -693,12 +682,12 @@
                 // This case is not defined by the DOM spec, we choose
                 // to create a new attribute in this case and remove an old one from the tree
                 // note this might cause events to be propagated or user data to be lost
-                newAttr = new AttrNSImpl((CoreDocumentImpl)getOwnerDocument(), namespaceURI, qualifiedName, localName);
+                newAttr = ((CoreDocumentImpl)getOwnerDocument()).createAttributeNS(namespaceURI, qualifiedName, localName);
                 attributes.setNamedItemNS(newAttr);
             }
 
-            newAttr.setNodeValue(value);
-        }
+                        newAttr.setNodeValue(value);
+                }
 
     } // setAttributeNS(String,String,String)
 
@@ -753,7 +742,7 @@
         if (attributes == null) {
             return null;
         }
-        return (Attr) attributes.getNamedItemNS(namespaceURI, localName);
+        return (Attr)attributes.getNamedItemNS(namespaceURI, localName);
 
     } // getAttributeNodeNS(String,String):Attr
 
@@ -788,9 +777,9 @@
         if (ownerDocument.errorChecking) {
             if (isReadOnly()) {
                 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
-                throw new DOMException(
-                        DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                        msg);
+                    throw new DOMException(
+                                     DOMException.NO_MODIFICATION_ALLOWED_ERR,
+                                     msg);
             }
             if (newAttr.getOwnerDocument() != ownerDocument) {
                 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
@@ -807,8 +796,8 @@
     } // setAttributeNodeNS(Attr):Attr
 
     /**
-     * NON-DOM: sets attribute node for this element
-     */
+      * NON-DOM: sets attribute node for this element
+      */
     protected int setXercesAttributeNode(Attr attr) {
 
         if (needsSyncData()) {
@@ -823,8 +812,8 @@
     }
 
     /**
-     * NON-DOM: get inded of an attribute
-     */
+      * NON-DOM: get inded of an attribute
+      */
     protected int getXercesAttribute(String namespaceURI, String localName) {
 
         if (needsSyncData()) {
@@ -879,7 +868,7 @@
      * @since WD-DOM-Level-2-19990923
      */
     public NodeList getElementsByTagNameNS(String namespaceURI,
-            String localName) {
+                                           String localName) {
         return new DeepNodeListImpl(this, namespaceURI, localName);
     }
 
@@ -911,7 +900,7 @@
                     }
                 } else {
                     Node n2 = map2.getNamedItemNS(n1.getNamespaceURI(),
-                            n1.getLocalName());
+                                                  n1.getLocalName());
                     if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
                         return false;
                     }
@@ -930,14 +919,15 @@
         }
         if (ownerDocument.errorChecking) {
             if (isReadOnly()) {
-                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                 throw new DOMException(
-                        DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                        msg);
+                        DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
             }
 
             if (at.getOwnerElement() != this) {
-                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
             }
         }
@@ -959,22 +949,21 @@
         Attr at = getAttributeNode(name);
 
         if (at == null) {
-            String msg = DOMMessageFormatter.formatMessage(
-                    DOMMessageFormatter.DOM_DOMAIN,
-                    "NOT_FOUND_ERR", null);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
-        }
+                }
 
         if (ownerDocument.errorChecking) {
             if (isReadOnly()) {
-                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
-                throw new DOMException(
-                        DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                        msg);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
             }
 
             if (at.getOwnerElement() != this) {
-                String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
             }
         }
@@ -991,7 +980,7 @@
      * DOM Level 3: register the given attribute node as an ID attribute
      */
     public void setIdAttributeNS(String namespaceURI, String localName,
-            boolean makeId) {
+                                    boolean makeId) {
         if (needsSyncData()) {
             synchronizeData();
         }
@@ -1002,19 +991,18 @@
         Attr at = getAttributeNodeNS(namespaceURI, localName);
 
         if (at == null) {
-            String msg = DOMMessageFormatter.formatMessage(
-                    DOMMessageFormatter.DOM_DOMAIN,
-                    "NOT_FOUND_ERR", null);
+                String msg = DOMMessageFormatter.formatMessage(
+                        DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
-        }
+                }
 
-        if (ownerDocument.errorChecking) {
+                if (ownerDocument.errorChecking) {
             if (isReadOnly()) {
                 String msg = DOMMessageFormatter.formatMessage(
                         DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                 throw new DOMException(
-                        DOMException.NO_MODIFICATION_ALLOWED_ERR,
-                        msg);
+                                     DOMException.NO_MODIFICATION_ALLOWED_ERR,
+                                     msg);
             }
 
             if (at.getOwnerElement() != this) {
@@ -1029,14 +1017,14 @@
         } else {
             ownerDocument.putIdentifier(at.getValue(), this);
         }
-    }
+   }
 
     /**
      * @see org.w3c.dom.TypeInfo#getTypeName()
      */
-    public String getTypeName() {
+     public String getTypeName() {
         return null;
-    }
+     }
 
     /**
      * @see org.w3c.dom.TypeInfo#getTypeNamespace()
@@ -1059,17 +1047,16 @@
      * reference type
      */
     public boolean isDerivedFrom(String typeNamespaceArg,
-            String typeNameArg,
-            int derivationMethod) {
+                                 String typeNameArg,
+                                 int derivationMethod) {
 
         return false;
     }
 
-    /**
-     * Method getSchemaTypeInfo.
-     *
-     * @return TypeInfo
-     */
+        /**
+         * Method getSchemaTypeInfo.
+         * @return TypeInfo
+         */
     public TypeInfo getSchemaTypeInfo() {
         if (needsSyncData()) {
             synchronizeData();
@@ -1159,8 +1146,7 @@
         if (doctype == null) {
             return null;
         }
-        ElementDefinitionImpl eldef
-                = (ElementDefinitionImpl) doctype.getElements()
+        ElementDefinitionImpl eldef = (ElementDefinitionImpl)doctype.getElements()
                 .getNamedItem(getNodeName());
         if (eldef == null) {
             return null;
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementNSImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementNSImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -86,13 +86,13 @@
 
         private void setName(String namespaceURI, String qname) {
 
-                String prefix;
-                // DOM Level 3: namespace URI is never empty string.
-                this.namespaceURI = namespaceURI;
-                if (namespaceURI != null) {
+            String prefix;
+            // DOM Level 3: namespace URI is never empty string.
+            this.namespaceURI = namespaceURI;
+            if (namespaceURI != null) {
             //convert the empty string to 'null'
-                        this.namespaceURI =     (namespaceURI.length() == 0) ? null : namespaceURI;
-                }
+            this.namespaceURI = (namespaceURI.length() == 0) ? null : namespaceURI;
+            }
 
         int colon1, colon2 ;
 
@@ -190,37 +190,6 @@
         reconcileDefaultAttributes();
     }
 
-    /**
-     * NON-DOM: resets this node and sets specified values for the node
-     *
-     * @param ownerDocument
-     * @param namespaceURI
-     * @param qualifiedName
-     * @param localName
-     */
-    protected void setValues (CoreDocumentImpl ownerDocument,
-                            String namespaceURI, String qualifiedName,
-                            String localName){
-
-        // remove children first
-        firstChild = null;
-        previousSibling = null;
-        nextSibling = null;
-        fNodeListCache = null;
-
-        // set owner document
-        attributes = null;
-        super.flags = 0;
-        setOwnerDocument(ownerDocument);
-
-        // synchronizeData will initialize attributes
-        needsSyncData(true);
-        super.name = qualifiedName;
-        this.localName = localName;
-        this.namespaceURI = namespaceURI;
-
-    }
-
     //
     // Node methods
     //
@@ -340,88 +309,13 @@
         return localName;
     }
 
-
-   /**
-     * DOM Level 3 WD - Experimental.
-     * Retrieve baseURI
+    /**
+     * NON-DOM
+     * Returns the xml:base attribute.
      */
-    public String getBaseURI() {
-
-        if (needsSyncData()) {
-            synchronizeData();
-        }
-        // Absolute base URI is computed according to XML Base (http://www.w3.org/TR/xmlbase/#granularity)
-
-        // 1.  the base URI specified by an xml:base attribute on the element, if one exists
-
-        if (attributes != null) {
-            Attr attrNode = (Attr)attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
-            if (attrNode != null) {
-                String uri =  attrNode.getNodeValue();
-                if (uri.length() != 0 ) {// attribute value is always empty string
-                    try {
-                        uri = new URI(uri).toString();
-                    }
-                    catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e) {
-                        // This may be a relative URI.
-
-                        // Start from the base URI of the parent, or if this node has no parent, the owner node.
-                        NodeImpl parentOrOwner = (parentNode() != null) ? parentNode() : ownerNode;
-
-                        // Make any parentURI into a URI object to use with the URI(URI, String) constructor.
-                        String parentBaseURI = (parentOrOwner != null) ? parentOrOwner.getBaseURI() : null;
-
-                        if (parentBaseURI != null) {
-                            try {
-                                uri = new URI(new URI(parentBaseURI), uri).toString();
-                            }
-                            catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException ex){
-                                // This should never happen: parent should have checked the URI and returned null if invalid.
-                                return null;
-                            }
-                            return uri;
-                        }
-                        // REVISIT: what should happen in this case?
-                        return null;
-                    }
-                    return uri;
-                }
-            }
-        }
-
-        //2.the base URI of the element's parent element within the document or external entity,
-        //if one exists
-        String parentElementBaseURI = (this.parentNode() != null) ? this.parentNode().getBaseURI() : null ;
-        //base URI of parent element is not null
-        if(parentElementBaseURI != null){
-            try {
-                //return valid absolute base URI
-               return new URI(parentElementBaseURI).toString();
-            }
-            catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
-                // REVISIT: what should happen in this case?
-                return null;
-            }
-        }
-        //3. the base URI of the document entity or external entity containing the element
-
-        String baseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null ;
-
-        if(baseURI != null){
-            try {
-                //return valid absolute base URI
-               return new URI(baseURI).toString();
-            }
-            catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
-                // REVISIT: what should happen in this case?
-                return null;
-            }
-        }
-
-        return null;
-
-    }
-
+    protected Attr getXMLBaseAttribute() {
+        return (Attr) attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
+    } // getXMLBaseAttribute():Attr
 
     /**
      * @see org.w3c.dom.TypeInfo#getTypeName()
@@ -452,12 +346,12 @@
      * Checks if a type is derived from another by restriction. See:
      * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
      *
-     * @param ancestorNS
+     * @param typeNamespaceArg
      *        The namspace of the ancestor type declaration
-     * @param ancestorName
+     * @param typeNameArg
      *        The name of the ancestor type declaration
-     * @param type
-     *        The reference type definition
+     * @param derivationMethod
+     *        The derivation method
      *
      * @return boolean True if the type is derived by restriciton for the
      *         reference type
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NodeImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NodeImpl.java	Fri May 03 14:59:32 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.
  */
  /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -78,6 +79,7 @@
  * @author Arnaud  Le Hors, IBM
  * @author Joe Kesselman, IBM
  * @since  PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  */
 public abstract class NodeImpl
     implements Node, NodeList, EventTarget, Cloneable, Serializable{
@@ -122,15 +124,6 @@
      */
     public static final short TREE_POSITION_DISCONNECTED = 0x00;
 
-
-    // DocumentPosition
-    public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
-    public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
-    public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
-    public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
-    public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
-    public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
-
     /** Serialization version. */
     static final long serialVersionUID = -6316591992167219696L;
 
@@ -324,7 +317,7 @@
      * NON-DOM
      * set the ownerDocument of this node
      */
-    void setOwnerDocument(CoreDocumentImpl doc) {
+    protected void setOwnerDocument(CoreDocumentImpl doc) {
         if (needsSyncData()) {
             synchronizeData();
         }
@@ -559,7 +552,7 @@
      * @see ParentNode
      *
      * @return org.w3c.dom.Node
-     * @param Index int
+     * @param index int
      */
     public Node item(int index) {
         return null;
@@ -976,9 +969,7 @@
           return 0;
 
         // check if other is from a different implementation
-        try {
-            NodeImpl node = (NodeImpl) other;
-        } catch (ClassCastException e) {
+        if (other != null && !(other instanceof NodeImpl)) {
             // other comes from a different implementation
             String msg = DOMMessageFormatter.formatMessage(
                DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
@@ -1041,7 +1032,7 @@
             otherDepth +=1;
             if (node == this)
               // The other node is a descendent of the reference node.
-              return (DOCUMENT_POSITION_IS_CONTAINED |
+              return (DOCUMENT_POSITION_CONTAINED_BY |
                       DOCUMENT_POSITION_FOLLOWING);
             otherAncestor = node;
         }
@@ -1131,7 +1122,7 @@
           case Node.NOTATION_NODE:
           case Node.ENTITY_NODE: {
           DocumentType container = thisOwnerDoc.getDoctype();
-            if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
+            if (container == this) return (DOCUMENT_POSITION_CONTAINED_BY |
                                           DOCUMENT_POSITION_FOLLOWING);
             otherNode = otherAncestor = thisOwnerDoc;
             break;
@@ -1139,7 +1130,7 @@
           case Node.DOCUMENT_TYPE_NODE: {
             if (thisNode == otherOwnerDoc)
               return (DOCUMENT_POSITION_FOLLOWING |
-                      DOCUMENT_POSITION_IS_CONTAINED);
+                      DOCUMENT_POSITION_CONTAINED_BY);
             else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
               return (DOCUMENT_POSITION_PRECEDING);
             break;
@@ -1153,7 +1144,7 @@
                   // The other node is a descendent of the reference
                   // node's element
                   return DOCUMENT_POSITION_FOLLOWING |
-                         DOCUMENT_POSITION_IS_CONTAINED;
+                         DOCUMENT_POSITION_CONTAINED_BY;
                 otherAncestor = node;
             }
 
@@ -1302,8 +1293,8 @@
         return getNodeValue();  // overriden in some subclasses
     }
 
-    // internal method taking a StringBuffer in parameter
-    void getTextContent(StringBuffer buf) throws DOMException {
+    // internal method taking a StringBuilder in parameter
+    void getTextContent(StringBuilder buf) throws DOMException {
         String content = getNodeValue();
         if (content != null) {
             buf.append(content);
@@ -1425,7 +1416,11 @@
             return false;
         }
         case Node.DOCUMENT_NODE:{
-                return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
+                Element docElement = ((Document)this).getDocumentElement();
+                if (docElement != null) {
+                    return docElement.isDefaultNamespace(namespaceURI);
+                }
+                return false;
             }
 
         case Node.ENTITY_NODE :
@@ -1475,12 +1470,15 @@
 
         switch (type) {
         case Node.ELEMENT_NODE: {
-
-                String namespace = this.getNamespaceURI(); // to flip out children
+                this.getNamespaceURI(); // to flip out children
                 return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
             }
         case Node.DOCUMENT_NODE:{
-                return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
+                Element docElement = ((Document)this).getDocumentElement();
+                if (docElement != null) {
+                    return docElement.lookupPrefix(namespaceURI);
+                }
+                return null;
             }
 
         case Node.ENTITY_NODE :
@@ -1511,8 +1509,8 @@
      * Look up the namespace URI associated to the given prefix, starting from this node.
      * Use lookupNamespaceURI(null) to lookup the default namespace
      *
-     * @param namespaceURI
-     * @return th URI for the namespace
+     * @param specifiedPrefix
+     * @return the URI for the namespace
      * @since DOM Level 3
      */
     public String lookupNamespaceURI(String specifiedPrefix) {
@@ -1537,20 +1535,20 @@
                     int length = map.getLength();
                     for (int i=0;i<length;i++) {
                         Node attr = map.item(i);
-                        String attrPrefix = attr.getPrefix();
-                        String value = attr.getNodeValue();
                         namespace = attr.getNamespaceURI();
                         if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
+                            String attrPrefix = attr.getPrefix();
+                            String value = attr.getNodeValue();
                             // at this point we are dealing with DOM Level 2 nodes only
                             if (specifiedPrefix == null &&
                                 attr.getNodeName().equals("xmlns")) {
                                 // default namespace
-                                return value;
+                                return value.length() > 0 ? value : null;
                             } else if (attrPrefix !=null &&
                                        attrPrefix.equals("xmlns") &&
                                        attr.getLocalName().equals(specifiedPrefix)) {
                                 // non default namespace
-                                return value;
+                                return value.length() > 0 ? value : null;
                             }
                         }
                     }
@@ -1565,7 +1563,11 @@
 
             }
         case Node.DOCUMENT_NODE : {
-                return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
+                Element docElement = ((Document)this).getDocumentElement();
+                if (docElement != null) {
+                    return docElement.lookupNamespaceURI(specifiedPrefix);
+                }
+                return null;
             }
         case Node.ENTITY_NODE :
         case Node.NOTATION_NODE:
@@ -1591,15 +1593,14 @@
         }
     }
 
-
-    Node getElementAncestor (Node currentNode){
+    Node getElementAncestor(Node currentNode) {
         Node parent = currentNode.getParentNode();
-        if (parent != null) {
+        while (parent != null) {
             short type = parent.getNodeType();
             if (type == Node.ELEMENT_NODE) {
                 return parent;
             }
-            return getElementAncestor(parent);
+            parent = parent.getParentNode();
         }
         return null;
     }
@@ -1624,10 +1625,10 @@
             int length = map.getLength();
             for (int i=0;i<length;i++) {
                 Node attr = map.item(i);
-                String attrPrefix = attr.getPrefix();
-                String value = attr.getNodeValue();
                 namespace = attr.getNamespaceURI();
                 if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
+                    String attrPrefix = attr.getPrefix();
+                    String value = attr.getNodeValue();
                     // DOM Level 2 nodes
                     if (((attr.getNodeName().equals("xmlns")) ||
                          (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
@@ -1687,9 +1688,6 @@
      * <code>Text</code> nodes, as well as any user data or event listeners
      * registered on the nodes.
      * @param arg The node to compare equality with.
-     * @param deep If <code>true</code>, recursively compare the subtrees; if
-     *   <code>false</code>, compare only the nodes themselves (and its
-     *   attributes, if it is an <code>Element</code>).
      * @return If the nodes, and possibly subtrees are equal,
      *   <code>true</code> otherwise <code>false</code>.
      * @since DOM Level 3
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/PSVIDOMImplementationImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/PSVIDOMImplementationImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -21,11 +21,8 @@
 
 package com.sun.org.apache.xerces.internal.dom;
 
-import org.w3c.dom.DOMException;
 import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
 import org.w3c.dom.DocumentType;
-import org.w3c.dom.Element;
 
 /**
  * The DOMImplementation class is description of a particular
@@ -40,7 +37,7 @@
  *
  * @since  PR-DOM-Level-1-19980818.
  */
-public class PSVIDOMImplementationImpl extends CoreDOMImplementationImpl {
+public class PSVIDOMImplementationImpl extends DOMImplementationImpl {
 
     //
     // Data
@@ -49,7 +46,7 @@
     // static
 
     /** Dom implementation singleton. */
-    static PSVIDOMImplementationImpl singleton = new PSVIDOMImplementationImpl();
+    static final PSVIDOMImplementationImpl singleton = new PSVIDOMImplementationImpl();
 
     //
     // Public methods
@@ -84,42 +81,12 @@
                feature.equalsIgnoreCase("psvi");
     } // hasFeature(String,String):boolean
 
-    /**
-     * Introduced in DOM Level 2. <p>
-     *
-     * Creates an XML Document object of the specified type with its document
-     * element.
-     *
-     * @param namespaceURI     The namespace URI of the document
-     *                         element to create, or null.
-     * @param qualifiedName    The qualified name of the document
-     *                         element to create.
-     * @param doctype          The type of document to be created or null.<p>
-     *
-     *                         When doctype is not null, its
-     *                         Node.ownerDocument attribute is set to
-     *                         the document being created.
-     * @return Document        A new Document object.
-     * @throws DOMException    WRONG_DOCUMENT_ERR: Raised if doctype has
-     *                         already been used with a different document.
-     * @since WD-DOM-Level-2-19990923
-     */
-    public Document           createDocument(String namespaceURI,
-                                             String qualifiedName,
-                                             DocumentType doctype)
-                                             throws DOMException
-    {
-        if (doctype != null && doctype.getOwnerDocument() != null) {
-            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
-                                   DOMMessageFormatter.formatMessage(
-                                   DOMMessageFormatter.XML_DOMAIN,
-                                                       "WRONG_DOCUMENT_ERR", null));
-        }
-        DocumentImpl doc = new PSVIDocumentImpl(doctype);
-        Element e = doc.createElementNS( namespaceURI, qualifiedName);
-        doc.appendChild(e);
-        return doc;
+    //
+    // Protected methods
+    //
+
+    protected CoreDocumentImpl createDocument(DocumentType doctype) {
+        return new PSVIDocumentImpl(doctype);
     }
 
-
-} // class DOMImplementationImpl
+} // class PSVIDOMImplementationImpl
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ParentNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ParentNode.java	Fri May 03 14:59:32 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.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -68,6 +68,7 @@
  * @author Arnaud  Le Hors, IBM
  * @author Joe Kesselman, IBM
  * @author Andy Clark, IBM
+ * @LastModified: Apr 2019
  */
 public abstract class ParentNode
     extends ChildNode {
@@ -174,18 +175,16 @@
      * NON-DOM
      * set the ownerDocument of this node and its children
      */
-    void setOwnerDocument(CoreDocumentImpl doc) {
+    protected void setOwnerDocument(CoreDocumentImpl doc) {
         if (needsSyncChildren()) {
             synchronizeChildren();
         }
-       for (ChildNode child = firstChild;
-             child != null; child = child.nextSibling) {
-             child.setOwnerDocument(doc);
-        }
-        /* setting the owner document of self, after it's children makes the
-           data of children available to the new document. */
         super.setOwnerDocument(doc);
         ownerDocument = doc;
+        for (ChildNode child = firstChild;
+        child != null; child = child.nextSibling) {
+            child.setOwnerDocument(doc);
+        }
     }
 
     /**
@@ -368,16 +367,14 @@
             // Prevent cycles in the tree
             // newChild cannot be ancestor of this Node,
             // and actually cannot be this
-            if (ownerDocument.ancestorChecking) {
-                boolean treeSafe = true;
-                for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode())
-                {
-                    treeSafe = newChild != a;
-                }
-                if(!treeSafe) {
-                    throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
-                                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
-                }
+            boolean treeSafe = true;
+            for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode())
+            {
+                treeSafe = newChild != a;
+            }
+            if(!treeSafe) {
+                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+                            DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
             }
         }
 
@@ -509,6 +506,9 @@
         // notify document
         ownerDocument.removingNode(this, oldInternal, replace);
 
+        // Save previous sibling for normalization checking.
+        final ChildNode oldPreviousSibling = oldInternal.previousSibling();
+
         // update cached length if we have any
         if (fNodeListCache != null) {
             if (fNodeListCache.fLength != -1) {
@@ -519,7 +519,7 @@
                 // move the cache to its (soon former) previous sibling
                 if (fNodeListCache.fChild == oldInternal) {
                     fNodeListCache.fChildIndex--;
-                    fNodeListCache.fChild = oldInternal.previousSibling();
+                    fNodeListCache.fChild = oldPreviousSibling;
                 } else {
                     // otherwise just invalidate the cache
                     fNodeListCache.fChildIndex = -1;
@@ -550,9 +550,6 @@
             }
         }
 
-        // Save previous sibling for normalization checking.
-        ChildNode oldPreviousSibling = oldInternal.previousSibling();
-
         // Remove oldInternal's references to tree
         oldInternal.ownerNode       = ownerDocument;
         oldInternal.isOwned(false);
@@ -624,20 +621,15 @@
             if (next == null) {
                 return hasTextContent(child) ? ((NodeImpl) child).getTextContent() : "";
             }
-            if (fBufferStr == null){
-                fBufferStr = new StringBuffer();
-            }
-            else {
-                fBufferStr.setLength(0);
-            }
-            getTextContent(fBufferStr);
-            return fBufferStr.toString();
+            StringBuilder buf = new StringBuilder();
+            getTextContent(buf);
+            return buf.toString();
         }
         return "";
     }
 
-    // internal method taking a StringBuffer in parameter
-    void getTextContent(StringBuffer buf) throws DOMException {
+    // internal method taking a StringBuilder in parameter
+    void getTextContent(StringBuilder buf) throws DOMException {
         Node child = getFirstChild();
         while (child != null) {
             if (hasTextContent(child)) {
@@ -684,6 +676,9 @@
     private int nodeListGetLength() {
 
         if (fNodeListCache == null) {
+            if (needsSyncChildren()) {
+                synchronizeChildren();
+            }
             // get rid of trivial cases
             if (firstChild == null) {
                 return 0;
@@ -733,6 +728,9 @@
     private Node nodeListItem(int index) {
 
         if (fNodeListCache == null) {
+            if (needsSyncChildren()) {
+                synchronizeChildren();
+            }
             // get rid of trivial case
             if (firstChild == lastChild()) {
                 return index == 0 ? firstChild : null;
@@ -870,7 +868,7 @@
         Node child1 = getFirstChild();
         Node child2 = arg.getFirstChild();
         while (child1 != null && child2 != null) {
-            if (!((NodeImpl) child1).isEqualNode(child2)) {
+            if (!child1.isEqualNode(child2)) {
                 return false;
             }
             child1 = child1.getNextSibling();
@@ -997,7 +995,7 @@
     /** Serialize object. */
     private void writeObject(ObjectOutputStream out) throws IOException {
 
-        // synchronize chilren
+        // synchronize children
         if (needsSyncChildren()) {
             synchronizeChildren();
         }
@@ -1022,7 +1020,7 @@
     /*
      * a class to store some user data along with its handler
      */
-    protected class UserDataRecord implements Serializable {
+    class UserDataRecord implements Serializable {
         /** Serialization version. */
         private static final long serialVersionUID = 3258126977134310455L;
 
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/TextImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/TextImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,5 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -42,6 +41,7 @@
  * @xerces.internal
  *
  * @since  PR-DOM-Level-1-19980818.
+ * @LastModified: Apr 2019
  */
 public class TextImpl
     extends CharacterDataImpl
@@ -146,37 +146,32 @@
             synchronizeData();
         }
 
-        if (fBufferStr == null){
-            fBufferStr = new StringBuffer();
-        }
-        else {
-            fBufferStr.setLength(0);
-        }
+        StringBuilder buffer = new StringBuilder();
         if (data != null && data.length() != 0) {
-            fBufferStr.append(data);
+            buffer.append(data);
         }
 
-        //concatenate text of logically adjacent text nodes to the left of this node in the tree
-        getWholeTextBackward(this.getPreviousSibling(), fBufferStr, this.getParentNode());
-        String temp = fBufferStr.toString();
+        // concatenate text of logically adjacent text nodes to the left of this node in the tree
+        getWholeTextBackward(this.getPreviousSibling(), buffer, this.getParentNode());
+        String temp = buffer.toString();
 
-        //clear buffer
-        fBufferStr.setLength(0);
+        // clear buffer
+        buffer.setLength(0);
 
-        //concatenate text of logically adjacent text nodes to the right of this node in the tree
-        getWholeTextForward(this.getNextSibling(), fBufferStr, this.getParentNode());
+        // concatenate text of logically adjacent text nodes to the right of this node in the tree
+        getWholeTextForward(this.getNextSibling(), buffer, this.getParentNode());
 
-        return temp + fBufferStr.toString();
+        return temp + buffer.toString();
 
     }
 
     /**
-     * internal method taking a StringBuffer in parameter and inserts the
+     * internal method taking a StringBuilder in parameter and inserts the
      * text content at the start of the buffer
      *
      * @param buf
      */
-    protected void insertTextContent(StringBuffer buf) throws DOMException {
+    protected void insertTextContent(StringBuilder buf) throws DOMException {
          String content = getNodeValue();
          if (content != null) {
              buf.insert(0, content);
@@ -193,7 +188,7 @@
      *         other than EntityRef, Text, CDATA is encountered, otherwise
      *         return false
      */
-    private boolean getWholeTextForward(Node node, StringBuffer buffer, Node parent){
+    private boolean getWholeTextForward(Node node, StringBuilder buffer, Node parent){
         // boolean to indicate whether node is a child of an entity reference
         boolean inEntRef = false;
 
@@ -240,7 +235,7 @@
      *         other than EntityRef, Text, CDATA is encountered, otherwise
      *         return false
      */
-    private boolean getWholeTextBackward(Node node, StringBuffer buffer, Node parent){
+    private boolean getWholeTextBackward(Node node, StringBuilder buffer, Node parent){
 
         // boolean to indicate whether node is a child of an entity reference
         boolean inEntRef = false;
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -111,7 +111,7 @@
  * @author Elena Litani IBM
  * @author Andy Clark IBM
  * @author Neeraj Bajaj, Sun Microsystems, inc.
- * @LastModified: Nov 2017
+ * @LastModified: Apr 2019
  */
 public class XMLSchemaValidator
     implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler, XSElementDeclHelper {
@@ -2429,7 +2429,7 @@
                             fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth());
                         // nothing to do if nothing matched, or if not all
                         // fields are present.
-                        if (values != null && values.fValuesCount == values.fFieldCount)
+                        if (values != null && values.fHasValue)
                             values.endDocumentFragment();
                     }
                 }
@@ -3718,6 +3718,7 @@
 
         /** Current data value count. */
         protected int fValuesCount;
+        protected boolean fHasValue = false;
 
         /** global data */
         public final Vector<Object> fValues = new Vector<>();
@@ -3885,6 +3886,7 @@
             }
             else {
                 fValuesCount++;
+                fHasValue = true;
             }
             fLocalValues[i] = actualValue;
             fLocalValueTypes[i] = valueType;
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/ParserConfigurationSettings.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/ParserConfigurationSettings.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -23,11 +23,11 @@
 import com.sun.org.apache.xerces.internal.impl.Constants;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * This class implements the basic operations for managing parser
@@ -42,6 +42,7 @@
  *
  * @author Andy Clark, IBM
  *
+ * @LastModified: Apr 2019
  */
 public class ParserConfigurationSettings
     implements XMLComponentManager {
@@ -56,13 +57,13 @@
     // data
 
     /** Recognized properties. */
-    protected Set<String> fRecognizedProperties;
+    protected List<String> fRecognizedProperties;
 
     /** Properties. */
     protected Map<String, Object> fProperties;
 
     /** Recognized features. */
-    protected Set<String> fRecognizedFeatures;
+    protected List<String> fRecognizedFeatures;
 
     /** Features. */
     protected Map<String, Boolean> fFeatures;
@@ -86,8 +87,8 @@
     public ParserConfigurationSettings(XMLComponentManager parent) {
 
         // create storage for recognized features and properties
-        fRecognizedFeatures = new HashSet<>();
-        fRecognizedProperties = new HashSet<>();
+        fRecognizedFeatures = new ArrayList<>();
+        fRecognizedProperties = new ArrayList<>();
 
         // create table for features and properties
         fFeatures = new HashMap<>();
@@ -195,7 +196,7 @@
      *                                   a critical error.
      */
     @Override
-    public final boolean getFeature(String featureId)
+    public boolean getFeature(String featureId)
         throws XMLConfigurationException {
 
         FeatureState state = getFeatureState(featureId);
@@ -222,7 +223,7 @@
             FeatureState checkState = checkFeature(featureId);
             if (checkState.isExceptional()) {
                 return checkState;
-            }
+        }
             return FeatureState.is(false);
         }
         return FeatureState.is(state);
@@ -241,7 +242,7 @@
      *                                   a critical error.
      */
     @Override
-    public final Object getProperty(String propertyId)
+    public Object getProperty(String propertyId)
         throws XMLConfigurationException {
 
         PropertyState state = getPropertyState(propertyId);
@@ -270,7 +271,7 @@
             PropertyState state = checkProperty(propertyId);
             if (state.isExceptional()) {
                 return state;
-            }
+        }
         }
 
         return PropertyState.is(propertyValue);
@@ -325,7 +326,7 @@
                 PropertyState state = fParentSettings.getPropertyState(propertyId);
                 if (state.isExceptional()) {
                     return state;
-                }
+            }
             }
             else {
                 return PropertyState.NOT_RECOGNIZED;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri May 03 14:59:32 2019 -0400
@@ -1559,6 +1559,10 @@
             return ClassFile.CONSTANT_Fieldref;
         }
 
+        public MethodHandleSymbol asMethodHandle(boolean getter) {
+            return new MethodHandleSymbol(this, getter);
+        }
+
         /** Clone this symbol with new owner.
          */
         public VarSymbol clone(Symbol newOwner) {
@@ -2110,27 +2114,39 @@
     public static class MethodHandleSymbol extends MethodSymbol implements LoadableConstant {
 
         private Symbol refSym;
+        private boolean getter;
 
         public MethodHandleSymbol(Symbol msym) {
+            this(msym, false);
+        }
+
+        public MethodHandleSymbol(Symbol msym, boolean getter) {
             super(msym.flags_field, msym.name, msym.type, msym.owner);
             this.refSym = msym;
+            this.getter = getter;
         }
 
         /**
          * Returns the kind associated with this method handle.
          */
         public int referenceKind() {
-            if (refSym.isConstructor()) {
-                return ClassFile.REF_newInvokeSpecial;
+            if (refSym.kind == VAR) {
+                return getter ?
+                        refSym.isStatic() ? ClassFile.REF_getStatic : ClassFile.REF_getField :
+                        refSym.isStatic() ? ClassFile.REF_putStatic : ClassFile.REF_putField;
             } else {
-                if (refSym.isStatic()) {
-                    return ClassFile.REF_invokeStatic;
-                } else if ((refSym.flags() & PRIVATE) != 0) {
-                    return ClassFile.REF_invokeSpecial;
-                } else if (refSym.enclClass().isInterface()) {
-                    return ClassFile.REF_invokeInterface;
+                if (refSym.isConstructor()) {
+                    return ClassFile.REF_newInvokeSpecial;
                 } else {
-                    return ClassFile.REF_invokeVirtual;
+                    if (refSym.isStatic()) {
+                        return ClassFile.REF_invokeStatic;
+                    } else if ((refSym.flags() & PRIVATE) != 0) {
+                        return ClassFile.REF_invokeSpecial;
+                    } else if (refSym.enclClass().isInterface()) {
+                        return ClassFile.REF_invokeInterface;
+                    } else {
+                        return ClassFile.REF_invokeVirtual;
+                    }
                 }
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri May 03 14:59:32 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
@@ -566,7 +566,7 @@
                 Assert.checkNonNull(jarFSProvider, "should have been caught before!");
                 this.fileSystem = jarFSProvider.newFileSystem(archivePath, env);
             } else {
-                this.fileSystem = FileSystems.newFileSystem(archivePath, null);
+                this.fileSystem = FileSystems.newFileSystem(archivePath, (ClassLoader)null);
             }
             packages = new HashMap<>();
             for (Path root : fileSystem.getRootDirectories()) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri May 03 14:59:32 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
@@ -379,7 +379,7 @@
                         /* Not a recognized extension; open it to see if
                          it looks like a valid zip file. */
                         try {
-                            FileSystems.newFileSystem(file, null).close();
+                            FileSystems.newFileSystem(file, (ClassLoader)null).close();
                             if (warn) {
                                 log.warning(Lint.LintCategory.PATH,
                                             Warnings.UnexpectedArchiveFile(file));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Fri May 03 14:59:32 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
@@ -113,7 +113,7 @@
         SUPPORTED_JAVA_PLATFORM_VERSIONS = new TreeSet<>(NUMERICAL_COMPARATOR);
         Path ctSymFile = findCtSym();
         if (Files.exists(ctSymFile)) {
-            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, null);
+            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, (ClassLoader)null);
                  DirectoryStream<Path> dir =
                          Files.newDirectoryStream(fs.getRootDirectories().iterator().next())) {
                 for (Path section : dir) {
@@ -252,7 +252,7 @@
                 try {
                     FileSystem fs = ctSym2FileSystem.get(file);
                     if (fs == null) {
-                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null));
+                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, (ClassLoader)null));
                     }
 
                     Path root = fs.getRootDirectories().iterator().next();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri May 03 14:59:32 2019 -0400
@@ -444,7 +444,14 @@
             } catch(ServiceConfigurationError sce) {
                 log.error(Errors.ProcBadConfigFile(sce.getLocalizedMessage()));
                 throw new Abort(sce);
+            } catch (UnsupportedClassVersionError ucve) {
+                log.error(Errors.ProcCantLoadClass(ucve.getLocalizedMessage()));
+                throw new Abort(ucve);
+            } catch (ClassFormatError cfe) {
+                log.error(Errors.ProcCantLoadClass(cfe.getLocalizedMessage()));
+                throw new Abort(cfe);
             } catch (Throwable t) {
+                log.error(Errors.ProcBadConfigFile(t.getLocalizedMessage()));
                 throw new Abort(t);
             }
         }
@@ -461,6 +468,7 @@
                 log.error(Errors.ProcBadConfigFile(sce.getLocalizedMessage()));
                 throw new Abort(sce);
             } catch (Throwable t) {
+                log.error(Errors.ProcBadConfigFile(t.getLocalizedMessage()));
                 throw new Abort(t);
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java	Fri May 03 14:59:32 2019 -0400
@@ -424,7 +424,8 @@
         private void printModifiers(Element e) {
             ElementKind kind = e.getKind();
             if (kind == PARAMETER) {
-                printAnnotationsInline(e);
+                // Print annotation inline
+                writer.print(annotationsToString(e));
             } else {
                 printAnnotations(e);
                 indent();
@@ -460,39 +461,32 @@
                 break;
 
             }
-
-            for(Modifier m: modifiers) {
-                writer.print(m.toString() + " ");
+            if (!modifiers.isEmpty()) {
+                writer.print(modifiers.stream()
+                             .map(Modifier::toString)
+                             .collect(Collectors.joining(" ", "", " ")));
             }
         }
 
         private void printFormalTypeParameters(Parameterizable e,
                                                boolean pad) {
             List<? extends TypeParameterElement> typeParams = e.getTypeParameters();
-            if (typeParams.size() > 0) {
-                writer.print("<");
-
-                boolean first = true;
-                for(TypeParameterElement tpe: typeParams) {
-                    if (!first)
-                        writer.print(", ");
-                    printAnnotationsInline(tpe);
-                    writer.print(tpe.toString());
-                    first = false;
-                }
-
-                writer.print(">");
+            if (!typeParams.isEmpty()) {
+                writer.print(typeParams.stream()
+                             .map(tpe -> annotationsToString(tpe) + tpe.toString())
+                             .collect(Collectors.joining(", ", "<", ">")));
                 if (pad)
                     writer.print(" ");
             }
         }
 
-        private void printAnnotationsInline(Element e) {
-            List<? extends AnnotationMirror> annots = e.getAnnotationMirrors();
-            for(AnnotationMirror annotationMirror : annots) {
-                writer.print(annotationMirror);
-                writer.print(" ");
-            }
+        private String annotationsToString(Element e) {
+            List<? extends AnnotationMirror> annotations = e.getAnnotationMirrors();
+            return annotations.isEmpty() ?
+                "" :
+                annotations.stream()
+                .map(AnnotationMirror::toString)
+                .collect(Collectors.joining(" ", "", " "));
         }
 
         private void printAnnotations(Element e) {
@@ -569,17 +563,11 @@
 
             if(kind != ANNOTATION_TYPE) {
                 List<? extends TypeMirror> interfaces = e.getInterfaces();
-                if (interfaces.size() > 0) {
-                    writer.print((kind.isClass() ? " implements" : " extends"));
-
-                    boolean first = true;
-                    for(TypeMirror interf: interfaces) {
-                        if (!first)
-                            writer.print(",");
-                        writer.print(" ");
-                        writer.print(interf.toString());
-                        first = false;
-                    }
+                if (!interfaces.isEmpty()) {
+                    writer.print((kind.isClass() ? " implements " : " extends "));
+                    writer.print(interfaces.stream()
+                                 .map(TypeMirror::toString)
+                                 .collect(Collectors.joining(", ")));
                 }
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri May 03 14:59:32 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
@@ -1051,6 +1051,10 @@
 compiler.err.proc.cant.find.class=\
     Could not find class file for ''{0}''.
 
+# 0: string
+compiler.err.proc.cant.load.class=\
+    Could not load processor class file due to ''{0}''.
+
 # Print a client-generated error message; assumed to be localized, no translation required
 # 0: string
 compiler.err.proc.messager=\
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java	Fri May 03 14:59:32 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
@@ -75,9 +75,9 @@
 
     protected final String algorithm;
 
-    protected CKey(String algorithm, long hCryptProv, long hCryptKey, int keyLength) {
+    protected CKey(String algorithm, NativeHandles handles, int keyLength) {
         this.algorithm = algorithm;
-        this.handles = new NativeHandles(hCryptProv, hCryptKey);
+        this.handles = handles;
         this.keyLength = keyLength;
     }
 
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyPair.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyPair.java	Fri May 03 14:59:32 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
@@ -36,9 +36,13 @@
 
     private final CPublicKey publicKey;
 
+    /**
+     * This method is called by native codes in security.cpp.
+     */
     CKeyPair(String alg, long hCryptProv, long hCryptKey, int keyLength) {
-        privateKey = CPrivateKey.of(alg, hCryptProv, hCryptKey, keyLength);
-        publicKey = CPublicKey.of(alg, hCryptProv, hCryptKey, keyLength);
+        CKey.NativeHandles handles = new CKey.NativeHandles(hCryptProv, hCryptKey);
+        privateKey = CPrivateKey.of(alg, handles, keyLength);
+        publicKey = CPublicKey.of(alg, handles, keyLength);
     }
 
     public CPrivateKey getPrivate() {
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java	Fri May 03 14:59:32 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
@@ -37,12 +37,18 @@
 
     private static final long serialVersionUID = 8113152807912338063L;
 
-    private CPrivateKey(String alg, long hCryptProv, long hCryptKey, int keyLength) {
-        super(alg, hCryptProv, hCryptKey, keyLength);
+    private CPrivateKey(String alg, NativeHandles handles, int keyLength) {
+        super(alg, handles, keyLength);
     }
 
-    public static CPrivateKey of(String alg, long hCryptProv, long hCryptKey, int keyLength) {
-        return new CPrivateKey(alg, hCryptProv, hCryptKey, keyLength);
+    // Called by native code inside security.cpp
+    static CPrivateKey of(
+            String alg, long hCryptProv, long hCryptKey, int keyLength) {
+        return of(alg, new NativeHandles(hCryptProv, hCryptKey), keyLength);
+    }
+
+    public static CPrivateKey of(String alg, NativeHandles handles, int keyLength) {
+        return new CPrivateKey(alg, handles, keyLength);
     }
 
     // this key does not support encoding
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java	Fri May 03 14:59:32 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
@@ -59,8 +59,8 @@
         private ECPoint w = null;
         private static final long serialVersionUID = 12L;
 
-        CECPublicKey(long hCryptProv, int keyLength) {
-            super("EC", hCryptProv, 0, keyLength);
+        CECPublicKey(NativeHandles handles, int keyLength) {
+            super("EC", handles, keyLength);
         }
 
         @Override
@@ -121,8 +121,8 @@
         private BigInteger exponent = null;
         private static final long serialVersionUID = 12L;
 
-        CRSAPublicKey(long hCryptProv, long hCryptKey, int keyLength) {
-            super("RSA", hCryptProv, hCryptKey, keyLength);
+        CRSAPublicKey(NativeHandles handles, int keyLength) {
+            super("RSA", handles, keyLength);
         }
 
         public String toString() {
@@ -181,21 +181,27 @@
         private native byte[] getModulus(byte[] keyBlob) throws KeyException;
     }
 
+    // Called by native code inside security.cpp
+    static CPublicKey of(
+            String alg, long hCryptProv, long hCryptKey, int keyLength) {
+        return of(alg, new NativeHandles(hCryptProv, hCryptKey), keyLength);
+    }
+
     public static CPublicKey of(
-            String alg, long hCryptProv, long hCryptKey, int keyLength) {
+            String alg, NativeHandles handles, int keyLength) {
         switch (alg) {
             case "RSA":
-                return new CRSAPublicKey(hCryptProv, hCryptKey, keyLength);
+                return new CRSAPublicKey(handles, keyLength);
             case "EC":
-                return new CECPublicKey(hCryptProv, keyLength);
+                return new CECPublicKey(handles, keyLength);
             default:
                 throw new AssertionError("Unsupported algorithm: " + alg);
         }
     }
 
     protected CPublicKey(
-            String alg, long hCryptProv, long hCryptKey, int keyLength) {
-        super(alg, hCryptProv, hCryptKey, keyLength);
+            String alg, NativeHandles handles, int keyLength) {
+        super(alg, handles, keyLength);
     }
 
     @Override
--- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Fri May 03 14:59:32 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
@@ -692,18 +692,22 @@
 
 
 /*
- * Class:     sun_security_mscapi_Key
+ * Class:     sun_security_mscapi_CKey
  * Method:    cleanUp
  * Signature: (JJ)V
  */
-JNIEXPORT void JNICALL Java_sun_security_mscapi_Key_cleanUp
+JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp
   (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)
 {
-    if (hCryptKey != NULL)
-        ::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated
+    if (hCryptKey == NULL && hCryptProv != NULL) {
+        NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);
+    } else {
+        if (hCryptKey != NULL)
+            ::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated
 
-    if (hCryptProv != NULL)
-        ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated
+        if (hCryptProv != NULL)
+            ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated
+    }
 }
 
 /*
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Fri May 03 14:59:32 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
@@ -44,6 +44,8 @@
     public static final int JVM_CONSTANT_MethodType         = 16;
     public static final int JVM_CONSTANT_Dynamic            = 17;
     public static final int JVM_CONSTANT_InvokeDynamic      = 18;
+    public static final int JVM_CONSTANT_Module             = 19;
+    public static final int JVM_CONSTANT_Package            = 20;
 
     // JVM_CONSTANT_MethodHandle subtypes
     public static final int JVM_REF_getField                = 1;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, 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
@@ -50,7 +50,7 @@
     ownerFieldOffset = f.getOffset();
     f = type.getField("FreeNext");
     FreeNextFieldOffset = f.getOffset();
-    countField  = type.getJIntField("_count");
+    contentionsField  = type.getJIntField("_contentions");
     waitersField = type.getJIntField("_waiters");
     recursionsField = type.getCIntegerField("_recursions");
   }
@@ -87,19 +87,14 @@
   // FIXME
   //  void      set_queue(void* owner);
 
-  public int count() { return countField.getValue(addr); }
-  // FIXME
-  //  void      set_count(int count);
-
   public long recursions() { return recursionsField.getValue(addr); }
 
   public OopHandle object() {
     return addr.getOopHandleAt(objectFieldOffset);
   }
 
-  // contentions is always equal to count
   public int contentions() {
-      return count();
+      return contentionsField.getValue(addr);
   }
 
   // FIXME
@@ -114,7 +109,7 @@
   private static long          objectFieldOffset;
   private static long          ownerFieldOffset;
   private static long          FreeNextFieldOffset;
-  private static JIntField     countField;
+  private static JIntField     contentionsField;
   private static JIntField     waitersField;
   private static CIntegerField recursionsField;
   // FIXME: expose platform-dependent stuff
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, 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
@@ -83,7 +83,7 @@
         }
       }
     }
-    tty.println("  _count: " + mon.count());
+    tty.println("  _contentions: " + mon.contentions());
     tty.println("  _waiters: " + mon.waiters());
     tty.println("  _recursions: " + mon.recursions());
   }
@@ -98,7 +98,7 @@
     ObjectMonitor mon;
     while (i.hasNext()) {
       mon = (ObjectMonitor)i.next();
-      if (mon.count() != 0 || mon.waiters() != 0 || mon.owner() != null) {
+      if (mon.contentions() != 0 || mon.waiters() != 0 || mon.owner() != null) {
         OopHandle object = mon.object();
         if (object == null) {
           dumpMonitor(tty, mon, true);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, 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
@@ -191,7 +191,9 @@
     public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
 
     /**
-     * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+     * Gets the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+     *
+     * @return {@code null} if there no deterministic {@link PlatformKind} for {@code javaKind}
      */
     public abstract PlatformKind getPlatformKind(JavaKind javaKind);
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, 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
@@ -87,7 +87,11 @@
 
     @Override
     public int hashCode() {
-        return getBCI();
+        int hc = method.hashCode() * 31 + bci;
+        if (caller != null) {
+            hc = (hc * 31) + caller.hashCode();
+        }
+        return hc;
     }
 
     /**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, 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
@@ -44,6 +44,8 @@
      *            created.
      * @return a reference to the ready-to-run code
      * @throws BailoutException if the code installation failed
+     * @throws IllegalArgumentException if {@code installedCode != null} and this object does not
+     *             support a predefined {@link InstalledCode} object
      */
     default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCode, SpeculationLog log, InstalledCode installedCode) {
         return installCode(method, compiledCode, installedCode, log, false);
@@ -58,6 +60,8 @@
      * @param compiledCode the compiled code to be added
      * @return a reference to the ready-to-run code
      * @throws BailoutException if the code installation failed
+     * @throws IllegalArgumentException if {@code installedCode != null} and this object does not
+     *             support a predefined {@link InstalledCode} object
      */
     default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompiledCode compiledCode) {
         return installCode(method, compiledCode, null, null, true);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 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
@@ -52,14 +52,14 @@
     /**
      * @return the address of entity representing this installed code.
      */
-    public final long getAddress() {
+    public long getAddress() {
         return address;
     }
 
     /**
      * @return the address of the normal entry point of the installed code.
      */
-    public final long getEntryPoint() {
+    public long getEntryPoint() {
         return entryPoint;
     }
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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,5 +27,12 @@
  */
 public final class InvalidInstalledCodeException extends Exception {
 
+    public InvalidInstalledCodeException() {
+    }
+
+    public InvalidInstalledCodeException(String message) {
+        super(message);
+    }
+
     private static final long serialVersionUID = -3540232440794244844L;
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, 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
@@ -24,6 +24,8 @@
 
 import java.util.concurrent.atomic.AtomicInteger;
 
+import jdk.vm.ci.services.Services;
+
 /**
  * A facility for timing a step in the runtime initialization sequence. This is independent from all
  * other JVMCI code so as to not perturb the initialization sequence. It is enabled by setting the
@@ -58,21 +60,32 @@
     }
 
     public static InitTimer timer(String name) {
-        return ENABLED ? new InitTimer(name) : null;
+        return isEnabled() ? new InitTimer(name) : null;
     }
 
     public static InitTimer timer(String name, Object suffix) {
-        return ENABLED ? new InitTimer(name + suffix) : null;
+        return isEnabled() ? new InitTimer(name + suffix) : null;
     }
 
     /**
-     * Specifies if initialization timing is enabled. Note: This property cannot use
+     * Determines if initialization timing is enabled. Note: This property cannot use
      * {@code HotSpotJVMCIRuntime.Option} since that class is not visible from this package.
      */
-    private static final boolean ENABLED = Boolean.getBoolean("jvmci.InitTimer");
+    private static boolean isEnabled() {
+        if (enabledPropertyValue == null) {
+            enabledPropertyValue = Boolean.parseBoolean(Services.getSavedProperty("jvmci.InitTimer"));
+            nesting = new AtomicInteger();
+        }
+        return enabledPropertyValue;
+    }
 
-    public static final AtomicInteger nesting = ENABLED ? new AtomicInteger() : null;
-    public static final String SPACES = "                                            ";
+    /**
+     * Cache for value of {@code jvmci.InitTimer} system property.
+     */
+    @NativeImageReinitialize private static Boolean enabledPropertyValue;
+
+    private static AtomicInteger nesting;
+    private static final String SPACES = "                                            ";
 
     /**
      * Used to assert the invariant that all related initialization happens on the same thread.
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java	Fri May 03 14:59:32 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
@@ -28,7 +28,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Denotes a field that should have the default value for its type when building a native image.
+ * Denotes a field that should have the default value for its type in an ahead of time image.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.FIELD})
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Fri May 03 14:59:32 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,6 +24,7 @@
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+import jdk.vm.ci.services.Services;
 
 /**
  * Used to access native configuration details.
@@ -36,7 +37,7 @@
         super(config);
     }
 
-    final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+    final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux");
 
     final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, 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 @@
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+import jdk.vm.ci.services.Services;
 
 /**
  * Used to access AMD64 specific native configuration details.
@@ -34,7 +35,7 @@
         super(config);
     }
 
-    final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+    final boolean windowsOs = Services.getSavedProperty("os.name", "").startsWith("Windows");
 
     final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
     final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Cleaner.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * A cleaner tracks a referent object and includes some {@linkplain #doCleanup() cleanup code} that
+ * is run some time after the referent object has become weakly-reachable.
+ *
+ * This is like {@link sun.misc.Cleaner} but with weak semantics instead of phantom. Objects
+ * referenced by this might be referenced by {@link ResolvedJavaType} which is kept alive by a
+ * {@link WeakReference} so we need equivalent reference strength.
+ */
+abstract class Cleaner extends WeakReference<Object> {
+
+    /**
+     * Head of linked list of cleaners.
+     */
+    @NativeImageReinitialize private static Cleaner first;
+
+    /**
+     * Linked list pointers.
+     */
+    private Cleaner next = null;
+    private Cleaner prev = null;
+
+    Cleaner(Object referent) {
+        super(referent, queue);
+        add(this);
+    }
+
+    private static synchronized Cleaner add(Cleaner cl) {
+        if (first != null) {
+            clean();
+        }
+        if (first != null) {
+            cl.next = first;
+            first.prev = cl;
+        }
+        first = cl;
+        return cl;
+    }
+
+    /**
+     * Removes {@code cl} from the linked list of cleaners.
+     */
+    private static synchronized void remove(Cleaner cl) {
+        // If already removed, do nothing
+        if (cl.next == cl) {
+            return;
+        }
+
+        // Update list
+        if (first == cl) {
+            if (cl.next != null) {
+                first = cl.next;
+            } else {
+                first = cl.prev;
+            }
+        }
+        if (cl.next != null) {
+            cl.next.prev = cl.prev;
+        }
+        if (cl.prev != null) {
+            cl.prev.next = cl.next;
+        }
+
+        // Indicate removal by pointing the cleaner to itself
+        cl.next = cl;
+        cl.prev = cl;
+    }
+
+    /**
+     * Performs the cleanup action now that this object's referent has become weakly reachable.
+     */
+    abstract void doCleanup();
+
+    /**
+     * Remove the cleaners whose referents have become weakly reachable.
+     */
+    static void clean() {
+        Cleaner c = (Cleaner) queue.poll();
+        while (c != null) {
+            remove(c);
+            c.doCleanup();
+            c = (Cleaner) queue.poll();
+        }
+    }
+
+    /**
+     * The {@link ReferenceQueue} to which {@link Cleaner}s are enqueued once their referents'
+     * become unreachable.
+     */
+    private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, 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
@@ -36,6 +36,10 @@
 import jdk.vm.ci.code.stack.InspectedFrameVisitor;
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -51,17 +55,60 @@
      */
     private static native void registerNatives();
 
-    static {
-        initialize();
-    }
+    /**
+     * These values mirror the equivalent values from {@link Unsafe} but are approriate for the JVM
+     * being compiled against.
+     */
+    // Checkstyle: stop
+    final int ARRAY_BOOLEAN_BASE_OFFSET;
+    final int ARRAY_BYTE_BASE_OFFSET;
+    final int ARRAY_SHORT_BASE_OFFSET;
+    final int ARRAY_CHAR_BASE_OFFSET;
+    final int ARRAY_INT_BASE_OFFSET;
+    final int ARRAY_LONG_BASE_OFFSET;
+    final int ARRAY_FLOAT_BASE_OFFSET;
+    final int ARRAY_DOUBLE_BASE_OFFSET;
+    final int ARRAY_OBJECT_BASE_OFFSET;
+    final int ARRAY_BOOLEAN_INDEX_SCALE;
+    final int ARRAY_BYTE_INDEX_SCALE;
+    final int ARRAY_SHORT_INDEX_SCALE;
+    final int ARRAY_CHAR_INDEX_SCALE;
+    final int ARRAY_INT_INDEX_SCALE;
+    final int ARRAY_LONG_INDEX_SCALE;
+    final int ARRAY_FLOAT_INDEX_SCALE;
+    final int ARRAY_DOUBLE_INDEX_SCALE;
+    final int ARRAY_OBJECT_INDEX_SCALE;
+    // Checkstyle: resume
 
     @SuppressWarnings("try")
-    private static void initialize() {
+    CompilerToVM() {
         try (InitTimer t = timer("CompilerToVM.registerNatives")) {
             registerNatives();
+            ARRAY_BOOLEAN_BASE_OFFSET = arrayBaseOffset(JavaKind.Boolean);
+            ARRAY_BYTE_BASE_OFFSET = arrayBaseOffset(JavaKind.Byte);
+            ARRAY_SHORT_BASE_OFFSET = arrayBaseOffset(JavaKind.Short);
+            ARRAY_CHAR_BASE_OFFSET = arrayBaseOffset(JavaKind.Char);
+            ARRAY_INT_BASE_OFFSET = arrayBaseOffset(JavaKind.Int);
+            ARRAY_LONG_BASE_OFFSET = arrayBaseOffset(JavaKind.Long);
+            ARRAY_FLOAT_BASE_OFFSET = arrayBaseOffset(JavaKind.Float);
+            ARRAY_DOUBLE_BASE_OFFSET = arrayBaseOffset(JavaKind.Double);
+            ARRAY_OBJECT_BASE_OFFSET = arrayBaseOffset(JavaKind.Object);
+            ARRAY_BOOLEAN_INDEX_SCALE = arrayIndexScale(JavaKind.Boolean);
+            ARRAY_BYTE_INDEX_SCALE = arrayIndexScale(JavaKind.Byte);
+            ARRAY_SHORT_INDEX_SCALE = arrayIndexScale(JavaKind.Short);
+            ARRAY_CHAR_INDEX_SCALE = arrayIndexScale(JavaKind.Char);
+            ARRAY_INT_INDEX_SCALE = arrayIndexScale(JavaKind.Int);
+            ARRAY_LONG_INDEX_SCALE = arrayIndexScale(JavaKind.Long);
+            ARRAY_FLOAT_INDEX_SCALE = arrayIndexScale(JavaKind.Float);
+            ARRAY_DOUBLE_INDEX_SCALE = arrayIndexScale(JavaKind.Double);
+            ARRAY_OBJECT_INDEX_SCALE = arrayIndexScale(JavaKind.Object);
         }
     }
 
+    native int arrayBaseOffset(JavaKind kind);
+
+    native int arrayIndexScale(JavaKind kind);
+
     /**
      * Gets the {@link CompilerToVM} instance associated with the singleton
      * {@link HotSpotJVMCIRuntime} instance.
@@ -152,13 +199,16 @@
      * Converts a name to a type.
      *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
-     * @param accessingClass the context of resolution (must not be null)
+     * @param accessingClass the context of resolution. A value of {@code null} implies that the
+     *            class should be resolved with the class loader.
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
      *            either return a {@link ResolvedJavaType} or throw an exception
      * @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
      * @throws ClassNotFoundException if {@code resolve == true} and the resolution failed
      */
-    native HotSpotResolvedObjectTypeImpl lookupType(String name, Class<?> accessingClass, boolean resolve) throws ClassNotFoundException;
+    native HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws ClassNotFoundException;
+
+    native HotSpotResolvedJavaType lookupClass(Class<?> javaClass);
 
     /**
      * Resolves the entry at index {@code cpi} in {@code constantPool} to an object.
@@ -167,7 +217,7 @@
      * entry types: {@code JVM_CONSTANT_MethodHandle}, {@code JVM_CONSTANT_MethodHandleInError},
      * {@code JVM_CONSTANT_MethodType} and {@code JVM_CONSTANT_MethodTypeInError}.
      */
-    native Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Resolves the entry at index {@code cpi} in {@code constantPool} to an object, looking in the
@@ -176,7 +226,7 @@
      * The behavior of this method is undefined if {@code cpi} does not denote a
      * {@code JVM_CONSTANT_String} entry.
      */
-    native Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Gets the {@code JVM_CONSTANT_NameAndType} index from the entry at index {@code cpi} in
@@ -318,7 +368,7 @@
      * Gets the appendix object (if any) associated with the entry at index {@code cpi} in
      * {@code constantPool}.
      */
-    native Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Installs the result of a compilation into the code cache.
@@ -335,7 +385,7 @@
      * @throws JVMCIError if there is something wrong with the compiled code or the associated
      *             metadata.
      */
-    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog);
+    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, long failedSpeculationsAddress, byte[] speculations);
 
     /**
      * Generates the VM metadata for some compiled code and copies them into {@code metaData}. This
@@ -433,10 +483,10 @@
     /**
      * Executes some {@code installedCode} with arguments {@code args}.
      *
-     * @return the result of executing {@code installedCode}
-     * @throws InvalidInstalledCodeException if {@code installedCode} has been invalidated
+     * @return the result of executing {@code nmethodMirror}
+     * @throws InvalidInstalledCodeException if {@code nmethodMirror} has been invalidated
      */
-    native Object executeInstalledCode(Object[] args, InstalledCode installedCode) throws InvalidInstalledCodeException;
+    native Object executeHotSpotNmethod(Object[] args, HotSpotNmethod nmethodMirror) throws InvalidInstalledCodeException;
 
     /**
      * Gets the line number table for {@code method}. The line number table is encoded as (bci,
@@ -472,6 +522,19 @@
     native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
 
     /**
+     * Reads an object pointer within a VM data structure. That is, any {@link VMField} whose
+     * {@link VMField#type type} is {@code "oop"} (e.g.,
+     * {@code Klass::_java_mirror}, {@code JavaThread::_threadObj}).
+     *
+     * Note that {@link Unsafe#getObject(Object, long)} cannot be used for this since it does a
+     * {@code narrowOop} read if the VM is using compressed oops whereas oops within VM data
+     * structures are (currently) always uncompressed.
+     *
+     * @param address address of an oop field within a VM data structure
+     */
+    native HotSpotObjectConstantImpl readUncompressedOop(long address);
+
+    /**
      * Sets flags on {@code method} indicating that it should never be inlined or compiled by the
      * VM.
      */
@@ -484,10 +547,12 @@
     native void reprofile(HotSpotResolvedJavaMethodImpl method);
 
     /**
-     * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
-     * raised the next time {@code installedCode} is executed.
+     * Invalidates {@code nmethodMirror} such that {@link InvalidInstalledCodeException} will be
+     * raised the next time {@code nmethodMirror} is {@linkplain #executeHotSpotNmethod executed}.
+     * The {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and any
+     * current activations of the {@code nmethod} are deoptimized.
      */
-    native void invalidateInstalledCode(InstalledCode installedCode);
+    native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror);
 
     /**
      * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
@@ -572,7 +637,7 @@
      * @param displacement
      * @return null or the resolved method for this location
      */
-    native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
+    native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(HotSpotObjectConstantImpl base, long displacement);
 
     /**
      * Gets the {@code ConstantPool*} associated with {@code object} and returns a
@@ -586,7 +651,7 @@
      * @throws IllegalArgumentException if {@code object} is neither a
      *             {@link HotSpotResolvedJavaMethodImpl} nor a {@link HotSpotResolvedObjectTypeImpl}
      */
-    native HotSpotConstantPool getConstantPool(Object object);
+    native HotSpotConstantPool getConstantPool(MetaspaceObject object);
 
     /**
      * Read a HotSpot Klass* value from the memory location described by {@code base} plus
@@ -604,7 +669,19 @@
      * @param compressed true if the location contains a compressed Klass*
      * @return null or the resolved method for this location
      */
-    native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed);
+    private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed);
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(MetaspaceObject base, long displacement, boolean compressed) {
+        return getResolvedJavaType0(base, displacement, compressed);
+    }
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotObjectConstantImpl base, long displacement, boolean compressed) {
+        return getResolvedJavaType0(base, displacement, compressed);
+    }
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(long displacement, boolean compressed) {
+        return getResolvedJavaType0(null, displacement, compressed);
+    }
 
     /**
      * Return the size of the HotSpot ProfileData* pointed at by {@code position}. If
@@ -641,7 +718,7 @@
      * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on
      * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
      */
-    native void compileToBytecode(Object lambdaForm);
+    native void compileToBytecode(HotSpotObjectConstantImpl lambdaForm);
 
     /**
      * Gets the value of the VM flag named {@code name}.
@@ -660,6 +737,164 @@
     native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type);
 
     /**
+     * Gets the object at the address {@code oopAddress}.
+     *
+     * @param oopAddress a valid {@code oopDesc**} value
+     */
+    native Object getObjectAtAddress(long oopAddress);
+
+    /**
+     * @see ResolvedJavaType#getInterfaces()
+     */
+    native HotSpotResolvedObjectTypeImpl[] getInterfaces(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * @see ResolvedJavaType#getComponentType()
+     */
+    native HotSpotResolvedJavaType getComponentType(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Forces initialization of {@code type}.
+     */
+    native void ensureInitialized(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Checks if {@code object} is a String and is an interned string value.
+     */
+    native boolean isInternedString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Gets the {@linkplain System#identityHashCode(Object) identity} has code for the object
+     * represented by this constant.
+     */
+    native int getIdentityHashCode(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a constant object representing a boxed primitive into a boxed primitive.
+     */
+    native Object unboxPrimitive(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a boxed primitive into a JavaConstant representing the same value.
+     */
+    native HotSpotObjectConstantImpl boxPrimitive(Object source);
+
+    /**
+     * Gets the {@link ResolvedJavaMethod}s for all the constructors of the type {@code holder}.
+     */
+    native ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl holder);
+
+    /**
+     * Gets the {@link ResolvedJavaMethod}s for all the non-constructor methods of the type
+     * {@code holder}.
+     */
+    native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl holder);
+
+    /**
+     * Reads the current value of a static field.
+     */
+    native JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl resolvedObjectType, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    /**
+     * Reads the current value of an instance field.
+     */
+    native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    /**
+     * @see ResolvedJavaType#isInstance(JavaConstant)
+     */
+    native boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl object);
+
+    /**
+     * @see ResolvedJavaType#isAssignableFrom(ResolvedJavaType)
+     */
+    native boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType);
+
+    /**
+     * @see ConstantReflectionProvider#asJavaType(Constant)
+     */
+    native HotSpotResolvedJavaType asJavaType(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a String constant into a String.
+     */
+    native String asString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Compares the contents of {@code xHandle} and {@code yHandle} for pointer equality.
+     */
+    native boolean equals(HotSpotObjectConstantImpl x, long xHandle, HotSpotObjectConstantImpl y, long yHandle);
+
+    /**
+     * Gets a {@link JavaConstant} wrapping the {@link java.lang.Class} mirror for {@code type}.
+     */
+    native HotSpotObjectConstantImpl getJavaMirror(HotSpotResolvedJavaType type);
+
+    /**
+     * Returns the length of the array if {@code object} represents an array or -1 otherwise.
+     */
+    native int getArrayLength(HotSpotObjectConstantImpl object);
+
+    /**
+     * Reads the element at {@code index} if {@code object} is an array. Elements of an object array
+     * are returned as {@link JavaConstant}s and primitives are returned as boxed values. The value
+     * {@code null} is returned if the {@code index} is out of range or object is not an array.
+     */
+    native Object readArrayElement(HotSpotObjectConstantImpl object, int index);
+
+    /**
+     * Reads a byte sized value from {@code displacement} in {@code object}.
+     */
+    native byte getByte(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a short sized value from {@code displacement} in {@code object}.
+     */
+    native short getShort(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads an int sized value from {@code displacement} in {@code object}.
+     */
+    native int getInt(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a long sized value from {@code displacement} in {@code object}.
+     */
+    native long getLong(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a Java object from {@code displacement} in {@code object}.
+     */
+    native HotSpotObjectConstantImpl getObject(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * @see HotSpotJVMCIRuntime#registerNativeMethods
+     */
+    native long[] registerNativeMethods(Class<?> clazz);
+
+    /**
+     * @see HotSpotJVMCIRuntime#translate(Object)
+     */
+    native long translate(Object obj);
+
+    /**
+     * @see HotSpotJVMCIRuntime#unhand(Class, long)
+     */
+    native Object unhand(long handle);
+
+    /**
+     * Updates {@code address} and {@code entryPoint} fields of {@code nmethodMirror} based on the
+     * current state of the {@code nmethod} identified by {@code address} and
+     * {@code nmethodMirror.compileId} in the code cache.
+     */
+    native void updateHotSpotNmethod(HotSpotNmethod nmethodMirror);
+
+    /**
+     * @see InstalledCode#getCode()
+     */
+    native byte[] getCode(HotSpotInstalledCode code);
+
+    /**
      * Gets a {@link Executable} corresponding to {@code method}.
      */
     native Executable asReflectionExecutable(HotSpotResolvedJavaMethodImpl method);
@@ -671,4 +906,45 @@
      * @param fieldIndex the {@code fieldDescriptor::index()} denoting the field
      */
     native Field asReflectionField(HotSpotResolvedObjectTypeImpl holder, int fieldIndex);
+
+    /**
+     * @see HotSpotJVMCIRuntime#getIntrinsificationTrustPredicate(Class...)
+     */
+    native boolean isTrustedForIntrinsics(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Releases the resources backing the global JNI {@code handle}. This is equivalent to the
+     * {@code DeleteGlobalRef} JNI function.
+     */
+    native void deleteGlobalHandle(long handle);
+
+    /**
+     * Gets the failed speculations pointed to by {@code *failedSpeculationsAddress}.
+     *
+     * @param currentFailures the known failures at {@code failedSpeculationsAddress}
+     * @return the list of failed speculations with each entry being a single speculation in the
+     *         format emitted by {@link HotSpotSpeculationEncoding#toByteArray()}
+     */
+    native byte[][] getFailedSpeculations(long failedSpeculationsAddress, byte[][] currentFailures);
+
+    /**
+     * Gets the address of the {@code MethodData::_failed_speculations} field in the
+     * {@code MethodData} associated with {@code method}. This will create and install the
+     * {@code MethodData} if it didn't already exist.
+     */
+    native long getFailedSpeculationsAddress(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Frees the failed speculations pointed to by {@code *failedSpeculationsAddress}.
+     */
+    native void releaseFailedSpeculations(long failedSpeculationsAddress);
+
+    /**
+     * Adds a speculation to the failed speculations pointed to by
+     * {@code *failedSpeculationsAddress}.
+     *
+     * @return {@code false} if the speculation could not be appended to the list
+     */
+    native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation);
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+final class DirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl {
+
+    static JavaConstant forObject(Object object, boolean compressed) {
+        if (object == null) {
+            return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
+        } else {
+            return new DirectHotSpotObjectConstantImpl(object, compressed);
+        }
+    }
+
+    static HotSpotObjectConstantImpl forNonNullObject(Object object, boolean compressed) {
+        if (object == null) {
+            throw new NullPointerException();
+        }
+        return new DirectHotSpotObjectConstantImpl(object, compressed);
+    }
+
+    private DirectHotSpotObjectConstantImpl(Object object, boolean compressed) {
+        super(compressed);
+        assert object != null;
+        this.object = object;
+    }
+
+    final Object object;
+
+    @Override
+    public JavaConstant compress() {
+        assert !compressed;
+        return new DirectHotSpotObjectConstantImpl(object, true);
+    }
+
+    @Override
+    public JavaConstant uncompress() {
+        assert compressed;
+        return new DirectHotSpotObjectConstantImpl(object, false);
+    }
+
+    @Override
+    public int getIdentityHashCode() {
+        return System.identityHashCode(object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+/**
+ * This class manages a set of {@code jobject} and {@code jmetadata} handles whose lifetimes are
+ * dependent on associated {@link IndirectHotSpotObjectConstantImpl} and
+ * {@link MetaspaceHandleObject} wrapper objects respectively.
+ *
+ * The general theory of operation is that all wrappers are created by calling into the VM which
+ * calls back out to actually create the wrapper instance. During the call the VM keeps the object
+ * or metadata reference alive through the use of handles. Once the call completes the wrapper
+ * object is registered here and will be scanned during metadata scanning. The weakness of the
+ * reference to the wrapper object allows the handles to be reclaimed when they are no longer used.
+ */
+final class HandleCleaner extends Cleaner {
+
+    /**
+     * A {@code jmetadata} or {@code jobject} handle.
+     */
+    private final long handle;
+
+    /**
+     * Specifies if {@link #handle} is a {@code jobject} or {@code jmetadata}.
+     */
+    private final boolean isJObject;
+
+    private HandleCleaner(Object wrapper, long handle, boolean isJObject) {
+        super(wrapper);
+        this.handle = handle;
+        this.isJObject = isJObject;
+    }
+
+    /**
+     * Releases the resource associated with {@code this.handle}.
+     */
+    @Override
+    void doCleanup() {
+        if (isJObject) {
+            // The sentinel value used to denote a free handle is
+            // an object on the HotSpot heap so we call into the
+            // VM to set the target of an object handle to this value.
+            CompilerToVM.compilerToVM().deleteGlobalHandle(handle);
+        } else {
+            // Setting the target of a jmetadata handle to 0 enables
+            // the handle to be reused. See MetadataHandleBlock in
+            // jvmciRuntime.cpp for more info.
+            long value = UNSAFE.getLong(null, handle);
+            UNSAFE.compareAndSetLong(null, handle, value, 0);
+        }
+    }
+
+    /**
+     * Registers a cleaner for {@code handle}. The cleaner will release the handle some time after
+     * {@code wrapper} is detected as unreachable by the garbage collector.
+     */
+    @SuppressWarnings("unused")
+    static void create(Object wrapper, long handle) {
+        assert wrapper instanceof IndirectHotSpotObjectConstantImpl || wrapper instanceof MetaspaceHandleObject;
+        new HandleCleaner(wrapper, handle, wrapper instanceof IndirectHotSpotObjectConstantImpl);
+    }
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri May 03 14:59:32 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
@@ -23,6 +23,7 @@
 package jdk.vm.ci.hotspot;
 
 import java.util.Map;
+import java.util.Objects;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.code.BytecodeFrame;
@@ -102,25 +103,42 @@
     @Override
     public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) {
         InstalledCode resultInstalledCode;
-        if (installedCode == null) {
-            if (method == null) {
-                // Must be a stub
-                resultInstalledCode = new HotSpotRuntimeStub(((HotSpotCompiledCode) compiledCode).getName());
-            } else {
-                resultInstalledCode = new HotSpotNmethod((HotSpotResolvedJavaMethod) method, ((HotSpotCompiledCode) compiledCode).getName(), isDefault);
-            }
+        if (installedCode != null) {
+            throw new IllegalArgumentException("InstalledCode argument must be null");
+        }
+        HotSpotCompiledCode hsCompiledCode = (HotSpotCompiledCode) compiledCode;
+        String name = hsCompiledCode.getName();
+        HotSpotCompiledNmethod hsCompiledNmethod = null;
+        if (method == null) {
+            // Must be a stub
+            resultInstalledCode = new HotSpotRuntimeStub(name);
         } else {
-            resultInstalledCode = installedCode;
+            hsCompiledNmethod = (HotSpotCompiledNmethod) hsCompiledCode;
+            HotSpotResolvedJavaMethodImpl hsMethod = (HotSpotResolvedJavaMethodImpl) method;
+            resultInstalledCode = new HotSpotNmethod(hsMethod, name, isDefault, hsCompiledNmethod.id);
         }
 
-        HotSpotSpeculationLog speculationLog = (log != null && log.hasSpeculations()) ? (HotSpotSpeculationLog) log : null;
+        HotSpotSpeculationLog speculationLog = null;
+        if (log != null) {
+            if (log.hasSpeculations()) {
+                speculationLog = (HotSpotSpeculationLog) log;
+            }
+        }
 
-        int result = runtime.getCompilerToVM().installCode(target, (HotSpotCompiledCode) compiledCode, resultInstalledCode, speculationLog);
+        byte[] speculations;
+        long failedSpeculationsAddress;
+        if (speculationLog != null) {
+            speculations = speculationLog.getFlattenedSpeculations(true);
+            failedSpeculationsAddress = speculationLog.getFailedSpeculationsAddress();
+        } else {
+            speculations = new byte[0];
+            failedSpeculationsAddress = 0L;
+        }
+        int result = runtime.getCompilerToVM().installCode(target, (HotSpotCompiledCode) compiledCode, resultInstalledCode, failedSpeculationsAddress, speculations);
         if (result != config.codeInstallResultOk) {
             String resultDesc = config.getCodeInstallResultDescription(result);
-            if (compiledCode instanceof HotSpotCompiledNmethod) {
-                HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode;
-                String msg = compiledNmethod.getInstallationFailureMessage();
+            if (hsCompiledNmethod != null) {
+                String msg = hsCompiledNmethod.getInstallationFailureMessage();
                 if (msg != null) {
                     msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
                 } else {
@@ -139,7 +157,11 @@
 
     @Override
     public void invalidateInstalledCode(InstalledCode installedCode) {
-        runtime.getCompilerToVM().invalidateInstalledCode(installedCode);
+        if (installedCode instanceof HotSpotNmethod) {
+            runtime.getCompilerToVM().invalidateHotSpotNmethod((HotSpotNmethod) installedCode);
+        } else {
+            throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
+        }
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Fri May 03 14:59:32 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
@@ -29,7 +29,14 @@
  * the address of a {@code JVMCIEnv} object that provides native context for a compilation.
  */
 public class HotSpotCompilationRequest extends CompilationRequest {
-    private final long jvmciEnv;
+    /**
+     * Address of the native {@code JVMCICompileState} associated with the request.
+     */
+    private final long compileState;
+
+    /**
+     * An identifier for the request.
+     */
     private final int id;
 
     /**
@@ -39,10 +46,10 @@
      * @param method the method to be compiled
      * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
      *            method's entry point
-     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param compileState address of a native {@code JVMCICompileState} object or 0L
      */
-    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv) {
-        this(method, entryBCI, jvmciEnv, method.allocateCompileId(entryBCI));
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long compileState) {
+        this(method, entryBCI, compileState, method.allocateCompileId(entryBCI));
     }
 
     /**
@@ -51,12 +58,12 @@
      * @param method the method to be compiled
      * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
      *            method's entry point
-     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param compileState address of a native {@code JVMCICompileState} object or 0L
      * @param id an identifier for the request
      */
-    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
         super(method, entryBCI);
-        this.jvmciEnv = jvmciEnv;
+        this.compileState = compileState;
         this.id = id;
     }
 
@@ -66,10 +73,12 @@
     }
 
     /**
-     * Gets the address of the native {@code JVMCIEnv} object or 0L if no such object exists.
+     * Gets the address of the native {@code JVMCICompileState} or 0L if no such object exists. This
+     * method should really be named {@code getCompileState} but must remain as is for API
+     * stability.
      */
     public long getJvmciEnv() {
-        return jvmciEnv;
+        return compileState;
     }
 
     /**
@@ -78,5 +87,4 @@
     public int getId() {
         return id;
     }
-
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, 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
@@ -42,9 +42,9 @@
     protected final int id;
 
     /**
-     * Address of a native {@code JVMCIEnv} object or 0L if no such object exists.
+     * Address of a native {@code JVMCICompileState} object or 0L if no such object exists.
      */
-    protected final long jvmciEnv;
+    protected final long compileState;
 
     protected final boolean hasUnsafeAccess;
 
@@ -56,12 +56,12 @@
 
     public HotSpotCompiledNmethod(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
                     int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot, HotSpotResolvedJavaMethod method, int entryBCI,
-                    int id, long jvmciEnv, boolean hasUnsafeAccess) {
+                    int id, long compileState, boolean hasUnsafeAccess) {
         super(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, deoptRescueSlot);
         this.method = method;
         this.entryBCI = entryBCI;
         this.id = id;
-        this.jvmciEnv = jvmciEnv;
+        this.compileState = compileState;
         this.hasUnsafeAccess = hasUnsafeAccess;
     }
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri May 03 14:59:32 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
@@ -27,9 +27,8 @@
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.invoke.MethodHandle;
-
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaField;
@@ -45,7 +44,7 @@
 /**
  * Implementation of {@link ConstantPool} for HotSpot.
  */
-public final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
+public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleObject {
 
     /**
      * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
@@ -97,76 +96,86 @@
         }
     }
 
-    /**
-     * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and
-     * internal ones.
-     */
-    private enum JVM_CONSTANT {
-        // @formatter:off
-        Utf8(config().jvmConstantUtf8),
-        Integer(config().jvmConstantInteger),
-        Long(config().jvmConstantLong),
-        Float(config().jvmConstantFloat),
-        Double(config().jvmConstantDouble),
-        Class(config().jvmConstantClass),
-        UnresolvedClass(config().jvmConstantUnresolvedClass),
-        UnresolvedClassInError(config().jvmConstantUnresolvedClassInError),
-        String(config().jvmConstantString),
-        Fieldref(config().jvmConstantFieldref),
-        MethodRef(config().jvmConstantMethodref),
-        InterfaceMethodref(config().jvmConstantInterfaceMethodref),
-        NameAndType(config().jvmConstantNameAndType),
-        MethodHandle(config().jvmConstantMethodHandle),
-        MethodHandleInError(config().jvmConstantMethodHandleInError),
-        MethodType(config().jvmConstantMethodType),
-        MethodTypeInError(config().jvmConstantMethodTypeInError),
-        InvokeDynamic(config().jvmConstantInvokeDynamic);
-        // @formatter:on
+    static final class JvmConstant {
+        private final int tag;
+        private final String name;
 
-        private final int tag;
-
-        private static final int ExternalMax = config().jvmConstantExternalMax;
-        private static final int InternalMin = config().jvmConstantInternalMin;
-        private static final int InternalMax = config().jvmConstantInternalMax;
-
-        JVM_CONSTANT(int tag) {
+        JvmConstant(int tag, String name) {
             this.tag = tag;
+            this.name = name;
         }
 
-        /**
-         * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy
-         * initialization.
-         */
-        static class TagValueMap {
-            private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1];
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    /**
+     * {@code JVM_CONSTANT} constants used in the VM including both public and internal ones.
+     */
+    static final class JvmConstants {
+
+        private final HotSpotVMConfig c = config();
+        private final int externalMax = c.jvmConstantExternalMax;
+        private final int internalMax = c.jvmConstantInternalMax;
+        private final int internalMin = c.jvmConstantInternalMin;
+        private final JvmConstant[] table = new JvmConstant[externalMax + 1 + (internalMax - internalMin) + 1];
 
-            static {
-                assert InternalMin > ExternalMax;
-                for (JVM_CONSTANT e : values()) {
-                    table[indexOf(e.tag)] = e;
+        final JvmConstant jvmUtf8 = add(new JvmConstant(c.jvmConstantUtf8, "Utf8"));
+        final JvmConstant jvmInteger = add(new JvmConstant(c.jvmConstantInteger, "Integer"));
+        final JvmConstant jvmLong = add(new JvmConstant(c.jvmConstantLong, "Long"));
+        final JvmConstant jvmFloat = add(new JvmConstant(c.jvmConstantFloat, "Float"));
+        final JvmConstant jvmDouble = add(new JvmConstant(c.jvmConstantDouble, "Double"));
+        final JvmConstant jvmClass = add(new JvmConstant(c.jvmConstantClass, "Class"));
+        final JvmConstant jvmUnresolvedClass = add(new JvmConstant(c.jvmConstantUnresolvedClass, "UnresolvedClass"));
+        final JvmConstant jvmUnresolvedClassInError = add(new JvmConstant(c.jvmConstantUnresolvedClassInError, "UnresolvedClassInError"));
+        final JvmConstant jvmString = add(new JvmConstant(c.jvmConstantString, "String"));
+        final JvmConstant jvmFieldref = add(new JvmConstant(c.jvmConstantFieldref, "Fieldref"));
+        final JvmConstant jvmMethodref = add(new JvmConstant(c.jvmConstantMethodref, "Methodref"));
+        final JvmConstant jvmInterfaceMethodref = add(new JvmConstant(c.jvmConstantInterfaceMethodref, "InterfaceMethodref"));
+        final JvmConstant jvmNameAndType = add(new JvmConstant(c.jvmConstantNameAndType, "NameAndType"));
+        final JvmConstant jvmMethodHandle = add(new JvmConstant(c.jvmConstantMethodHandle, "MethodHandle"));
+        final JvmConstant jvmMethodHandleInError = add(new JvmConstant(c.jvmConstantMethodHandleInError, "MethodHandleInError"));
+        final JvmConstant jvmMethodType = add(new JvmConstant(c.jvmConstantMethodType, "MethodType"));
+        final JvmConstant jvmMethodTypeInError = add(new JvmConstant(c.jvmConstantMethodTypeInError, "MethodTypeInError"));
+        final JvmConstant jvmInvokeDynamic = add(new JvmConstant(c.jvmConstantInvokeDynamic, "InvokeDynamic"));
+
+        private JvmConstant add(JvmConstant constant) {
+            table[indexOf(constant.tag)] = constant;
+            return constant;
+        }
+
+        private int indexOf(int tag) {
+            if (tag >= internalMin) {
+                return tag - internalMin + externalMax + 1;
+            } else {
+                assert tag <= externalMax;
+            }
+            return tag;
+        }
+
+        JvmConstant get(int tag) {
+            JvmConstant res = table[indexOf(tag)];
+            if (res != null) {
+                return res;
+            }
+            throw new JVMCIError("Unknown JvmConstant tag %s", tag);
+        }
+
+        @NativeImageReinitialize private static volatile JvmConstants instance;
+
+        static JvmConstants instance() {
+            JvmConstants result = instance;
+            if (result == null) {
+                synchronized (JvmConstants.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new JvmConstants();
+                    }
                 }
             }
-
-            private static int indexOf(int tag) {
-                if (tag >= InternalMin) {
-                    return tag - InternalMin + ExternalMax + 1;
-                } else {
-                    assert tag <= ExternalMax;
-                }
-                return tag;
-            }
-
-            static JVM_CONSTANT get(int tag) {
-                JVM_CONSTANT res = table[indexOf(tag)];
-                if (res != null) {
-                    return res;
-                }
-                throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag);
-            }
-        }
-
-        public static JVM_CONSTANT getEnum(int tag) {
-            return TagValueMap.get(tag);
+            return result;
         }
     }
 
@@ -182,15 +191,18 @@
     }
 
     /**
-     * Reference to the C++ ConstantPool object.
+     * Handle to the {@code ConstantPool} VM object. The handle is in
+     * {@code JVMCI::_metadata_handles}.
      */
-    private final long metaspaceConstantPool;
+    private final long metadataHandle;
+
     private volatile LookupTypeCacheElement lastLookupType;
+    private final JvmConstants constants;
 
     /**
      * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that
      * the ConstantPool is kept alive for the duration of this call and the
-     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+     * {@link HotSpotJVMCIRuntime} keeps it alive after that.
      *
      * Called from the VM.
      *
@@ -198,14 +210,15 @@
      * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool}
      */
     @SuppressWarnings("unused")
+    @VMEntryPoint
     private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
-        HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool);
-        runtime().metaAccessContext.add(cp);
-        return cp;
+        return new HotSpotConstantPool(metaspaceConstantPool);
     }
 
-    private HotSpotConstantPool(long metaspaceConstantPool) {
-        this.metaspaceConstantPool = metaspaceConstantPool;
+    private HotSpotConstantPool(long metadataHandle) {
+        this.metadataHandle = metadataHandle;
+        this.constants = JvmConstants.instance();
+        HandleCleaner.create(this, metadataHandle);
     }
 
     /**
@@ -271,12 +284,12 @@
     }
 
     long getMetaspaceConstantPool() {
-        return metaspaceConstantPool;
+        return getMetaspacePointer();
     }
 
     @Override
-    public long getMetaspacePointer() {
-        return getMetaspaceConstantPool();
+    public long getMetadataHandle() {
+        return metadataHandle;
     }
 
     /**
@@ -285,7 +298,7 @@
      * @param index constant pool index
      * @return constant pool tag
      */
-    private JVM_CONSTANT getTagAt(int index) {
+    private JvmConstant getTagAt(int index) {
         assert checkBounds(index);
         HotSpotVMConfig config = config();
         final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset);
@@ -293,7 +306,7 @@
         if (tag == 0) {
             return null;
         }
-        return JVM_CONSTANT.getEnum(tag);
+        return constants.get(tag);
     }
 
     /**
@@ -315,7 +328,7 @@
      * @return integer constant pool entry at index
      */
     private int getIntAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Integer);
+        assert checkTag(index, constants.jvmInteger);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -327,7 +340,7 @@
      * @return long constant pool entry
      */
     private long getLongAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Long);
+        assert checkTag(index, constants.jvmLong);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -339,7 +352,7 @@
      * @return float constant pool entry
      */
     private float getFloatAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Float);
+        assert checkTag(index, constants.jvmFloat);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -351,7 +364,7 @@
      * @return float constant pool entry
      */
     private double getDoubleAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Double);
+        assert checkTag(index, constants.jvmDouble);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -363,7 +376,7 @@
      * @return {@code JVM_CONSTANT_NameAndType} constant pool entry
      */
     private int getNameAndTypeAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.NameAndType);
+        assert checkTag(index, constants.jvmNameAndType);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -470,22 +483,23 @@
      * @param tag expected tag
      * @throws AssertionError if the check fails
      */
-    private boolean checkTag(int index, JVM_CONSTANT tag) {
-        final JVM_CONSTANT tagAt = getTagAt(index);
+    private boolean checkTag(int index, JvmConstant tag) {
+        final JvmConstant tagAt = getTagAt(index);
         assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
         return true;
     }
 
     /**
-     * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
-     * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
+     * Asserts that the constant pool tag at index {@code index} is a
+     * {@link JvmConstants#jvmFieldref}, or a {@link JvmConstants#jvmMethodref}, or a
+     * {@link JvmConstants#jvmInterfaceMethodref}.
      *
      * @param index constant pool index
      * @throws AssertionError if the check fails
      */
     private boolean checkTagIsFieldOrMethod(int index) {
-        final JVM_CONSTANT tagAt = getTagAt(index);
-        assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
+        final JvmConstant tagAt = getTagAt(index);
+        assert tagAt == constants.jvmFieldref || tagAt == constants.jvmMethodref || tagAt == constants.jvmInterfaceMethodref : tagAt;
         return true;
     }
 
@@ -505,35 +519,33 @@
     @Override
     public Object lookupConstant(int cpi) {
         assert cpi != 0;
-        final JVM_CONSTANT tag = getTagAt(cpi);
-        switch (tag) {
-            case Integer:
+        final JvmConstant tag = getTagAt(cpi);
+        switch (tag.name) {
+            case "Integer":
                 return JavaConstant.forInt(getIntAt(cpi));
-            case Long:
+            case "Long":
                 return JavaConstant.forLong(getLongAt(cpi));
-            case Float:
+            case "Float":
                 return JavaConstant.forFloat(getFloatAt(cpi));
-            case Double:
+            case "Double":
                 return JavaConstant.forDouble(getDoubleAt(cpi));
-            case Class:
-            case UnresolvedClass:
-            case UnresolvedClassInError:
+            case "Class":
+            case "UnresolvedClass":
+            case "UnresolvedClassInError":
                 final int opcode = -1;  // opcode is not used
                 return lookupType(cpi, opcode);
-            case String:
+            case "String":
                 /*
                  * Normally, we would expect a String here, but unsafe anonymous classes can have
                  * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
                  * entries do not have a symbol in the constant pool slot.
                  */
-                Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
-                return HotSpotObjectConstantImpl.forObject(string);
-            case MethodHandle:
-            case MethodHandleInError:
-            case MethodType:
-            case MethodTypeInError:
-                Object obj = compilerToVM().resolveConstantInPool(this, cpi);
-                return HotSpotObjectConstantImpl.forObject(obj);
+                return compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
+            case "MethodHandle":
+            case "MethodHandleInError":
+            case "MethodType":
+            case "MethodTypeInError":
+                return compilerToVM().resolveConstantInPool(this, cpi);
             default:
                 throw new JVMCIError("Unknown constant pool tag %s", tag);
         }
@@ -541,7 +553,7 @@
 
     @Override
     public String lookupUtf8(int cpi) {
-        assert checkTag(cpi, JVM_CONSTANT.Utf8);
+        assert checkTag(cpi, constants.jvmUtf8);
         return compilerToVM().getSymbol(getEntryAt(cpi));
     }
 
@@ -554,12 +566,7 @@
     public JavaConstant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
         final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-        Object appendix = compilerToVM().lookupAppendixInPool(this, index);
-        if (appendix == null) {
-            return null;
-        } else {
-            return HotSpotObjectConstantImpl.forObject(appendix);
-        }
+        return compilerToVM().lookupAppendixInPool(this, index);
     }
 
     /**
@@ -587,7 +594,7 @@
             String name = getNameOf(index);
             HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index));
             if (opcode == Bytecodes.INVOKEDYNAMIC) {
-                HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class);
+                HotSpotResolvedObjectType holder = runtime().getMethodHandleClass();
                 return new UnresolvedJavaMethod(name, signature, holder);
             } else {
                 final int klassIndex = getKlassRefIndexAt(index);
@@ -709,40 +716,37 @@
                 throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
         }
 
-        final JVM_CONSTANT tag = getTagAt(index);
+        final JvmConstant tag = getTagAt(index);
         if (tag == null) {
-            assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
+            assert getTagAt(index - 1) == constants.jvmDouble || getTagAt(index - 1) == constants.jvmLong;
             return;
         }
-        switch (tag) {
-            case MethodRef:
-            case Fieldref:
-            case InterfaceMethodref:
+        switch (tag.name) {
+            case "Methodref":
+            case "Fieldref":
+            case "InterfaceMethodref":
                 index = getUncachedKlassRefIndexAt(index);
                 // Read the tag only once because it could change between multiple reads.
-                final JVM_CONSTANT klassTag = getTagAt(index);
-                assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
+                final JvmConstant klassTag = getTagAt(index);
+                assert klassTag == constants.jvmClass || klassTag == constants.jvmUnresolvedClass || klassTag == constants.jvmUnresolvedClassInError : klassTag;
                 // fall through
-            case Class:
-            case UnresolvedClass:
-            case UnresolvedClassInError:
+            case "Class":
+            case "UnresolvedClass":
+            case "UnresolvedClassInError":
                 final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
-                if (initialize) {
-                    Class<?> klass = type.mirror();
-                    if (!klass.isPrimitive() && !klass.isArray()) {
-                        UNSAFE.ensureClassInitialized(klass);
-                    }
+                if (initialize && !type.isPrimitive() && !type.isArray()) {
+                    type.ensureInitialized();
                 }
-                if (tag == JVM_CONSTANT.MethodRef) {
+                if (tag == constants.jvmMethodref) {
                     if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
                         final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-                        assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+                        assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
                         compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                     }
                 }
 
                 break;
-            case InvokeDynamic:
+            case "InvokeDynamic":
                 if (isInvokedynamicIndex(cpi)) {
                     compilerToVM().resolveInvokeDynamicInPool(this, cpi);
                 }
@@ -788,7 +792,7 @@
     public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
         if (Bytecodes.isInvokeHandleAlias(opcode)) {
             final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-            assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+            assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
             int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
             return op == opcode;
         }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Fri May 03 14:59:32 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
@@ -23,21 +23,19 @@
 package jdk.vm.ci.hotspot;
 
 import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 
 /**
  * Represents a constant that was retrieved from a constant pool. Used to keep track of the constant
  * pool slot for the constant.
  */
-public final class HotSpotConstantPoolObject extends HotSpotObjectConstantImpl {
+public final class HotSpotConstantPoolObject implements JavaConstant {
 
-    static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, Object object) {
+    public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
         return new HotSpotConstantPoolObject(type, cpi, object);
     }
 
-    public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
-        return forObject(type, cpi, ((HotSpotObjectConstantImpl) object).object());
-    }
-
+    private final JavaConstant constant;
     private final HotSpotResolvedObjectType type;
     private final int cpi;
 
@@ -49,24 +47,72 @@
         return cpi;
     }
 
-    HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, Object object) {
-        super(object, false);
+    HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, JavaConstant constant) {
         this.type = type;
         this.cpi = cpi;
+        this.constant = constant;
     }
 
     @Override
     public boolean equals(Object o) {
         if (o instanceof HotSpotConstantPoolObject) {
-            if (super.equals(o)) {
-                HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
-                return type.equals(other.type) && cpi == other.cpi;
-            }
+            HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
+            return type.equals(other.type) && cpi == other.cpi && constant.equals(other.constant);
         }
         return false;
     }
 
     @Override
+    public int hashCode() {
+        return constant.hashCode() + cpi + type.hashCode();
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return constant.getJavaKind();
+    }
+
+    @Override
+    public boolean isNull() {
+        return constant.isNull();
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return constant.isDefaultForKind();
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        return constant.asBoxedPrimitive();
+    }
+
+    @Override
+    public int asInt() {
+        return constant.asInt();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        return constant.asBoolean();
+    }
+
+    @Override
+    public long asLong() {
+        return constant.asLong();
+    }
+
+    @Override
+    public float asFloat() {
+        return constant.asFloat();
+    }
+
+    @Override
+    public double asDouble() {
+        return 0;
+    }
+
+    @Override
     public String toValueString() {
         return getCpType().getName() + getCpi();
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Fri May 03 14:59:32 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
@@ -22,7 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.reflect.Array;
 import java.util.Objects;
 
 import jdk.vm.ci.common.JVMCIError;
@@ -65,7 +64,7 @@
         if (x == y) {
             return true;
         } else if (x instanceof HotSpotObjectConstantImpl) {
-            return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object();
+            return y instanceof HotSpotObjectConstantImpl && x.equals(y);
         } else {
             return Objects.equals(x, y);
         }
@@ -77,11 +76,8 @@
             return null;
         }
 
-        Object arrayObject = ((HotSpotObjectConstantImpl) array).object();
-        if (!arrayObject.getClass().isArray()) {
-            return null;
-        }
-        return Array.getLength(arrayObject);
+        HotSpotObjectConstantImpl arrayObject = ((HotSpotObjectConstantImpl) array);
+        return runtime.getReflection().getLength(arrayObject);
     }
 
     @Override
@@ -89,18 +85,8 @@
         if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
             return null;
         }
-        Object a = ((HotSpotObjectConstantImpl) array).object();
-
-        if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
-            return null;
-        }
-
-        if (a instanceof Object[]) {
-            Object element = ((Object[]) a)[index];
-            return HotSpotObjectConstantImpl.forObject(element);
-        } else {
-            return JavaConstant.forBoxedPrimitive(Array.get(a, index));
-        }
+        HotSpotObjectConstantImpl arrayObject = ((HotSpotObjectConstantImpl) array);
+        return runtime.getReflection().readArrayElement(arrayObject, index);
     }
 
     /**
@@ -135,7 +121,7 @@
         if (source == null || !source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
             return null;
         }
-        return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive());
+        return runtime.getReflection().boxPrimitive(source);
     }
 
     @Override
@@ -146,28 +132,25 @@
         if (source.isNull()) {
             return null;
         }
-        return JavaConstant.forBoxedPrimitive(((HotSpotObjectConstantImpl) source).object());
+        return runtime.getReflection().unboxPrimitive((HotSpotObjectConstantImpl) source);
     }
 
     @Override
     public JavaConstant forString(String value) {
-        return HotSpotObjectConstantImpl.forObject(value);
+        return runtime.getReflection().forObject(value);
     }
 
     public JavaConstant forObject(Object value) {
-        return HotSpotObjectConstantImpl.forObject(value);
+        return runtime.getReflection().forObject(value);
     }
 
     @Override
     public ResolvedJavaType asJavaType(Constant constant) {
-        if (constant instanceof HotSpotObjectConstant) {
-            Object obj = ((HotSpotObjectConstantImpl) constant).object();
-            if (obj instanceof Class) {
-                return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType((Class<?>) obj);
-            }
+        if (constant instanceof HotSpotObjectConstantImpl) {
+            return ((HotSpotObjectConstantImpl) constant).asJavaType();
         }
         if (constant instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
+            MetaspaceObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
             if (obj instanceof HotSpotResolvedObjectTypeImpl) {
                 return (ResolvedJavaType) obj;
             }
@@ -179,15 +162,15 @@
     public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) {
         HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
         if (hotspotField.isStatic()) {
-            HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
+            HotSpotResolvedObjectTypeImpl holder = (HotSpotResolvedObjectTypeImpl) hotspotField.getDeclaringClass();
             if (holder.isInitialized()) {
-                return memoryAccess.readFieldValue(hotspotField, holder.mirror(), field.isVolatile());
+                return holder.readFieldValue(hotspotField, field.isVolatile());
             }
         } else {
-            if (receiver.isNonNull()) {
-                Object object = ((HotSpotObjectConstantImpl) receiver).object();
+            if (receiver.isNonNull() && receiver instanceof HotSpotObjectConstantImpl) {
+                HotSpotObjectConstantImpl object = ((HotSpotObjectConstantImpl) receiver);
                 if (hotspotField.isInObject(receiver)) {
-                    return memoryAccess.readFieldValue(hotspotField, object, field.isVolatile());
+                    return object.readFieldValue(hotspotField, field.isVolatile());
                 }
             }
         }
@@ -196,7 +179,7 @@
 
     @Override
     public JavaConstant asJavaClass(ResolvedJavaType type) {
-        return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedJavaType) type).mirror());
+        return ((HotSpotResolvedJavaType) type).getJavaMirror();
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 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
@@ -22,28 +22,28 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
 
-import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.code.InstalledCode;
 
 /**
- * Implementation of {@link InstalledCode} for HotSpot.
+ * Implementation of {@link InstalledCode} for HotSpot representing a {@code CodeBlob}. The address
+ * of the {@code CodeBlob} is stored in {@link InstalledCode#address}.
  */
 public abstract class HotSpotInstalledCode extends InstalledCode {
 
     /**
-     * Total size of the code blob.
+     * Total size of the code blob (i.e. {@code CodeBlob::size()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
 
     /**
-     * Start address of the code.
+     * Start address of the code (i.e. {@code CodeBlob::code_begin()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
 
     /**
-     * Size of the code.
+     * Size of the code (i.e. {@code CodeBlob::code_size()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
 
@@ -52,7 +52,7 @@
     }
 
     /**
-     * @return the total size of this code blob
+     * Gets the value of {@code CodeBlob::size()}.
      */
     public int getSize() {
         return size;
@@ -61,22 +61,25 @@
     @Override
     public abstract String toString();
 
+    /**
+     * Gets the value of {@code CodeBlob::code_begin()} if {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
     @Override
     public long getStart() {
         return codeStart;
     }
 
+    /**
+     * Gets the value of {@code CodeBlob::code_size()} if {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
     public long getCodeSize() {
         return codeSize;
     }
 
     @Override
     public byte[] getCode() {
-        if (!isValid()) {
-            return null;
-        }
-        byte[] code = new byte[codeSize];
-        UNSAFE.copyMemory(null, codeStart, code, Unsafe.ARRAY_BYTE_BASE_OFFSET, codeSize);
-        return code;
+        return compilerToVM().getCode(this);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJDKReflection.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,491 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link HotSpotJVMCIReflection} in terms of standard JDK reflection API. This is
+ * only available when running in the HotSpot heap.
+ */
+final class HotSpotJDKReflection extends HotSpotJVMCIReflection {
+
+    @Override
+    Object resolveObject(HotSpotObjectConstantImpl object) {
+        if (object == null) {
+            return null;
+        }
+        return ((DirectHotSpotObjectConstantImpl) object).object;
+    }
+
+    @Override
+    boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj) {
+        Class<?> javaMirror = getMirror(holder);
+        Object value = resolveObject(obj);
+        return javaMirror.isInstance(value);
+    }
+
+    @Override
+    boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isAssignableFrom(getMirror(otherType));
+
+    }
+
+    @Override
+    Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getAnnotations();
+    }
+
+    @Override
+    Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getDeclaredAnnotations();
+    }
+
+    @Override
+    <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getAnnotation(annotationClass);
+    }
+
+    @Override
+    boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isLocalClass();
+    }
+
+    @Override
+    boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isMemberClass();
+    }
+
+    @Override
+    HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return (HotSpotResolvedObjectType) runtime().fromClass(javaMirror.getEnclosingClass());
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
+        Class<?> javaMirror = getMirror(holder);
+        return readFieldValue(field, javaMirror, isVolatile);
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
+        Object value = resolveObject(object);
+        return readFieldValue(field, value, isVolatile);
+    }
+
+    @Override
+    boolean equals(HotSpotObjectConstantImpl a, HotSpotObjectConstantImpl b) {
+        return resolveObject(a) == resolveObject(b) && a.isCompressed() == b.isCompressed();
+    }
+
+    @Override
+    JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType holder) {
+        return holder.mirror;
+    }
+
+    @Override
+    ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
+        java.lang.reflect.Parameter[] javaParameters = getMethod(javaMethod).getParameters();
+        ResolvedJavaMethod.Parameter[] res = new ResolvedJavaMethod.Parameter[javaParameters.length];
+        for (int i = 0; i < res.length; i++) {
+            java.lang.reflect.Parameter src = javaParameters[i];
+            String paramName = src.isNamePresent() ? src.getName() : null;
+            res[i] = new ResolvedJavaMethod.Parameter(paramName, src.getModifiers(), javaMethod, i);
+        }
+        return res;
+    }
+
+    @Override
+    Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getParameterAnnotations();
+    }
+
+    @Override
+    Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getGenericParameterTypes();
+    }
+
+    @Override
+    Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        return getField(javaField).getAnnotations();
+    }
+
+    @Override
+    Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getAnnotations();
+    }
+
+    @Override
+    Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getDeclaredAnnotations();
+    }
+
+    @Override
+    Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        return getField(javaField).getDeclaredAnnotations();
+    }
+
+    @Override
+    <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
+        return getMethod(javaMethod).getAnnotation(annotationClass);
+    }
+
+    @Override
+    <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
+        return getField(javaField).getAnnotation(annotationClass);
+    }
+
+    @Override
+    HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        Class<?> theClass = value.getClass();
+        return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(theClass);
+    }
+
+    @Override
+    String asString(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return null;
+    }
+
+    @Override
+    ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        if (value instanceof Class) {
+            Class<?> javaClass = (Class<?>) value;
+            return runtime().fromClass(javaClass);
+        }
+        if (value instanceof ResolvedJavaType) {
+            return (ResolvedJavaType) value;
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
+        Object value = resolveObject(object);
+        if (type.isInstance(value)) {
+            return (T) value;
+        }
+        return null;
+    }
+
+    @Override
+    Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
+        Object value = resolveObject(object);
+        if (getMirror(type).isInstance(value)) {
+            return value;
+        }
+        return null;
+    }
+
+    @Override
+    String formatString(HotSpotObjectConstantImpl object) {
+        return JavaKind.Object.format(resolveObject(object));
+    }
+
+    @Override
+    Integer getLength(HotSpotObjectConstantImpl arrayObject) {
+        Object object = resolveObject(arrayObject);
+        if (object.getClass().isArray()) {
+            return Array.getLength(object);
+        }
+        return null;
+    }
+
+    @Override
+    JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
+        Object a = resolveObject(arrayObject);
+        if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
+            return null;
+        }
+        if (a instanceof Object[]) {
+            Object element = ((Object[]) a)[index];
+            return forObject(element);
+        } else {
+            if (a instanceof int[]) {
+                return JavaConstant.forInt(((int[]) a)[index]);
+            } else if (a instanceof char[]) {
+                return JavaConstant.forChar(((char[]) a)[index]);
+            } else if (a instanceof byte[]) {
+                return JavaConstant.forByte(((byte[]) a)[index]);
+            } else if (a instanceof long[]) {
+                return JavaConstant.forLong(((long[]) a)[index]);
+            } else if (a instanceof short[]) {
+                return JavaConstant.forShort(((short[]) a)[index]);
+            } else if (a instanceof float[]) {
+                return JavaConstant.forFloat(((float[]) a)[index]);
+            } else if (a instanceof double[]) {
+                return JavaConstant.forDouble(((double[]) a)[index]);
+            } else if (a instanceof boolean[]) {
+                return JavaConstant.forBoolean(((boolean[]) a)[index]);
+            } else {
+                throw new JVMCIError("Should not reach here");
+            }
+        }
+    }
+
+    @Override
+    JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
+        return JavaConstant.forBoxedPrimitive(resolveObject(source));
+    }
+
+    @Override
+    JavaConstant forObject(Object value) {
+        if (value == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return forNonNullObject(value);
+    }
+
+    private static HotSpotObjectConstantImpl forNonNullObject(Object value) {
+        return DirectHotSpotObjectConstantImpl.forNonNullObject(value, false);
+    }
+
+    @Override
+    JavaConstant boxPrimitive(JavaConstant source) {
+        return forNonNullObject(source.asBoxedPrimitive());
+    }
+
+    @Override
+    int getInt(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getInt((resolveObject(object)), displacement);
+    }
+
+    @Override
+    byte getByte(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getByte(resolveObject(object), displacement);
+    }
+
+    @Override
+    short getShort(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getShort(resolveObject(object), displacement);
+    }
+
+    @Override
+    long getLong(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getLong(resolveObject(object), displacement);
+    }
+
+    @Override
+    void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
+        checkRead(kind, displacement, type, resolveObject(constant));
+    }
+
+    /**
+     * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
+     * as initialization is idempotent.
+     */
+    private long oopSizeOffset;
+
+    private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
+        MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
+        ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
+        for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
+            if (f.getName().equals("oop_size")) {
+                int offset = f.getOffset();
+                assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
+                return offset;
+            }
+        }
+        throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
+    }
+
+    long oopSizeOffset() {
+        if (oopSizeOffset == 0) {
+            oopSizeOffset = computeOopSizeOffset(runtime());
+        }
+        return oopSizeOffset;
+    }
+
+    private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object) {
+        if (type.isArray()) {
+            ResolvedJavaType componentType = type.getComponentType();
+            JavaKind componentKind = componentType.getJavaKind();
+            final int headerSize = runtime().getArrayBaseOffset(componentKind);
+            int sizeOfElement = runtime().getArrayIndexScale(componentKind);
+            int length = Array.getLength(object);
+            long arrayEnd = headerSize + (sizeOfElement * length);
+            boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
+            if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
+                int index = (int) ((displacement - headerSize) / sizeOfElement);
+                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
+                                " at offset " + displacement + " (index ~ " + index + ") in " +
+                                type.toJavaName() + " object of length " + length);
+            }
+        } else if (kind != JavaKind.Object) {
+            long size;
+            if (object instanceof Class) {
+                int wordSize = runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
+                size = UNSAFE.getInt(object, oopSizeOffset()) * wordSize;
+            } else {
+                size = Math.abs(type.instanceSize());
+            }
+            int bytesToRead = kind.getByteCount();
+            if (displacement + bytesToRead > size || displacement < 0) {
+                throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
+                                type.toJavaName() + " object of size " + size);
+            }
+        } else {
+            ResolvedJavaField field = null;
+            if (object instanceof Class) {
+                // Read of a static field
+                HotSpotResolvedJavaType hotSpotResolvedJavaType = runtime().fromClass((Class<?>) object);
+                if (hotSpotResolvedJavaType instanceof HotSpotResolvedObjectTypeImpl) {
+                    HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) hotSpotResolvedJavaType;
+                    field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
+                }
+            }
+            if (field == null) {
+                field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
+            }
+            if (field == null) {
+                throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
+                                " at offset " + displacement + " in " + type.toJavaName() + " object");
+            }
+            if (field.getJavaKind() != JavaKind.Object) {
+                throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
+                                " at offset " + displacement + " in " + type.toJavaName() + " object");
+            }
+        }
+        return true;
+    }
+
+    JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
+        assert obj != null;
+        assert !field.isStatic() || obj instanceof Class;
+        long displacement = field.getOffset();
+
+        assert checkRead(field.getJavaKind(), displacement,
+                        (HotSpotResolvedObjectType) runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(field.isStatic() ? (Class<?>) obj : obj.getClass()),
+                        obj);
+        JavaKind kind = field.getJavaKind();
+        switch (kind) {
+            case Boolean:
+                return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
+            case Byte:
+                return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
+            case Char:
+                return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
+            case Short:
+                return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
+            case Int:
+                return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
+            case Long:
+                return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
+            case Float:
+                return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
+            case Double:
+                return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
+            case Object:
+                return forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
+            default:
+                throw new IllegalArgumentException("Unsupported kind: " + kind);
+
+        }
+    }
+
+    /**
+     * Gets a {@link Method} object corresponding to {@code method}. This method guarantees the same
+     * {@link Method} object is returned if called twice on the same {@code method} value.
+     */
+    private static Executable getMethod(HotSpotResolvedJavaMethodImpl method) {
+        assert !method.isClassInitializer() : method;
+        if (method.toJavaCache == null) {
+            synchronized (method) {
+                if (method.toJavaCache == null) {
+                    method.toJavaCache = compilerToVM().asReflectionExecutable(method);
+                }
+            }
+        }
+        return method.toJavaCache;
+    }
+
+    /**
+     * Gets a {@link Field} object corresponding to {@code field}. This method guarantees the same
+     * {@link Field} object is returned if called twice on the same {@code field} value. This is
+     * required to ensure the results of {@link HotSpotResolvedJavaFieldImpl#getAnnotations()} and
+     * {@link HotSpotResolvedJavaFieldImpl#getAnnotation(Class)} are stable (i.e., for a given field
+     * {@code f} and annotation class {@code a}, the same object is returned for each call to
+     * {@code f.getAnnotation(a)}).
+     */
+    private static Field getField(HotSpotResolvedJavaFieldImpl field) {
+        HotSpotResolvedObjectTypeImpl declaringClass = field.getDeclaringClass();
+        synchronized (declaringClass) {
+            HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = declaringClass.reflectionFieldCache;
+            if (cache == null) {
+                cache = new HashMap<>();
+                declaringClass.reflectionFieldCache = cache;
+            }
+            Field reflect = cache.get(field);
+            if (reflect == null) {
+                reflect = compilerToVM().asReflectionField(field.getDeclaringClass(), field.getIndex());
+                cache.put(field, reflect);
+            }
+            return reflect;
+        }
+    }
+
+    Class<?> getMirror(HotSpotResolvedObjectTypeImpl holder) {
+        return (Class<?>) resolveObject((HotSpotObjectConstantImpl) holder.getJavaMirror());
+    }
+
+    Class<?> getMirror(HotSpotResolvedJavaType type) {
+        assert type != null;
+        if (type instanceof HotSpotResolvedPrimitiveType) {
+            return (Class<?>) resolveObject(((HotSpotResolvedPrimitiveType) type).mirror);
+        } else {
+            return getMirror((HotSpotResolvedObjectTypeImpl) type);
+        }
+    }
+}
+
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Fri May 03 14:59:32 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
@@ -22,10 +22,12 @@
  */
 package jdk.vm.ci.hotspot;
 
+import java.util.List;
 import java.util.Set;
 
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
 import jdk.vm.ci.runtime.JVMCICompiler;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
@@ -33,6 +35,8 @@
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.JVMCIServiceLocator;
 
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 final class HotSpotJVMCICompilerConfig {
 
     /**
@@ -61,7 +65,7 @@
     /**
      * Factory of the selected system compiler.
      */
-    private static JVMCICompilerFactory compilerFactory;
+    @NativeImageReinitialize private static JVMCICompilerFactory compilerFactory;
 
     /**
      * Gets the selected system compiler factory.
@@ -78,7 +82,7 @@
                 if (compilerName.isEmpty() || compilerName.equals("null")) {
                     factory = new DummyCompilerFactory();
                 } else {
-                    for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                    for (JVMCICompilerFactory f : getJVMCICompilerFactories()) {
                         if (f.getCompilerName().equals(compilerName)) {
                             factory = f;
                         }
@@ -89,7 +93,7 @@
                 }
             } else {
                 // Auto select a single available compiler
-                for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                for (JVMCICompilerFactory f : getJVMCICompilerFactories()) {
                     if (factory == null) {
                         openJVMCITo(f.getClass().getModule());
                         factory = f;
@@ -113,15 +117,21 @@
      * Opens all JVMCI packages to {@code otherModule}.
      */
     private static void openJVMCITo(Module otherModule) {
-        Module jvmci = HotSpotJVMCICompilerConfig.class.getModule();
-        if (jvmci != otherModule) {
-            Set<String> packages = jvmci.getPackages();
-            for (String pkg : packages) {
-                boolean opened = jvmci.isOpen(pkg, otherModule);
-                if (!opened) {
-                    jvmci.addOpens(pkg, otherModule);
+        if (!IS_IN_NATIVE_IMAGE) {
+            Module jvmci = HotSpotJVMCICompilerConfig.class.getModule();
+            if (jvmci != otherModule) {
+                Set<String> packages = jvmci.getPackages();
+                for (String pkg : packages) {
+                    boolean opened = jvmci.isOpen(pkg, otherModule);
+                    if (!opened) {
+                        jvmci.addOpens(pkg, otherModule);
+                    }
                 }
             }
         }
     }
+
+    private static List<JVMCICompilerFactory> getJVMCICompilerFactories() {
+        return JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class);
+    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +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.
- */
-package jdk.vm.ci.hotspot;
-
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
-/**
- * This class manages the set of metadata roots that must be scanned during garbage collection.
- * Because of class redefinition Method* and ConstantPool* can be freed if they don't appear to be
- * in use so they must be tracked when there are live references to them from Java.
- *
- * The general theory of operation is that all {@link MetaspaceWrapperObject}s are created by
- * calling into the VM which calls back out to actually create the wrapper instance. During the call
- * the VM keeps the metadata reference alive through the use of metadata handles. Once the call
- * completes the wrapper object is registered here and will be scanned during metadata scanning. The
- * weakness of the reference to the wrapper object allows them to be reclaimed when they are no
- * longer used.
- *
- */
-class HotSpotJVMCIMetaAccessContext {
-
-    /**
-     * The set of currently live contexts used for tracking of live metadata. Examined from the VM
-     * during garbage collection.
-     */
-    private static WeakReference<?>[] allContexts = new WeakReference<?>[0];
-
-    /**
-     * This is a chunked list of metadata roots. It can be read from VM native code so it's been
-     * marked volatile to ensure the order of updates are respected.
-     */
-    private volatile Object[] metadataRoots;
-
-    private ChunkedList<WeakReference<MetaspaceWrapperObject>> list = new ChunkedList<>();
-
-    /**
-     * The number of weak references freed since the last time the list was shrunk.
-     */
-    private int freed;
-
-    /**
-     * The {@link ReferenceQueue} tracking the weak references created by this context.
-     */
-    private final ReferenceQueue<MetaspaceWrapperObject> queue = new ReferenceQueue<>();
-
-    static synchronized void add(HotSpotJVMCIMetaAccessContext context) {
-        for (int i = 0; i < allContexts.length; i++) {
-            if (allContexts[i] == null || allContexts[i].get() == null) {
-                allContexts[i] = new WeakReference<>(context);
-                return;
-            }
-        }
-        int index = allContexts.length;
-        allContexts = Arrays.copyOf(allContexts, index + 2);
-        allContexts[index] = new WeakReference<>(context);
-    }
-
-    HotSpotJVMCIMetaAccessContext() {
-        add(this);
-    }
-
-    /**
-     * Periodically trim the list of tracked metadata. A new list is created to replace the old to
-     * avoid concurrent scanning issues.
-     */
-    private void clean() {
-        Reference<?> ref = queue.poll();
-        if (ref == null) {
-            return;
-        }
-        while (ref != null) {
-            freed++;
-            ref = queue.poll();
-        }
-        if (freed > list.size() / 2) {
-            ChunkedList<WeakReference<MetaspaceWrapperObject>> newList = new ChunkedList<>();
-            for (WeakReference<MetaspaceWrapperObject> element : list) {
-                /*
-                 * The referent could become null anywhere in here but it doesn't matter. It will
-                 * get cleaned up next time.
-                 */
-                if (element != null && element.get() != null) {
-                    newList.add(element);
-                }
-            }
-            list = newList;
-            metadataRoots = list.getHead();
-            freed = 0;
-        }
-    }
-
-    /**
-     * Add a {@link MetaspaceWrapperObject} to tracked by the GC. It's assumed that the caller is
-     * responsible for keeping the reference alive for the duration of the call. Once registration
-     * is complete then the VM will ensure it's kept alive.
-     *
-     * @param metaspaceObject
-     */
-
-    public synchronized void add(MetaspaceWrapperObject metaspaceObject) {
-        clean();
-        list.add(new WeakReference<>(metaspaceObject, queue));
-        if (list.getHead() != metadataRoots) {
-            /*
-             * The list enlarged so update the head.
-             */
-            metadataRoots = list.getHead();
-        }
-        assert isRegistered(metaspaceObject);
-    }
-
-    protected ResolvedJavaType createClass(Class<?> javaClass) {
-        if (javaClass.isPrimitive()) {
-            JavaKind kind = JavaKind.fromJavaClass(javaClass);
-            return new HotSpotResolvedPrimitiveType(kind);
-        } else {
-            return new HotSpotResolvedObjectTypeImpl(javaClass, this);
-        }
-    }
-
-    private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<>() {
-        @Override
-        protected WeakReference<ResolvedJavaType> computeValue(Class<?> type) {
-            return new WeakReference<>(createClass(type));
-        }
-    };
-
-    /**
-     * Gets the JVMCI mirror for a {@link Class} object.
-     *
-     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
-     */
-    public ResolvedJavaType fromClass(Class<?> javaClass) {
-        ResolvedJavaType javaType = null;
-        while (javaType == null) {
-            WeakReference<ResolvedJavaType> type = resolvedJavaType.get(javaClass);
-            javaType = type.get();
-            if (javaType == null) {
-                /*
-                 * If the referent has become null, clear out the current value and let computeValue
-                 * above create a new value. Reload the value in a loop because in theory the
-                 * WeakReference referent can be reclaimed at any point.
-                 */
-                resolvedJavaType.remove(javaClass);
-            }
-        }
-        return javaType;
-    }
-
-    /**
-     * A very simple append only chunked list implementation.
-     */
-    static class ChunkedList<T> implements Iterable<T> {
-        private static final int CHUNK_SIZE = 32;
-
-        private static final int NEXT_CHUNK_INDEX = CHUNK_SIZE - 1;
-
-        private Object[] head;
-        private int index;
-        private int size;
-
-        ChunkedList() {
-            head = new Object[CHUNK_SIZE];
-            index = 0;
-        }
-
-        void add(T element) {
-            if (index == NEXT_CHUNK_INDEX) {
-                Object[] newHead = new Object[CHUNK_SIZE];
-                newHead[index] = head;
-                head = newHead;
-                index = 0;
-            }
-            head[index++] = element;
-            size++;
-        }
-
-        Object[] getHead() {
-            return head;
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return new ChunkIterator<>();
-        }
-
-        int size() {
-            return size;
-        }
-
-        class ChunkIterator<V> implements Iterator<V> {
-
-            ChunkIterator() {
-                currentChunk = head;
-                currentIndex = -1;
-                next = findNext();
-            }
-
-            Object[] currentChunk;
-            int currentIndex;
-            V next;
-
-            @SuppressWarnings("unchecked")
-            V findNext() {
-                V result;
-                do {
-                    currentIndex++;
-                    if (currentIndex == NEXT_CHUNK_INDEX) {
-                        currentChunk = (Object[]) currentChunk[currentIndex];
-                        currentIndex = 0;
-                        if (currentChunk == null) {
-                            return null;
-                        }
-                    }
-                    result = (V) currentChunk[currentIndex];
-                } while (result == null);
-                return result;
-            }
-
-            @Override
-            public boolean hasNext() {
-                return next != null;
-            }
-
-            @Override
-            public V next() {
-                V result = next;
-                next = findNext();
-                return result;
-            }
-
-        }
-
-    }
-
-    synchronized boolean isRegistered(MetaspaceWrapperObject wrapper) {
-        for (WeakReference<MetaspaceWrapperObject> m : list) {
-            if (m != null && m.get() == wrapper) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Reflection interface for reflecting on the internals of HotSpot JVMCI types and objects.
+ */
+abstract class HotSpotJVMCIReflection {
+
+    abstract boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj);
+
+    abstract boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType);
+
+    abstract Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass);
+
+    abstract boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    abstract JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    abstract boolean equals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that);
+
+    abstract JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedJavaType);
+
+    abstract ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaMethod);
+
+    abstract Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaField);
+
+    abstract Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod);
+
+    abstract <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass);
+
+    abstract HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object);
+
+    abstract String asString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Given a {@link java.lang.Class} instance, return the corresponding ResolvedJavaType.
+     */
+    abstract ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object);
+
+    abstract <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type);
+
+    abstract Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type);
+
+    abstract String formatString(HotSpotObjectConstantImpl object);
+
+    abstract Integer getLength(HotSpotObjectConstantImpl arrayObject);
+
+    abstract JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index);
+
+    abstract JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source);
+
+    abstract JavaConstant forObject(Object value);
+
+    abstract JavaConstant boxPrimitive(JavaConstant source);
+
+    abstract int getInt(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract byte getByte(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract short getShort(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract long getLong(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type);
+
+    abstract <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass);
+
+    /**
+     * Resolves {@code objectHandle} to a raw object if possible.
+     *
+     * @throws HotSpotJVMCIUnsupportedOperationError if {@code objectHandle} refers to an object in
+     *             another heap
+     */
+    abstract Object resolveObject(HotSpotObjectConstantImpl objectHandle);
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri May 03 14:59:32 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
@@ -23,11 +23,22 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.common.InitTimer.timer;
+import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
 
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.io.Serializable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
 import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.ref.WeakReference;
+
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,18 +46,18 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Predicate;
 
-import jdk.internal.misc.VM;
 import jdk.internal.misc.Unsafe;
+
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.CompilationRequestResult;
 import jdk.vm.ci.code.CompiledCode;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevel;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -57,42 +68,144 @@
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
 import jdk.vm.ci.services.JVMCIServiceLocator;
+import jdk.vm.ci.services.Services;
 
 /**
  * HotSpot implementation of a JVMCI runtime.
- *
- * The initialization of this class is very fragile since it's initialized both through
- * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
- * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
- * can't have a static initializer and any required initialization must be done as part of
- * {@link #runtime()}. This allows the initialization to funnel back through
- * {@link JVMCI#initialize()} without deadlocking.
  */
 public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
 
-    @SuppressWarnings("try")
-    static class DelayedInit {
-        private static final HotSpotJVMCIRuntime instance;
+    /**
+     * Singleton instance lazily initialized via double-checked locking.
+     */
+    @NativeImageReinitialize private static volatile HotSpotJVMCIRuntime instance;
+
+    private HotSpotResolvedObjectTypeImpl javaLangObject;
+    private HotSpotResolvedObjectTypeImpl javaLangInvokeMethodHandle;
+    private HotSpotResolvedObjectTypeImpl constantCallSiteType;
+    private HotSpotResolvedObjectTypeImpl callSiteType;
+    private HotSpotResolvedObjectTypeImpl javaLangString;
+    private HotSpotResolvedObjectTypeImpl javaLangClass;
+    private HotSpotResolvedObjectTypeImpl throwableType;
+    private HotSpotResolvedObjectTypeImpl serializableType;
+    private HotSpotResolvedObjectTypeImpl cloneableType;
+    private HotSpotResolvedObjectTypeImpl enumType;
 
-        static {
-            try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
-                instance = new HotSpotJVMCIRuntime();
+    HotSpotResolvedObjectTypeImpl getJavaLangObject() {
+        if (javaLangObject == null) {
+            javaLangObject = (HotSpotResolvedObjectTypeImpl) fromClass(Object.class);
+        }
+        return javaLangObject;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangString() {
+        if (javaLangString == null) {
+            javaLangString = (HotSpotResolvedObjectTypeImpl) fromClass(String.class);
+        }
+        return javaLangString;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangClass() {
+        if (javaLangClass == null) {
+            javaLangClass = (HotSpotResolvedObjectTypeImpl) fromClass(Class.class);
+        }
+        return javaLangClass;
+    }
 
-                // Can only do eager initialization of the JVMCI compiler
-                // once the singleton instance is available.
-                if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
-                    instance.getCompiler();
-                }
-            }
+    HotSpotResolvedObjectTypeImpl getJavaLangCloneable() {
+        if (cloneableType == null) {
+            cloneableType = (HotSpotResolvedObjectTypeImpl) fromClass(Cloneable.class);
+        }
+        return cloneableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangSerializable() {
+        if (serializableType == null) {
+            serializableType = (HotSpotResolvedObjectTypeImpl) fromClass(Serializable.class);
+        }
+        return serializableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangThrowable() {
+        if (throwableType == null) {
+            throwableType = (HotSpotResolvedObjectTypeImpl) fromClass(Throwable.class);
         }
+        return throwableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangEnum() {
+        if (enumType == null) {
+            enumType = (HotSpotResolvedObjectTypeImpl) fromClass(Enum.class);
+        }
+        return enumType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getConstantCallSite() {
+        if (constantCallSiteType == null) {
+            constantCallSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(ConstantCallSite.class);
+        }
+        return constantCallSiteType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getCallSite() {
+        if (callSiteType == null) {
+            callSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(CallSite.class);
+        }
+        return callSiteType;
+    }
+
+    HotSpotResolvedObjectType getMethodHandleClass() {
+        if (javaLangInvokeMethodHandle == null) {
+            javaLangInvokeMethodHandle = (HotSpotResolvedObjectTypeImpl) fromClass(MethodHandle.class);
+        }
+        return javaLangInvokeMethodHandle;
     }
 
     /**
      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
      */
+    @VMEntryPoint
+    @SuppressWarnings("try")
     public static HotSpotJVMCIRuntime runtime() {
-        JVMCI.initialize();
-        return DelayedInit.instance;
+        HotSpotJVMCIRuntime result = instance;
+        if (result == null) {
+            // Synchronize on JVMCI.class to avoid deadlock
+            // between the two JVMCI initialization paths:
+            // HotSpotJVMCIRuntime.runtime() and JVMCI.getRuntime().
+            synchronized (JVMCI.class) {
+                result = instance;
+                if (result == null) {
+                    try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
+                        instance = result = new HotSpotJVMCIRuntime();
+
+                        // Can only do eager initialization of the JVMCI compiler
+                        // once the singleton instance is available.
+                        if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
+                            instance.getCompiler();
+                        }
+                    }
+                    // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
+                    // initialized.
+                    JVMCI.getRuntime();
+                }
+            }
+        }
+        return result;
+    }
+
+    @VMEntryPoint
+    static Throwable decodeThrowable(String encodedThrowable) throws Throwable {
+        return TranslatedException.decodeThrowable(encodedThrowable);
+    }
+
+    @VMEntryPoint
+    static String encodeThrowable(Throwable throwable) throws Throwable {
+        return TranslatedException.encodeThrowable(throwable);
+    }
+
+    @VMEntryPoint
+    static String callToString(Object o) {
+        return o.toString();
     }
 
     /**
@@ -101,17 +214,17 @@
     public enum Option {
         // @formatter:off
         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
-                                     "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
-                                     "An empty string or the value \"null\" selects a compiler " +
-                                     "that will raise an exception upon receiving a compilation request."),
+                "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
+                "An empty string or the value \"null\" selects a compiler " +
+                "that will raise an exception upon receiving a compilation request."),
         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
         // so that -XX:+JVMCIPrintProperties shows the option.
         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
         TraceMethodDataFilter(String.class, null,
-                        "Enables tracing of profiling info when read by JVMCI.",
-                        "Empty value: trace all methods",
-                        "Non-empty value: trace methods whose fully qualified name contains the value."),
+                "Enables tracing of profiling info when read by JVMCI.",
+                "Empty value: trace all methods",
+                "Non-empty value: trace methods whose fully qualified name contains the value."),
         UseProfilingInformation(Boolean.class, true, "");
         // @formatter:on
 
@@ -121,12 +234,12 @@
         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 
         /**
-         * Marker for uninitialized flags.
+         * Sentinel for value initialized to {@code null} since {@code null} means uninitialized.
          */
-        private static final String UNINITIALIZED = "UNINITIALIZED";
+        private static final String NULL_VALUE = "NULL";
 
         private final Class<?> type;
-        private Object value;
+        @NativeImageReinitialize private Object value;
         private final Object defaultValue;
         private boolean isDefault;
         private final String[] helpLines;
@@ -134,17 +247,16 @@
         Option(Class<?> type, Object defaultValue, String... helpLines) {
             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
             this.type = type;
-            this.value = UNINITIALIZED;
             this.defaultValue = defaultValue;
             this.helpLines = helpLines;
         }
 
         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
         private Object getValue() {
-            if (value == UNINITIALIZED) {
-                String propertyValue = VM.getSavedProperty(getPropertyName());
+            if (value == null) {
+                String propertyValue = Services.getSavedProperty(getPropertyName());
                 if (propertyValue == null) {
-                    this.value = defaultValue;
+                    this.value = defaultValue == null ? NULL_VALUE : defaultValue;
                     this.isDefault = true;
                 } else {
                     if (type == Boolean.class) {
@@ -156,10 +268,8 @@
                     }
                     this.isDefault = false;
                 }
-                // Saved properties should not be interned - let's be sure
-                assert value != UNINITIALIZED;
             }
-            return value;
+            return value == NULL_VALUE ? null : value;
         }
 
         /**
@@ -222,8 +332,10 @@
         }
     }
 
-    static HotSpotJVMCIBackendFactory findFactory(String architecture) {
-        for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader())) {
+    private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
+        Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
+assert factories != null : "sanity";
+        for (HotSpotJVMCIBackendFactory factory : factories) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
                 return factory;
             }
@@ -232,6 +344,23 @@
         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
     }
 
+    private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
+
+    @SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
+    private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
+        if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
+            return cachedHotSpotJVMCIBackendFactories;
+        }
+        Iterable<HotSpotJVMCIBackendFactory> result = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader());
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            cachedHotSpotJVMCIBackendFactories = new ArrayList<>();
+            for (HotSpotJVMCIBackendFactory factory : result) {
+                cachedHotSpotJVMCIBackendFactories.add(factory);
+            }
+        }
+        return result;
+    }
+
     /**
      * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
      */
@@ -239,22 +368,33 @@
         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
     }
 
-    final CompilerToVM compilerToVm;
+    protected final CompilerToVM compilerToVm;
 
     protected final HotSpotVMConfigStore configStore;
-    private final HotSpotVMConfig config;
+    protected final HotSpotVMConfig config;
     private final JVMCIBackend hostBackend;
 
     private final JVMCICompilerFactory compilerFactory;
     private final HotSpotJVMCICompilerFactory hsCompilerFactory;
     private volatile JVMCICompiler compiler;
-    final HotSpotJVMCIMetaAccessContext metaAccessContext;
+    protected final HotSpotJVMCIReflection reflection;
+
+    @NativeImageReinitialize private volatile boolean creatingCompiler;
 
     /**
-     * Stores the result of {@link HotSpotJVMCICompilerFactory#getCompilationLevelAdjustment} so
-     * that it can be read from the VM.
+     * Cache for speeding up {@link #fromClass(Class)}.
      */
-    @SuppressWarnings("unused") private final int compilationLevelAdjustment;
+    @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType;
+
+    @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;
+
+    /**
+     * Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can
+     * be read from the VM.
+     */
+    @SuppressWarnings("unused")//
+    @NativeImageReinitialize private Module[] excludeFromJVMCICompilation;
+
 
     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
 
@@ -280,6 +420,16 @@
             config = new HotSpotVMConfig(configStore);
         }
 
+        reflection = IS_IN_NATIVE_IMAGE ? new SharedLibraryJVMCIReflection() : new HotSpotJDKReflection();
+
+        PrintStream vmLogStream = null;
+        if (IS_IN_NATIVE_IMAGE) {
+            // Redirect System.out and System.err to HotSpot's TTY stream
+            vmLogStream = new PrintStream(getLogStream());
+            System.setOut(vmLogStream);
+            System.setErr(vmLogStream);
+        }
+
         String hostArchitecture = config.getHostArchitectureName();
 
         HotSpotJVMCIBackendFactory factory;
@@ -291,40 +441,103 @@
             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
         }
 
-        metaAccessContext = new HotSpotJVMCIMetaAccessContext();
-
         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
-            switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
-                case None:
-                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
-                    break;
-                case ByHolder:
-                    compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
-                    break;
-                case ByFullSignature:
-                    compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
-                    break;
-                default:
-                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
-                    break;
+            if (hsCompilerFactory.getCompilationLevelAdjustment() != None) {
+                String name = HotSpotJVMCICompilerFactory.class.getName();
+                String msg = String.format("%s.getCompilationLevelAdjustment() is no longer supported. " +
+                                "Use %s.excludeFromJVMCICompilation() instead.", name, name);
+                throw new UnsupportedOperationException(msg);
             }
         } else {
             hsCompilerFactory = null;
-            compilationLevelAdjustment = config.compLevelAdjustmentNone;
         }
 
         if (config.getFlag("JVMCIPrintProperties", Boolean.class)) {
-            PrintStream out = new PrintStream(getLogStream());
-            Option.printProperties(out);
-            compilerFactory.printProperties(out);
+            if (vmLogStream == null) {
+                vmLogStream = new PrintStream(getLogStream());
+            }
+            Option.printProperties(vmLogStream);
+            compilerFactory.printProperties(vmLogStream);
             System.exit(0);
         }
 
         if (Option.PrintConfig.getBoolean()) {
-            configStore.printConfig();
+            printConfig(configStore, compilerToVm);
+        }
+    }
+
+    HotSpotResolvedJavaType createClass(Class<?> javaClass) {
+        if (javaClass.isPrimitive()) {
+            return HotSpotResolvedPrimitiveType.forKind(JavaKind.fromJavaClass(javaClass));
+        }
+        if (IS_IN_NATIVE_IMAGE) {
+            try {
+                return compilerToVm.lookupType(javaClass.getName().replace('.', '/'), null, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
+        }
+        return compilerToVm.lookupClass(javaClass);
+    }
+
+    private HotSpotResolvedJavaType fromClass0(Class<?> javaClass) {
+        if (resolvedJavaType == null) {
+            synchronized (this) {
+                if (resolvedJavaType == null) {
+                    resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() {
+                        @Override
+                        protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) {
+                            return new WeakReference<>(createClass(type));
+                        }
+                    };
+                }
+            }
         }
+        HotSpotResolvedJavaType javaType = null;
+        while (javaType == null) {
+            WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass);
+            javaType = type.get();
+            if (javaType == null) {
+                /*
+                 * If the referent has become null, clear out the current value and let computeValue
+                 * above create a new value. Reload the value in a loop because in theory the
+                 * WeakReference referent can be reclaimed at any point.
+                 */
+                resolvedJavaType.remove(javaClass);
+            }
+        }
+        return javaType;
+    }
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+     */
+    HotSpotResolvedJavaType fromClass(Class<?> javaClass) {
+        if (javaClass == null) {
+            return null;
+        }
+        return fromClass0(javaClass);
+    }
+
+    synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
+        if (resolvedJavaTypes == null) {
+            resolvedJavaTypes = new HashMap<>();
+        }
+        assert klassPointer != 0;
+        WeakReference<ResolvedJavaType> klassReference = resolvedJavaTypes.get(klassPointer);
+        HotSpotResolvedObjectTypeImpl javaType = null;
+        if (klassReference != null) {
+            javaType = (HotSpotResolvedObjectTypeImpl) klassReference.get();
+        }
+        if (javaType == null) {
+            javaType = new HotSpotResolvedObjectTypeImpl(klassPointer, signature);
+            resolvedJavaTypes.put(klassPointer, new WeakReference<>(javaType));
+        }
+        return javaType;
     }
 
     private JVMCIBackend registerBackend(JVMCIBackend backend) {
@@ -334,24 +547,21 @@
         return backend;
     }
 
-    ResolvedJavaType fromClass(Class<?> javaClass) {
-        return metaAccessContext.fromClass(javaClass);
-    }
-
     public HotSpotVMConfigStore getConfigStore() {
         return configStore;
     }
 
-    HotSpotVMConfig getConfig() {
+    public HotSpotVMConfig getConfig() {
         return config;
     }
 
-    CompilerToVM getCompilerToVM() {
+    public CompilerToVM getCompilerToVM() {
         return compilerToVm;
     }
 
-    // Non-volatile since multi-initialization is harmless
-    private Predicate<ResolvedJavaType> intrinsificationTrustPredicate;
+    HotSpotJVMCIReflection getReflection() {
+        return reflection;
+    }
 
     /**
      * Gets a predicate that determines if a given type can be considered trusted for the purpose of
@@ -361,47 +571,17 @@
      *            compiler.
      */
     public Predicate<ResolvedJavaType> getIntrinsificationTrustPredicate(Class<?>... compilerLeafClasses) {
-        if (intrinsificationTrustPredicate == null) {
-            intrinsificationTrustPredicate = new Predicate<>() {
-                @Override
-                public boolean test(ResolvedJavaType type) {
-                    if (type instanceof HotSpotResolvedJavaType) {
-                        Class<?> mirror = getMirror(type);
-                        Module module = mirror.getModule();
-                        return getTrustedModules().contains(module);
-                    } else {
-                        return false;
-                    }
+        return new Predicate<ResolvedJavaType>() {
+            @Override
+            public boolean test(ResolvedJavaType type) {
+                if (type instanceof HotSpotResolvedObjectTypeImpl) {
+                    HotSpotResolvedObjectTypeImpl hsType = (HotSpotResolvedObjectTypeImpl) type;
+                    return compilerToVm.isTrustedForIntrinsics(hsType);
+                } else {
+                    return false;
                 }
-
-                private volatile Set<Module> trustedModules;
-
-                private Set<Module> getTrustedModules() {
-                    Set<Module> modules = trustedModules;
-                    if (modules == null) {
-                        modules = new HashSet<>();
-                        for (Class<?> compilerConfiguration : compilerLeafClasses) {
-                            Module compilerConfigurationModule = compilerConfiguration.getModule();
-                            if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
-                                throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
-                                                compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
-                            }
-                            modules.add(compilerConfigurationModule);
-                            for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
-                                for (Module module : compilerConfigurationModule.getLayer().modules()) {
-                                    if (module.getName().equals(require.name())) {
-                                        modules.add(module);
-                                    }
-                                }
-                            }
-                        }
-                        trustedModules = modules;
-                    }
-                    return modules;
-                }
-            };
-        }
-        return intrinsificationTrustPredicate;
+            }
+        };
     }
 
     /**
@@ -412,9 +592,11 @@
      *         does not support mapping {@link ResolvedJavaType} instances to {@link Class}
      *         instances
      */
-    @SuppressWarnings("static-method")
     public Class<?> getMirror(ResolvedJavaType type) {
-        return ((HotSpotResolvedJavaType) type).mirror();
+        if (type instanceof HotSpotResolvedJavaType && reflection instanceof HotSpotJDKReflection) {
+            return ((HotSpotJDKReflection) reflection).getMirror((HotSpotResolvedJavaType) type);
+        }
+        return null;
     }
 
     @Override
@@ -422,7 +604,10 @@
         if (compiler == null) {
             synchronized (this) {
                 if (compiler == null) {
+                    assert !creatingCompiler : "recursive compiler creation";
+                    creatingCompiler = true;
                     compiler = compilerFactory.createCompiler(this);
+                    creatingCompiler = false;
                 }
             }
         }
@@ -444,19 +629,23 @@
      */
     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
         Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
+        return lookupTypeInternal(name, accessingType, resolve);
+    }
+
+    JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
         // If the name represents a primitive type we can short-circuit the lookup.
         if (name.length() == 1) {
             JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
-            return fromClass(kind.toJavaClass());
+            return HotSpotResolvedPrimitiveType.forKind(kind);
         }
 
         // Resolve non-primitive types in the VM.
         HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
         try {
-            final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
+            final HotSpotResolvedJavaType klass = compilerToVm.lookupType(name, hsAccessingType, resolve);
 
             if (klass == null) {
-                assert resolve == false;
+                assert resolve == false : name;
                 return UnresolvedJavaType.create(name);
             }
             return klass;
@@ -480,48 +669,9 @@
         return Collections.unmodifiableMap(backends);
     }
 
-    /**
-     * Called from the VM.
-     */
-    @SuppressWarnings({"unused"})
-    private int adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, int level) {
-        CompilationLevel curLevel;
-        if (level == config.compilationLevelNone) {
-            curLevel = CompilationLevel.None;
-        } else if (level == config.compilationLevelSimple) {
-            curLevel = CompilationLevel.Simple;
-        } else if (level == config.compilationLevelLimitedProfile) {
-            curLevel = CompilationLevel.LimitedProfile;
-        } else if (level == config.compilationLevelFullProfile) {
-            curLevel = CompilationLevel.FullProfile;
-        } else if (level == config.compilationLevelFullOptimization) {
-            curLevel = CompilationLevel.FullOptimization;
-        } else {
-            throw JVMCIError.shouldNotReachHere();
-        }
-
-        switch (hsCompilerFactory.adjustCompilationLevel(declaringClass, name, signature, isOsr, curLevel)) {
-            case None:
-                return config.compilationLevelNone;
-            case Simple:
-                return config.compilationLevelSimple;
-            case LimitedProfile:
-                return config.compilationLevelLimitedProfile;
-            case FullProfile:
-                return config.compilationLevelFullProfile;
-            case FullOptimization:
-                return config.compilationLevelFullOptimization;
-            default:
-                return level;
-        }
-    }
-
-    /**
-     * Called from the VM.
-     */
-    @SuppressWarnings({"unused"})
-    private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
-        CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
+    @VMEntryPoint
+    private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
+        CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, compileState, id));
         assert result != null : "compileMethod must always return something";
         HotSpotCompilationRequestResult hsResult;
         if (result instanceof HotSpotCompilationRequestResult) {
@@ -542,11 +692,13 @@
 
     /**
      * Shuts down the runtime.
-     *
-     * Called from the VM.
      */
-    @SuppressWarnings({"unused"})
+    @VMEntryPoint
     private void shutdown() throws Exception {
+        // Cleaners are normally only processed when a new Cleaner is
+        // instantiated so process all remaining cleaners now.
+        Cleaner.clean();
+
         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
             vmEventListener.notifyShutdown();
         }
@@ -554,10 +706,8 @@
 
     /**
      * Notify on completion of a bootstrap.
-     *
-     * Called from the VM.
      */
-    @SuppressWarnings({"unused"})
+    @VMEntryPoint
     private void bootstrapFinished() throws Exception {
         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
             vmEventListener.notifyBootstrapFinished();
@@ -577,6 +727,41 @@
         }
     }
 
+    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
+    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
+        String line = String.format(format, args);
+        byte[] lineBytes = line.getBytes();
+        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+        vm.flushDebugOutput();
+    }
+
+    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
+        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
+        for (VMField field : fields.values()) {
+            if (!field.isStatic()) {
+                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
+            } else {
+                String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
+                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
+            }
+        }
+        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
+        for (VMFlag flag : flags.values()) {
+            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
+        }
+        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
+        for (Map.Entry<String, Long> e : addresses.entrySet()) {
+            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
+        for (Map.Entry<String, Long> e : constants.entrySet()) {
+            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        for (VMIntrinsicMethod e : store.getIntrinsics()) {
+            printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
+        }
+    }
+
     /**
      * Gets an output stream that writes to HotSpot's {@code tty} stream.
      */
@@ -619,27 +804,26 @@
      *
      * @return the offset in bytes
      */
-    @SuppressWarnings("static-method")
     public int getArrayBaseOffset(JavaKind kind) {
         switch (kind) {
             case Boolean:
-                return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+                return compilerToVm.ARRAY_BOOLEAN_BASE_OFFSET;
             case Byte:
-                return Unsafe.ARRAY_BYTE_BASE_OFFSET;
+                return compilerToVm.ARRAY_BYTE_BASE_OFFSET;
             case Char:
-                return Unsafe.ARRAY_CHAR_BASE_OFFSET;
+                return compilerToVm.ARRAY_CHAR_BASE_OFFSET;
             case Short:
-                return Unsafe.ARRAY_SHORT_BASE_OFFSET;
+                return compilerToVm.ARRAY_SHORT_BASE_OFFSET;
             case Int:
-                return Unsafe.ARRAY_INT_BASE_OFFSET;
+                return compilerToVm.ARRAY_INT_BASE_OFFSET;
             case Long:
-                return Unsafe.ARRAY_LONG_BASE_OFFSET;
+                return compilerToVm.ARRAY_LONG_BASE_OFFSET;
             case Float:
-                return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+                return compilerToVm.ARRAY_FLOAT_BASE_OFFSET;
             case Double:
-                return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+                return compilerToVm.ARRAY_DOUBLE_BASE_OFFSET;
             case Object:
-                return Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+                return compilerToVm.ARRAY_OBJECT_BASE_OFFSET;
             default:
                 throw new JVMCIError("%s", kind);
         }
@@ -651,27 +835,26 @@
      *
      * @return the scale in order to convert the index into a byte offset
      */
-    @SuppressWarnings("static-method")
     public int getArrayIndexScale(JavaKind kind) {
         switch (kind) {
             case Boolean:
-                return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+                return compilerToVm.ARRAY_BOOLEAN_INDEX_SCALE;
             case Byte:
-                return Unsafe.ARRAY_BYTE_INDEX_SCALE;
+                return compilerToVm.ARRAY_BYTE_INDEX_SCALE;
             case Char:
-                return Unsafe.ARRAY_CHAR_INDEX_SCALE;
+                return compilerToVm.ARRAY_CHAR_INDEX_SCALE;
             case Short:
-                return Unsafe.ARRAY_SHORT_INDEX_SCALE;
+                return compilerToVm.ARRAY_SHORT_INDEX_SCALE;
             case Int:
-                return Unsafe.ARRAY_INT_INDEX_SCALE;
+                return compilerToVm.ARRAY_INT_INDEX_SCALE;
             case Long:
-                return Unsafe.ARRAY_LONG_INDEX_SCALE;
+                return compilerToVm.ARRAY_LONG_INDEX_SCALE;
             case Float:
-                return Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+                return compilerToVm.ARRAY_FLOAT_INDEX_SCALE;
             case Double:
-                return Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+                return compilerToVm.ARRAY_DOUBLE_INDEX_SCALE;
             case Object:
-                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+                return compilerToVm.ARRAY_OBJECT_INDEX_SCALE;
             default:
                 throw new JVMCIError("%s", kind);
 
@@ -679,10 +862,10 @@
     }
 
     /**
-     * Links each native method in {@code clazz} to an implementation in the JVMCI SVM library.
+     * Links each native method in {@code clazz} to an implementation in the JVMCI shared library.
      * <p>
      * A use case for this is a JVMCI compiler implementation that offers an API to Java code
-     * executing in HotSpot to exercise functionality (mostly) in the JVMCI SVM library. For
+     * executing in HotSpot to exercise functionality (mostly) in the JVMCI shared library. For
      * example:
      *
      * <pre>
@@ -707,27 +890,82 @@
      * }
      * </pre>
      *
-     * The implementation of the native {@code JCompile.compile0} method would be in the SVM library
-     * that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0} implementation
-     * will be exported as the following JNI-compliant symbol:
+     * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
+     * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
+     * implementation will be exported as the following JNI-compatible symbol:
      *
      * <pre>
      * Java_com_jcompile_JCompile_compile0
      * </pre>
      *
-     * How the JVMCI compiler SVM library is built is outside the scope of this document.
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
      *
-     * @see "https://docs.oracle.com/javase/10/docs/specs/jni/design.html#resolving-native-method-names"
      *
+     * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
+     *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
+     *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
      * @throws NullPointerException if {@code clazz == null}
-     * @throws IllegalArgumentException if the current execution context is SVM or if {@code clazz}
-     *             is {@link Class#isPrimitive()}
-     * @throws UnsatisfiedLinkError if the JVMCI SVM library is not available, a native method in
-     *             {@code clazz} is already linked or the SVM JVMCI library does not contain a
-     *             JNI-compliant symbol for a native method in {@code clazz}
+     * @throws IllegalArgumentException if the current execution context is the JVMCI shared library
+     *             or if {@code clazz} is {@link Class#isPrimitive()}
+     * @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
+     *             {@code clazz} is already linked or the JVMCI shared library does not contain a
+     *             JNI-compatible symbol for a native method in {@code clazz}
      */
-    @SuppressWarnings({"static-method", "unused"})
-    public void registerNativeMethods(Class<?> clazz) {
-        throw new UnsatisfiedLinkError("SVM library is not available");
+    public long[] registerNativeMethods(Class<?> clazz) {
+        return compilerToVm.registerNativeMethods(clazz);
+    }
+
+    /**
+     * Creates or retrieves an object in the peer runtime that mirrors {@code obj}. The types whose
+     * objects can be translated are:
+     * <ul>
+     * <li>{@link HotSpotResolvedJavaMethodImpl},</li>
+     * <li>{@link HotSpotResolvedObjectTypeImpl},</li>
+     * <li>{@link HotSpotResolvedPrimitiveType},</li>
+     * <li>{@link IndirectHotSpotObjectConstantImpl},</li>
+     * <li>{@link DirectHotSpotObjectConstantImpl} and</li>
+     * <li>{@link HotSpotNmethod}</li>
+     * </ul>
+     *
+     * This mechanism can be used to pass and return values between the HotSpot and JVMCI shared
+     * library runtimes. In the receiving runtime, the value can be converted back to an object with
+     * {@link #unhand(Class, long)}.
+     *
+     * @param obj an object for which an equivalent instance in the peer runtime is requested
+     * @return a JNI global reference to the mirror of {@code obj} in the peer runtime
+     * @throws IllegalArgumentException if {@code obj} is not of a translatable type
+     *
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
+     */
+    public long translate(Object obj) {
+        return compilerToVm.translate(obj);
+    }
+
+    /**
+     * Dereferences and returns the object referred to by the JNI global reference {@code handle}.
+     * The global reference is deleted prior to returning. Any further use of {@code handle} is
+     * invalid.
+     *
+     * @param handle a JNI global reference to an object in the current runtime
+     * @return the object referred to by {@code handle}
+     * @throws ClassCastException if the returned object cannot be case to {@code type}
+     *
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
+     *
+     */
+    public <T> T unhand(Class<T> type, long handle) {
+        return type.cast(compilerToVm.unhand(handle));
+    }
+
+    /**
+     * Informs HotSpot that no method whose module is in {@code modules} is to be compiled
+     * with {@link #compileMethod}.
+     *
+     * @param modules the set of modules containing JVMCI compiler classes
+     */
+    public void excludeFromJVMCICompilation(Module...modules) {
+        this.excludeFromJVMCICompilation = modules.clone();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIUnsupportedOperationError.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.services.Services;
+
+/**
+ * Indicates a path in HotSpot JVMCI related code that is unsupported in the current execution
+ * environment. For example, certain operations are not supported by JVMCI code running in an ahead
+ * of time compiled {@linkplain Services#IS_IN_NATIVE_IMAGE native image}. This usually reflects
+ * functionality only needed in non-native image execution that would require a more complex
+ * implementation to support in a native image.
+ *
+ * An example of such functionality is {@link ResolvedJavaType#isLocal()}. This can be conveniently
+ * implemented when JVMCI is running on the HotSpot heap as we can obtain the {@link Class} mirror
+ * for the {@link ResolvedJavaType} and call {@link Class#isLocalClass()}. In a native image, there
+ * is no {@link Class} mirror available in the native image heap so implementing this would involve
+ * a call into VM native code that in turn would make an upcall into Java code executing on the
+ * HotSpot heap. We have opted to defer implementing functionality such as this until there's a
+ * demonstrated need for it.
+ */
+public class HotSpotJVMCIUnsupportedOperationError extends Error {
+
+    public HotSpotJVMCIUnsupportedOperationError(String reason) {
+        super(reason);
+    }
+
+    public HotSpotJVMCIUnsupportedOperationError(String reason, Throwable cause) {
+        super(reason, cause);
+    }
+
+    private static final long serialVersionUID = 7782431672678016392L;
+
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Fri May 03 14:59:32 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
@@ -22,19 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.reflect.Array;
-
-import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MemoryAccessProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PrimitiveConstant;
-import jdk.vm.ci.meta.ResolvedJavaField;
-import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * HotSpot implementation of {@link MemoryAccessProvider}.
@@ -55,89 +50,34 @@
      * @return {@code null} if {@code base} does not box an object otherwise the object boxed in
      *         {@code base}
      */
-    private Object asObject(Constant base, JavaKind kind, long displacement) {
+    private static HotSpotObjectConstantImpl asObject(Constant base, JavaKind kind, long displacement) {
         if (base instanceof HotSpotObjectConstantImpl) {
             HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
             HotSpotResolvedObjectType type = constant.getType();
-            Object object = constant.object();
-            checkRead(kind, displacement, type, object, runtime.getHostJVMCIBackend().getMetaAccess());
-            return object;
+            runtime().reflection.checkRead(constant, kind, displacement, type);
+            return constant;
         }
         return null;
     }
 
-    /**
-     * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
-     * as initialization is idempotent.
-     */
-    private long oopSizeOffset;
-
-    private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
-        MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
-        ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
-        for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
-            if (f.getName().equals("oop_size")) {
-                int offset = ((HotSpotResolvedJavaField) f).getOffset();
-                assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
-                return offset;
+    private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
+        if (base instanceof HotSpotMetaspaceConstant) {
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+                if (displacement == runtime.getConfig().javaMirrorOffset) {
+                    // Klass::_java_mirror is valid for all Klass* values
+                    return true;
+                }
+            } else {
+                throw new IllegalArgumentException(String.valueOf(metaspaceObject));
             }
         }
-        throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
-    }
-
-    private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object, MetaAccessProvider metaAccess) {
-        if (type.isArray()) {
-            ResolvedJavaType componentType = type.getComponentType();
-            JavaKind componentKind = componentType.getJavaKind();
-            final int headerSize = metaAccess.getArrayBaseOffset(componentKind);
-            int sizeOfElement = metaAccess.getArrayIndexScale(componentKind);
-            int length = Array.getLength(object);
-            long arrayEnd = headerSize + (sizeOfElement * length);
-            boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
-            if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
-                int index = (int) ((displacement - headerSize) / sizeOfElement);
-                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
-                                " at offset " + displacement + " (index ~ " + index + ") in " +
-                                type.toJavaName() + " object of length " + length);
-            }
-        } else if (kind != JavaKind.Object) {
-            long size;
-            if (object instanceof Class) {
-                if (oopSizeOffset == 0) {
-                    oopSizeOffset = computeOopSizeOffset(runtime);
-                }
-                int wordSize = runtime.getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
-                size = UNSAFE.getInt(object, oopSizeOffset) * wordSize;
-            } else {
-                size = Math.abs(type.instanceSize());
-            }
-            int bytesToRead = kind.getByteCount();
-            if (displacement + bytesToRead > size || displacement < 0) {
-                throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
-                                type.toJavaName() + " object of size " + size);
-            }
-        } else {
-            ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
-            if (field == null && object instanceof Class) {
-                // Read of a static field
-                HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object);
-                field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
-            }
-            if (field == null) {
-                throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
-                                " at offset " + displacement + " in " + type.toJavaName() + " object");
-            }
-            if (field.getJavaKind() != JavaKind.Object) {
-                throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
-                                " at offset " + displacement + " in " + type.toJavaName() + " object");
-            }
-        }
-        return true;
+        return false;
     }
 
     private static long asRawPointer(Constant base) {
         if (base instanceof HotSpotMetaspaceConstantImpl) {
-            MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             return meta.getMetaspacePointer();
         } else if (base instanceof PrimitiveConstant) {
             PrimitiveConstant prim = (PrimitiveConstant) base;
@@ -148,18 +88,18 @@
         throw new IllegalArgumentException(String.valueOf(base));
     }
 
-    private long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
-        Object base = asObject(baseConstant, kind, displacement);
+    private static long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
+        HotSpotObjectConstantImpl base = asObject(baseConstant, kind, displacement);
         if (base != null) {
             switch (bits) {
                 case Byte.SIZE:
-                    return UNSAFE.getByte(base, displacement);
+                    return runtime().reflection.getByte(base, displacement);
                 case Short.SIZE:
-                    return UNSAFE.getShort(base, displacement);
+                    return runtime().reflection.getShort(base, displacement);
                 case Integer.SIZE:
-                    return UNSAFE.getInt(base, displacement);
+                    return runtime().reflection.getInt(base, displacement);
                 case Long.SIZE:
-                    return UNSAFE.getLong(base, displacement);
+                    return runtime().reflection.getLong(base, displacement);
                 default:
                     throw new IllegalArgumentException(String.valueOf(bits));
             }
@@ -180,63 +120,33 @@
         }
     }
 
-    private boolean verifyReadRawObject(Object expected, Constant base, long displacement) {
+    private boolean verifyReadRawObject(JavaConstant expected, Constant base, long displacement) {
         if (base instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
-                if (displacement == runtime.getConfig().classMirrorHandleOffset) {
-                    assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
+                if (displacement == runtime.getConfig().javaMirrorOffset) {
+                    HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject;
+                    assert expected.equals(type.getJavaMirror());
                 }
             }
         }
         return true;
     }
 
-    private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
+    private JavaConstant readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
         long displacement = initialDisplacement;
-        Object ret;
-        Object base = asObject(baseConstant, JavaKind.Object, displacement);
+        JavaConstant ret;
+        HotSpotObjectConstantImpl base = asObject(baseConstant, JavaKind.Object, displacement);
         if (base == null) {
             assert !compressed;
             displacement += asRawPointer(baseConstant);
-            ret = UNSAFE.getUncompressedObject(displacement);
+            ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
             assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
         } else {
             assert runtime.getConfig().useCompressedOops == compressed;
-            ret = UNSAFE.getReference(base, displacement);
+            ret = runtime.getCompilerToVM().getObject(base, displacement);
         }
-        return ret;
-    }
-
-    JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
-        assert obj != null;
-        assert !field.isStatic() || obj instanceof Class;
-        long displacement = field.getOffset();
-        assert checkRead(field.getJavaKind(), displacement, (HotSpotResolvedObjectType) runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(obj.getClass()), obj,
-                        runtime.getHostJVMCIBackend().getMetaAccess());
-        JavaKind kind = field.getJavaKind();
-        switch (kind) {
-            case Boolean:
-                return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
-            case Byte:
-                return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
-            case Char:
-                return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
-            case Short:
-                return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
-            case Int:
-                return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
-            case Long:
-                return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
-            case Float:
-                return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
-            case Double:
-                return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
-            case Object:
-                return HotSpotObjectConstantImpl.forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
-            default:
-                throw new IllegalArgumentException("Unsupported kind: " + kind);
-        }
+        return ret == null ? JavaConstant.NULL_POINTER : ret;
     }
 
     @Override
@@ -271,34 +181,35 @@
     @Override
     public JavaConstant readObjectConstant(Constant base, long displacement) {
         if (base instanceof HotSpotObjectConstantImpl) {
-            Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
-            return HotSpotObjectConstantImpl.forObject(o);
+            return readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
+        }
+        if (!isValidObjectFieldDisplacement(base, displacement)) {
+            return null;
         }
-        if (base instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
-            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
-                 if (displacement == runtime.getConfig().classMirrorHandleOffset) {
-                    // Klass::_java_mirror is valid for all Klass* values
-                    return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror());
-                 }
-             } else {
-                 throw new IllegalArgumentException(String.valueOf(metaspaceObject));
-             }
+        if (base instanceof HotSpotMetaspaceConstant &&
+            displacement == runtime.getConfig().javaMirrorOffset) {
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            return ((HotSpotResolvedObjectTypeImpl) metaspaceObject).getJavaMirror();
         }
-        return null;
+        return readRawObject(base, displacement, false);
     }
 
     @Override
     public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
-        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
+        JavaConstant res = readRawObject(base, displacement, true);
+        return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress();
     }
 
     private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
         assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
-        Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
-        return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
+        if (base instanceof HotSpotMetaspaceConstantImpl) {
+            return runtime.getCompilerToVM().getResolvedJavaType((HotSpotResolvedObjectTypeImpl) ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType(), displacement, compressed);
+        } else {
+            return runtime.getCompilerToVM().getResolvedJavaType(((HotSpotObjectConstantImpl) base), displacement, compressed);
+        }
     }
 
+
     @Override
     public Constant readKlassPointerConstant(Constant base, long displacement) {
         HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
@@ -320,8 +231,7 @@
     @Override
     public Constant readMethodPointerConstant(Constant base, long displacement) {
         assert (base instanceof HotSpotObjectConstantImpl);
-        Object baseObject = ((HotSpotObjectConstantImpl) base).object();
-        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
+        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) base, displacement);
         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, 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
@@ -22,10 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
-import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-
-import java.lang.reflect.Array;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -43,6 +39,8 @@
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.Signature;
 import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.NoSpeculationReason;
+import jdk.vm.ci.meta.SpeculationLog.Speculation;
 
 // JaCoCo Exclude
 
@@ -87,20 +85,19 @@
     public ResolvedJavaField lookupJavaField(Field reflectionField) {
         Class<?> fieldHolder = reflectionField.getDeclaringClass();
 
-        HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder);
+        HotSpotResolvedJavaType holder = runtime.fromClass(fieldHolder);
+        assert holder != null : fieldHolder;
+        ResolvedJavaField[] fields;
         if (Modifier.isStatic(reflectionField.getModifiers())) {
-            final long offset = UNSAFE.staticFieldOffset(reflectionField);
-            for (ResolvedJavaField field : holder.getStaticFields()) {
-                if (offset == ((HotSpotResolvedJavaField) field).getOffset()) {
-                    return field;
-                }
-            }
+            fields = holder.getStaticFields();
         } else {
-            final long offset = UNSAFE.objectFieldOffset(reflectionField);
-            for (ResolvedJavaField field : holder.getInstanceFields(false)) {
-                if (offset == ((HotSpotResolvedJavaField) field).getOffset()) {
-                    return field;
-                }
+            fields = holder.getInstanceFields(false);
+        }
+        ResolvedJavaType fieldType = lookupJavaType(reflectionField.getType());
+        for (ResolvedJavaField field : fields) {
+            if (reflectionField.getName().equals(field.getName()) && field.getType().equals(fieldType)) {
+                assert Modifier.isStatic(reflectionField.getModifiers()) == field.isStatic();
+                return field;
             }
         }
 
@@ -147,19 +144,21 @@
     }
 
     @Override
-    public JavaConstant encodeSpeculation(SpeculationLog.Speculation speculation) {
-        if (speculation.getReason() instanceof SpeculationLog.NoSpeculationReason) {
+    public JavaConstant encodeSpeculation(Speculation speculation) {
+        if (speculation.getReason() instanceof NoSpeculationReason) {
             return JavaConstant.LONG_0;
         }
         return ((HotSpotSpeculationLog.HotSpotSpeculation) speculation).getEncoding();
     }
 
     @Override
-    public SpeculationLog.Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) {
+    public Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) {
         if (constant.equals(JavaConstant.LONG_0)) {
             return SpeculationLog.NO_SPECULATION;
         }
-        assert speculationLog != null : "Must have a speculation log";
+        if (speculationLog == null) {
+            throw new IllegalArgumentException("A speculation log is required to decode the speculation denoted by " + constant);
+        }
         return speculationLog.lookupSpeculation(constant);
     }
 
@@ -303,11 +302,11 @@
                 return 0;
             } else {
                 if (lookupJavaType.isArray()) {
-                    int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object());
+                    int length = runtime.getHostJVMCIBackend().getConstantReflection().readArrayLength(constant);
                     ResolvedJavaType elementType = lookupJavaType.getComponentType();
                     JavaKind elementKind = elementType.getJavaKind();
-                    final int headerSize = getArrayBaseOffset(elementKind);
-                    int sizeOfElement = getArrayIndexScale(elementKind);
+                    final int headerSize = runtime.getArrayBaseOffset(elementKind);
+                    int sizeOfElement = runtime.getArrayIndexScale(elementKind);
                     int log2ElementSize = CodeUtil.log2(sizeOfElement);
                     return computeArrayAllocationSize(length, headerSize, log2ElementSize);
                 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, 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
@@ -29,18 +29,18 @@
 
 final class HotSpotMetaspaceConstantImpl implements HotSpotMetaspaceConstant, VMConstant {
 
-    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceObject metaspaceObject, boolean compressed) {
         return new HotSpotMetaspaceConstantImpl(metaspaceObject, compressed);
     }
 
-    static MetaspaceWrapperObject getMetaspaceObject(Constant constant) {
+    static MetaspaceObject getMetaspaceObject(Constant constant) {
         return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject;
     }
 
-    private final MetaspaceWrapperObject metaspaceObject;
+    private final MetaspaceObject metaspaceObject;
     private final boolean compressed;
 
-    private HotSpotMetaspaceConstantImpl(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+    private HotSpotMetaspaceConstantImpl(MetaspaceObject metaspaceObject, boolean compressed) {
         this.metaspaceObject = metaspaceObject;
         this.compressed = compressed;
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, 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
@@ -78,8 +78,4 @@
         String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString();
         formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width));
     }
-
-    public JavaMethod asJavaMethod() {
-        return this;
-    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 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
@@ -30,6 +30,7 @@
 
 import java.util.Arrays;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.JavaMethodProfile;
@@ -45,26 +46,139 @@
  */
 final class HotSpotMethodData {
 
-    static final HotSpotVMConfig config = config();
-    static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.FALSE);
-    static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.UNKNOWN);
+    /**
+     * VM state that can be reset when building an AOT image.
+     */
+    static final class VMState {
+        final HotSpotVMConfig config = config();
+        final HotSpotMethodDataAccessor noDataNoExceptionAccessor = new NoMethodData(this, config.dataLayoutNoTag, TriState.FALSE);
+        final HotSpotMethodDataAccessor noDataExceptionPossiblyNotRecordedAccessor = new NoMethodData(this, config.dataLayoutNoTag, TriState.UNKNOWN);
+        final int noDataSize = cellIndexToOffset(0);
+        final int bitDataSize = cellIndexToOffset(0);
+        final int bitDataNullSeenFlag = 1 << config.bitDataNullSeenFlag;
+        final int counterDataSize = cellIndexToOffset(1);
+        final int counterDataCountOffset = cellIndexToOffset(config.methodDataCountOffset);
+        final int jumpDataSize = cellIndexToOffset(2);
+        final int takenCountOffset = cellIndexToOffset(config.jumpDataTakenOffset);
+        final int takenDisplacementOffset = cellIndexToOffset(config.jumpDataDisplacementOffset);
+        final int typeDataRowSize = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
+
+        final int nonprofiledCountOffset = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+        final int typeDataFirstTypeOffset = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+        final int typeDataFirstTypeCountOffset = cellIndexToOffset(config.receiverTypeDataCount0Offset);
+
+        final int typeCheckDataSize = cellIndexToOffset(2) + typeDataRowSize * config.typeProfileWidth;
+        final int virtualCallDataSize = cellIndexToOffset(2) + typeDataRowSize * (config.typeProfileWidth + config.methodProfileWidth);
+        final int virtualCallDataFirstMethodOffset = typeDataFirstTypeOffset + typeDataRowSize * config.typeProfileWidth;
+        final int virtualCallDataFirstMethodCountOffset = typeDataFirstTypeCountOffset + typeDataRowSize * config.typeProfileWidth;
+
+        final int retDataRowSize = cellsToBytes(3);
+        final int retDataSize = cellIndexToOffset(1) + retDataRowSize * config.bciProfileWidth;
+
+        final int branchDataSize = cellIndexToOffset(3);
+        final int notTakenCountOffset = cellIndexToOffset(config.branchDataNotTakenOffset);
+
+        final int arrayDataLengthOffset = cellIndexToOffset(config.arrayDataArrayLenOffset);
+        final int arrayDataStartOffset = cellIndexToOffset(config.arrayDataArrayStartOffset);
+
+        final int multiBranchDataSize = cellIndexToOffset(1);
+        final int multiBranchDataRowSizeInCells = config.multiBranchDataPerCaseCellCount;
+        final int multiBranchDataRowSize = cellsToBytes(multiBranchDataRowSizeInCells);
+        final int multiBranchDataFirstCountOffset = arrayDataStartOffset + cellsToBytes(0);
+        final int multiBranchDataFirstDisplacementOffset = arrayDataStartOffset + cellsToBytes(1);
+
+        final int argInfoDataSize = cellIndexToOffset(1);
+
+        // sorted by tag
+        // @formatter:off
+        final HotSpotMethodDataAccessor[] profileDataAccessors = {
+            null,
+            new BitData(this, config.dataLayoutBitDataTag),
+            new CounterData(this, config.dataLayoutCounterDataTag),
+            new JumpData(this, config.dataLayoutJumpDataTag),
+            new ReceiverTypeData(this, config.dataLayoutReceiverTypeDataTag),
+            new VirtualCallData(this, config.dataLayoutVirtualCallDataTag),
+            new RetData(this, config.dataLayoutRetDataTag),
+            new BranchData(this, config.dataLayoutBranchDataTag),
+            new MultiBranchData(this, config.dataLayoutMultiBranchDataTag),
+            new ArgInfoData(this, config.dataLayoutArgInfoDataTag),
+            new UnknownProfileData(this, config.dataLayoutCallTypeDataTag),
+            new VirtualCallTypeData(this, config.dataLayoutVirtualCallTypeDataTag),
+            new UnknownProfileData(this, config.dataLayoutParametersTypeDataTag),
+            new UnknownProfileData(this, config.dataLayoutSpeculativeTrapDataTag),
+        };
+        // @formatter:on
+
+        private boolean checkAccessorTags() {
+            int expectedTag = 0;
+            for (HotSpotMethodDataAccessor accessor : profileDataAccessors) {
+                if (expectedTag == 0) {
+                    assert accessor == null;
+                } else {
+                    assert accessor.tag == expectedTag : expectedTag + " != " + accessor.tag + " " + accessor;
+                }
+                expectedTag++;
+            }
+            return true;
+        }
+
+        private VMState() {
+            assert checkAccessorTags();
+        }
+
+        private static int truncateLongToInt(long value) {
+            return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
+        }
+
+        private int computeFullOffset(int position, int offsetInBytes) {
+            return config.methodDataOopDataOffset + position + offsetInBytes;
+        }
+
+        private int cellIndexToOffset(int cells) {
+            return config.dataLayoutHeaderSize + cellsToBytes(cells);
+        }
+
+        private int cellsToBytes(int cells) {
+            return cells * config.dataLayoutCellSize;
+        }
+
+        /**
+         * Singleton instance lazily initialized via double-checked locking.
+         */
+        @NativeImageReinitialize private static volatile VMState instance;
+
+        static VMState instance() {
+            VMState result = instance;
+            if (result == null) {
+                synchronized (VMState.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new VMState();
+                    }
+                }
+            }
+            return result;
+        }
+    }
 
     /**
      * Reference to the C++ MethodData object.
      */
     final long metaspaceMethodData;
     private final HotSpotResolvedJavaMethodImpl method;
+    private final VMState state;
 
     HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
         this.metaspaceMethodData = metaspaceMethodData;
         this.method = method;
+        this.state = VMState.instance();
     }
 
     /**
      * @return value of the MethodData::_data_size field
      */
     private int normalDataSize() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataDataSize);
     }
 
     /**
@@ -74,8 +188,8 @@
      * @return size of extra data records
      */
     private int extraDataSize() {
-        final int extraDataBase = config.methodDataOopDataOffset + normalDataSize();
-        final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + config.methodDataSize);
+        final int extraDataBase = state.config.methodDataOopDataOffset + normalDataSize();
+        final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + state.config.methodDataSize);
         return extraDataLimit - extraDataBase;
     }
 
@@ -98,25 +212,25 @@
     public int getDeoptimizationCount(DeoptimizationReason reason) {
         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
         int reasonIndex = metaAccess.convertDeoptReason(reason);
-        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
+        return UNSAFE.getByte(metaspaceMethodData + state.config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
     }
 
     public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
         int reasonIndex = metaAccess.convertDeoptReason(reason);
-        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
+        return UNSAFE.getByte(metaspaceMethodData + state.config.methodDataOopTrapHistoryOffset + state.config.deoptReasonOSROffset + reasonIndex) & 0xFF;
     }
 
     public int getDecompileCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDecompiles);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataDecompiles);
     }
 
     public int getOverflowRecompileCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowRecompiles);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataOverflowRecompiles);
     }
 
     public int getOverflowTrapCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowTraps);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataOverflowTraps);
     }
 
     public HotSpotMethodDataAccessor getNormalData(int position) {
@@ -140,27 +254,27 @@
 
     public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
         if (exceptionPossiblyNotRecorded) {
-            return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
+            return VMState.instance().noDataExceptionPossiblyNotRecordedAccessor;
         } else {
-            return NO_DATA_NO_EXCEPTION_ACCESSOR;
+            return VMState.instance().noDataNoExceptionAccessor;
         }
     }
 
     private HotSpotMethodDataAccessor getData(int position) {
         assert position >= 0 : "out of bounds";
-        final int tag = HotSpotMethodDataAccessor.readTag(config, this, position);
-        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag];
+        final int tag = HotSpotMethodDataAccessor.readTag(state.config, this, position);
+        HotSpotMethodDataAccessor accessor = state.profileDataAccessors[tag];
         assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
         return accessor;
     }
 
     int readUnsignedByte(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
     }
 
     int readUnsignedShort(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
     }
 
@@ -169,13 +283,13 @@
      * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
      */
     private long readUnsignedInt(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
     }
 
     private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
         long value = readUnsignedInt(position, offsetInBytes);
-        return truncateLongToInt(value);
+        return VMState.truncateLongToInt(value);
     }
 
     /**
@@ -183,34 +297,18 @@
      * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
      */
     private int readInt(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
     }
 
     private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
     }
 
     private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
-        return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
-    }
-
-    private static int truncateLongToInt(long value) {
-        return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
-    }
-
-    private static int computeFullOffset(int position, int offsetInBytes) {
-        return config.methodDataOopDataOffset + position + offsetInBytes;
-    }
-
-    private static int cellIndexToOffset(int cells) {
-        return config.dataLayoutHeaderSize + cellsToBytes(cells);
-    }
-
-    private static int cellsToBytes(int cells) {
-        return cells * config.dataLayoutCellSize;
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
+        return compilerToVM().getResolvedJavaType(metaspaceMethodData + fullOffsetInBytes, false);
     }
 
     /**
@@ -263,14 +361,12 @@
         return sb.toString();
     }
 
-    static final int NO_DATA_SIZE = cellIndexToOffset(0);
-
     static class NoMethodData extends HotSpotMethodDataAccessor {
 
         private final TriState exceptionSeen;
 
-        protected NoMethodData(HotSpotVMConfig config, int tag, TriState exceptionSeen) {
-            super(config, tag, NO_DATA_SIZE);
+        protected NoMethodData(VMState state, int tag, TriState exceptionSeen) {
+            super(state, tag, state.noDataSize);
             this.exceptionSeen = exceptionSeen;
         }
 
@@ -290,22 +386,19 @@
         }
     }
 
-    static final int BIT_DATA_SIZE = cellIndexToOffset(0);
-    static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
-
     static class BitData extends HotSpotMethodDataAccessor {
 
-        private BitData(HotSpotVMConfig config, int tag) {
-            super(config, tag, BIT_DATA_SIZE);
+        private BitData(VMState state, int tag) {
+            super(state, tag, state.bitDataSize);
         }
 
-        protected BitData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected BitData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
         public TriState getNullSeen(HotSpotMethodData data, int position) {
-            return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
+            return TriState.get((getFlags(data, position) & state.bitDataNullSeenFlag) != 0);
         }
 
         @Override
@@ -314,17 +407,14 @@
         }
     }
 
-    static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
-    static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
-
     static class CounterData extends BitData {
 
-        CounterData(HotSpotVMConfig config, int tag) {
-            super(config, tag, COUNTER_DATA_SIZE);
+        CounterData(VMState state, int tag) {
+            super(state, tag, state.counterDataSize);
         }
 
-        protected CounterData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected CounterData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -333,7 +423,7 @@
         }
 
         protected int getCounterValue(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.counterDataCountOffset);
         }
 
         @Override
@@ -342,18 +432,14 @@
         }
     }
 
-    static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
-    static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
-    static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
-
     static class JumpData extends HotSpotMethodDataAccessor {
 
-        JumpData(HotSpotVMConfig config, int tag) {
-            super(config, tag, JUMP_DATA_SIZE);
+        JumpData(VMState state, int tag) {
+            super(state, tag, state.jumpDataSize);
         }
 
-        protected JumpData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected JumpData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -363,11 +449,11 @@
 
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.takenCountOffset);
         }
 
         public int getTakenDisplacement(HotSpotMethodData data, int position) {
-            return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET);
+            return data.readInt(position, state.takenDisplacementOffset);
         }
 
         @Override
@@ -390,16 +476,10 @@
         }
     }
 
-    static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
-
-    static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
-    static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
-    static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
-
     abstract static class AbstractTypeData extends CounterData {
 
-        protected AbstractTypeData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected AbstractTypeData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -446,7 +526,7 @@
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
         public int getNonprofiledCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.nonprofiledCountOffset);
         }
 
         private JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
@@ -470,12 +550,12 @@
             return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
         }
 
-        private static int getTypeOffset(int row) {
-            return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getTypeOffset(int row) {
+            return state.typeDataFirstTypeOffset + row * state.typeDataRowSize;
         }
 
-        protected static int getTypeCountOffset(int row) {
-            return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        protected int getTypeCountOffset(int row) {
+            return state.typeDataFirstTypeCountOffset + row * state.typeDataRowSize;
         }
 
         @Override
@@ -493,16 +573,14 @@
         }
     }
 
-    static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-
     static class ReceiverTypeData extends AbstractTypeData {
 
-        ReceiverTypeData(HotSpotVMConfig config, int tag) {
-            super(config, tag, TYPE_CHECK_DATA_SIZE);
+        ReceiverTypeData(VMState state, int tag) {
+            super(state, tag, state.typeCheckDataSize);
         }
 
-        protected ReceiverTypeData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected ReceiverTypeData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -516,18 +594,14 @@
         }
     }
 
-    static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
-    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-
     static class VirtualCallData extends ReceiverTypeData {
 
-        VirtualCallData(HotSpotVMConfig config, int tag) {
-            super(config, tag, VIRTUAL_CALL_DATA_SIZE);
+        VirtualCallData(VMState state, int tag) {
+            super(state, tag, state.virtualCallDataSize);
         }
 
-        protected VirtualCallData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected VirtualCallData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -540,7 +614,7 @@
             }
 
             total += getCounterValue(data, position);
-            return truncateLongToInt(total);
+            return VMState.truncateLongToInt(total);
         }
 
         @Override
@@ -548,8 +622,8 @@
             return getCounterValue(data, position);
         }
 
-        private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+        private long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, state.nonprofiledCountOffset);
         }
 
         @Override
@@ -610,12 +684,12 @@
             return new JavaMethodProfile(notRecordedMethodProbability, pmethods);
         }
 
-        private static int getMethodOffset(int row) {
-            return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getMethodOffset(int row) {
+            return state.virtualCallDataFirstMethodOffset + row * state.typeDataRowSize;
         }
 
-        private static int getMethodCountOffset(int row) {
-            return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getMethodCountOffset(int row) {
+            return state.virtualCallDataFirstMethodCountOffset + row * state.typeDataRowSize;
         }
 
         @Override
@@ -632,8 +706,8 @@
 
     static class VirtualCallTypeData extends VirtualCallData {
 
-        VirtualCallTypeData(HotSpotVMConfig config, int tag) {
-            super(config, tag, 0);
+        VirtualCallTypeData(VMState state, int tag) {
+            super(state, tag, 0);
         }
 
         @Override
@@ -643,29 +717,23 @@
         }
     }
 
-    static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
-    static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
-
     static class RetData extends CounterData {
 
-        RetData(HotSpotVMConfig config, int tag) {
-            super(config, tag, RET_DATA_SIZE);
+        RetData(VMState state, int tag) {
+            super(state, tag, state.retDataSize);
         }
     }
 
-    static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
-    static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
-
     static class BranchData extends JumpData {
 
-        BranchData(HotSpotVMConfig config, int tag) {
-            super(config, tag, BRANCH_DATA_SIZE);
+        BranchData(VMState state, int tag) {
+            super(state, tag, state.branchDataSize);
         }
 
         @Override
         public double getBranchTakenProbability(HotSpotMethodData data, int position) {
-            long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
-            long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+            long takenCount = data.readUnsignedInt(position, state.takenCountOffset);
+            long notTakenCount = data.readUnsignedInt(position, state.notTakenCountOffset);
             long total = takenCount + notTakenCount;
 
             return total <= 0 ? -1 : takenCount / (double) total;
@@ -673,35 +741,32 @@
 
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
-            long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
-            return truncateLongToInt(count);
+            long count = data.readUnsignedInt(position, state.takenCountOffset) + data.readUnsignedInt(position, state.notTakenCountOffset);
+            return VMState.truncateLongToInt(count);
         }
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
-            long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
+            long taken = data.readUnsignedInt(pos, state.takenCountOffset);
+            long notTaken = data.readUnsignedInt(pos, state.notTakenCountOffset);
             double takenProbability = getBranchTakenProbability(data, pos);
             return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
         }
     }
 
-    static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
-    static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
-
     static class ArrayData extends HotSpotMethodDataAccessor {
 
-        ArrayData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        ArrayData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
         protected int getDynamicSize(HotSpotMethodData data, int position) {
-            return cellsToBytes(getLength(data, position));
+            return state.cellsToBytes(getLength(data, position));
         }
 
-        protected static int getLength(HotSpotMethodData data, int position) {
-            return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
+        protected int getLength(HotSpotMethodData data, int position) {
+            return data.readInt(position, state.arrayDataLengthOffset);
         }
 
         @Override
@@ -710,25 +775,19 @@
         }
     }
 
-    static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
-    static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
-    static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
-    static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
-    static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
-
     static class MultiBranchData extends ArrayData {
 
-        MultiBranchData(HotSpotVMConfig config, int tag) {
-            super(config, tag, MULTI_BRANCH_DATA_SIZE);
+        MultiBranchData(VMState state, int tag) {
+            super(state, tag, state.multiBranchDataSize);
         }
 
         @Override
         public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
             int arrayLength = getLength(data, position);
             assert arrayLength > 0 : "switch must have at least the default case";
-            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+            assert arrayLength % state.multiBranchDataRowSizeInCells == 0 : "array must have full rows";
 
-            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int length = arrayLength / state.multiBranchDataRowSizeInCells;
             long totalCount = 0;
             double[] result = new double[length];
 
@@ -753,7 +812,7 @@
             }
         }
 
-        private static long readCount(HotSpotMethodData data, int position, int i) {
+        private long readCount(HotSpotMethodData data, int position, int i) {
             int offset;
             long count;
             offset = getCountOffset(i);
@@ -765,29 +824,29 @@
         public int getExecutionCount(HotSpotMethodData data, int position) {
             int arrayLength = getLength(data, position);
             assert arrayLength > 0 : "switch must have at least the default case";
-            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+            assert arrayLength % state.multiBranchDataRowSizeInCells == 0 : "array must have full rows";
 
-            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int length = arrayLength / state.multiBranchDataRowSizeInCells;
             long totalCount = 0;
             for (int i = 0; i < length; i++) {
                 int offset = getCountOffset(i);
                 totalCount += data.readUnsignedInt(position, offset);
             }
 
-            return truncateLongToInt(totalCount);
+            return VMState.truncateLongToInt(totalCount);
         }
 
-        private static int getCountOffset(int index) {
-            return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        private int getCountOffset(int index) {
+            return state.multiBranchDataFirstCountOffset + index * state.multiBranchDataRowSize;
         }
 
-        private static int getDisplacementOffset(int index) {
-            return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        private int getDisplacementOffset(int index) {
+            return state.multiBranchDataFirstDisplacementOffset + index * state.multiBranchDataRowSize;
         }
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int entries = getLength(data, pos) / state.multiBranchDataRowSizeInCells;
             sb.append(format("entries(%d)", entries));
             for (int i = 0; i < entries; i++) {
                 sb.append(format("%n  %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
@@ -796,18 +855,16 @@
         }
     }
 
-    static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
-
     static class ArgInfoData extends ArrayData {
 
-        ArgInfoData(HotSpotVMConfig config, int tag) {
-            super(config, tag, ARG_INFO_DATA_SIZE);
+        ArgInfoData(VMState state, int tag) {
+            super(state, tag, state.argInfoDataSize);
         }
     }
 
     static class UnknownProfileData extends HotSpotMethodDataAccessor {
-        UnknownProfileData(HotSpotVMConfig config, int tag) {
-            super(config, tag, 0);
+        UnknownProfileData(VMState state, int tag) {
+            super(state, tag, 0);
         }
 
         @Override
@@ -824,47 +881,10 @@
     }
 
     public void setCompiledIRSize(int size) {
-        UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
+        UNSAFE.putInt(metaspaceMethodData + state.config.methodDataIRSizeOffset, size);
     }
 
     public int getCompiledIRSize() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataIRSizeOffset);
     }
-
-    // sorted by tag
-    // @formatter:off
-    static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
-        null,
-        new BitData(config, config.dataLayoutBitDataTag),
-        new CounterData(config, config.dataLayoutCounterDataTag),
-        new JumpData(config, config.dataLayoutJumpDataTag),
-        new ReceiverTypeData(config, config.dataLayoutReceiverTypeDataTag),
-        new VirtualCallData(config, config.dataLayoutVirtualCallDataTag),
-        new RetData(config, config.dataLayoutRetDataTag),
-        new BranchData(config, config.dataLayoutBranchDataTag),
-        new MultiBranchData(config, config.dataLayoutMultiBranchDataTag),
-        new ArgInfoData(config, config.dataLayoutArgInfoDataTag),
-        new UnknownProfileData(config, config.dataLayoutCallTypeDataTag),
-        new VirtualCallTypeData(config, config.dataLayoutVirtualCallTypeDataTag),
-        new UnknownProfileData(config, config.dataLayoutParametersTypeDataTag),
-        new UnknownProfileData(config, config.dataLayoutSpeculativeTrapDataTag),
-    };
-
-    private static boolean checkAccessorTags() {
-        int expectedTag = 0;
-        for (HotSpotMethodDataAccessor accessor : PROFILE_DATA_ACCESSORS) {
-            if (expectedTag == 0) {
-                assert accessor == null;
-            } else {
-                assert accessor.tag == expectedTag : expectedTag + " != " + accessor.tag + " " + accessor;
-            }
-            expectedTag++;
-        }
-        return true;
-    }
-
-    static {
-        assert checkAccessorTags();
-    }
-    // @formatter:on
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, 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
@@ -36,10 +36,12 @@
 
     final int tag;
     final int staticSize;
+    final HotSpotMethodData.VMState state;
     final HotSpotVMConfig config;
 
-    protected HotSpotMethodDataAccessor(HotSpotVMConfig config, int tag, int staticSize) {
-        this.config = config;
+    protected HotSpotMethodDataAccessor(HotSpotMethodData.VMState state, int tag, int staticSize) {
+        this.state = state;
+        this.config = state.config;
         this.tag = tag;
         this.staticSize = staticSize;
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, 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
@@ -26,9 +26,10 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import java.lang.invoke.MethodHandle;
-import java.util.Objects;
 
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.hotspot.HotSpotMethodData.VMState;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.MethodHandleAccessProvider;
@@ -45,15 +46,16 @@
     }
 
     /**
-     * Lazy initialization to break class initialization cycle. Field and method lookup is only
-     * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+     * Lazy initialized reflection on {@link MethodHandle} internals. Field and method lookup is
+     * only possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
      */
-    static class LazyInitialization {
-        static final ResolvedJavaType lambdaFormType;
-        static final ResolvedJavaField methodHandleFormField;
-        static final ResolvedJavaField lambdaFormVmentryField;
-        static final ResolvedJavaField methodField;
-        static final HotSpotResolvedJavaField vmtargetField;
+    static final class Internals {
+        final ResolvedJavaType lambdaFormType;
+        final ResolvedJavaField methodHandleFormField;
+        final ResolvedJavaField lambdaFormVmentryField;
+        final HotSpotResolvedJavaField callSiteTargetField;
+        final ResolvedJavaField methodField;
+        final HotSpotResolvedJavaField vmtargetField;
 
         /**
          * Search for an instance field with the given name in a class.
@@ -71,34 +73,53 @@
                     return field;
                 }
             }
-            throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName);
+            throw new NoSuchFieldError(declaringType + "." + fieldName);
         }
 
-        private static ResolvedJavaType resolveType(Class<?> c) {
-            return runtime().fromClass(c);
-        }
-
-        private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException {
-            return resolveType(Class.forName(className));
+        private static ResolvedJavaType resolveType(String className) {
+            return (ResolvedJavaType) runtime().lookupTypeInternal(className, null, true);
         }
 
-        static {
+        private Internals() {
             try {
-                ResolvedJavaType methodHandleType = resolveType(MethodHandle.class);
-                ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName");
-                lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
+                ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;");
+                ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;");
+                lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;");
                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
-                ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName");
+
+                ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;");
                 methodField = findFieldInClass(memberNameType, "method", methodType);
-                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass()));
+                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar())));
 
+                ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;");
+                callSiteTargetField = (HotSpotResolvedJavaField) findFieldInClass(callSiteType, "target", methodHandleType);
             } catch (Throwable ex) {
                 throw new JVMCIError(ex);
             }
         }
+
+        /**
+         * Singleton instance lazily initialized via double-checked locking.
+         */
+        @NativeImageReinitialize private static volatile Internals instance;
+
+        static Internals instance() {
+            Internals result = instance;
+            if (result == null) {
+                synchronized (VMState.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new Internals();
+                    }
+                }
+            }
+            return result;
+        }
+
     }
 
+
     @Override
     public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
         int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
@@ -131,19 +152,19 @@
         }
 
         /* Load non-public field: LambdaForm MethodHandle.form */
-        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+        Internals internals = Internals.instance();
+        JavaConstant lambdaForm = constantReflection.readFieldValue(internals.methodHandleFormField, methodHandle);
         if (lambdaForm == null || lambdaForm.isNull()) {
             return null;
         }
 
-        JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+        JavaConstant memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
         if (memberName.isNull() && forceBytecodeGeneration) {
-            Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType);
-            compilerToVM().compileToBytecode(Objects.requireNonNull(lf));
-            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+            compilerToVM().compileToBytecode((HotSpotObjectConstantImpl) lambdaForm);
+            memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
             assert memberName.isNonNull();
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(internals.methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -152,7 +173,7 @@
         if (memberName.isNull()) {
             return null;
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(Internals.instance().methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -165,8 +186,7 @@
             throw new IllegalArgumentException("unexpected type for memberName");
         }
 
-        Object object = ((HotSpotObjectConstantImpl) method).object();
         /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
-        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.getOffset());
+        return compilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) method, Internals.instance().vmtargetField.getOffset());
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, 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
@@ -23,6 +23,8 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.InvalidInstalledCodeException;
 import jdk.vm.ci.meta.JavaKind;
@@ -30,56 +32,104 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
- * Implementation of {@link InstalledCode} for code installed as an nmethod.
- *
- * When a {@link HotSpotNmethod} dies, it triggers unloading of the nmethod unless
- * {@link #isDefault() == true}.
+ * Implementation of {@link InstalledCode} for code installed as an {@code nmethod}. The address of
+ * the {@code nmethod} is stored in {@link InstalledCode#address} and the value of
+ * {@code nmethod::verified_entry_point()} is in {@link InstalledCode#entryPoint}.
  */
 public class HotSpotNmethod extends HotSpotInstalledCode {
 
     /**
-     * This (indirect) Method* reference is safe since class redefinition preserves all methods
-     * associated with nmethods in the code cache.
+     * This (indirect) {@code Method*} reference is safe since class redefinition preserves all
+     * methods associated with nmethods in the code cache.
      */
-    private final HotSpotResolvedJavaMethod method;
+    private final HotSpotResolvedJavaMethodImpl method;
 
+    /**
+     * Specifies whether the {@code nmethod} associated with this object is the code executed by
+     * default HotSpot linkage when a normal Java call to {@link #method} is made. That is, does
+     * {@code this.method.metadataHandle->_code} == {@code this.address}. If not, then the
+     * {@code nmethod} can only be invoked via a reference to this object. An example of this is the
+     * trampoline mechanism used by Truffle: https://goo.gl/LX88rZ.
+     */
     private final boolean isDefault;
 
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
+    /**
+     * Determines whether this object is in the oops table of the nmethod.
+     * <p>
+     * If this object is in the oops table, the VM uses the oops table entry to update this object's
+     * {@link #address} and {@link #entryPoint} fields when the state of the nmethod changes. The
+     * nmethod will be unloadable when this object dies.
+     * <p>
+     * Otherwise, the nmethod's unloadability is not changed when this object dies.
+     */
+    boolean inOopsTable() {
+        return compileIdSnapshot != 0;
+    }
+
+    /**
+     * If this field is 0, this object is in the oops table of the nmethod. Otherwise, the value of
+     * the field records the nmethod's compile identifier. This value is used to confirm an entry in
+     * the code cache retrieved by {@link #address} is indeed the nmethod represented by this
+     * object.
+     *
+     * @see #inOopsTable
+     */
+    private final long compileIdSnapshot;
+
+    HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
         super(name);
         this.method = method;
         this.isDefault = isDefault;
+        boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
+        this.compileIdSnapshot = inOopsTable ? 0L : compileId;
+        assert inOopsTable || compileId != 0L : this;
     }
 
     /**
      * Determines if the nmethod associated with this object is the compiled entry point for
-     * {@link #getMethod()}. If {@code false}, then the nmethod is unloaded when the VM determines
-     * this object has died.
+     * {@link #getMethod()}.
      */
     public boolean isDefault() {
         return isDefault;
     }
 
+    @Override
+    public boolean isValid() {
+        if (compileIdSnapshot != 0L) {
+            compilerToVM().updateHotSpotNmethod(this);
+        }
+        return super.isValid();
+    }
+
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
     public void invalidate() {
-        compilerToVM().invalidateInstalledCode(this);
+        compilerToVM().invalidateHotSpotNmethod(this);
+    }
+
+    @Override
+    public long getAddress() {
+        if (compileIdSnapshot != 0L) {
+            compilerToVM().updateHotSpotNmethod(this);
+        }
+        return super.getAddress();
+    }
+
+    @Override
+    public long getEntryPoint() {
+        if (compileIdSnapshot != 0L) {
+            return 0;
+        }
+        return super.getEntryPoint();
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
-    }
-
-    protected boolean checkThreeObjectArgs() {
-        assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
-        assert method.getSignature().getParameterKind(0) == JavaKind.Object;
-        assert method.getSignature().getParameterKind(1) == JavaKind.Object;
-        assert !method.isStatic() || method.getSignature().getParameterKind(2) == JavaKind.Object;
-        return true;
+        return String.format("HotSpotNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s, inOopsTable=%s]",
+                        method, getAddress(), isDefault, name, inOopsTable());
     }
 
     private boolean checkArgs(Object... args) {
@@ -98,8 +148,11 @@
 
     @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        if (IS_IN_NATIVE_IMAGE) {
+            throw new HotSpotJVMCIUnsupportedOperationError("Cannot execute nmethod via mirror in native image");
+        }
         assert checkArgs(args);
-        return compilerToVM().executeInstalledCode(args, this);
+        return compilerToVM().executeHotSpotNmethod(args, this);
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2017, 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
@@ -22,14 +22,9 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.ConstantCallSite;
-import java.lang.invoke.MethodHandle;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import jdk.vm.ci.meta.Assumptions;
-import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -38,45 +33,12 @@
  * Represents a constant non-{@code null} object reference, within the compiler and across the
  * compiler/runtime interface.
  */
-class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
-
-    static JavaConstant forObject(Object object) {
-        return forObject(object, false);
-    }
-
-    static JavaConstant forObject(Object object, boolean compressed) {
-        if (object == null) {
-            return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
-        } else {
-            return new HotSpotObjectConstantImpl(object, compressed);
-        }
-    }
+abstract class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
 
-    public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
-        if (kind == JavaKind.Object) {
-            return HotSpotObjectConstantImpl.forObject(value);
-        } else {
-            return JavaConstant.forBoxedPrimitive(value);
-        }
-    }
+    protected final boolean compressed;
 
-    static Object asBoxedValue(Constant constant) {
-        if (JavaConstant.isNull(constant)) {
-            return null;
-        } else if (constant instanceof HotSpotObjectConstantImpl) {
-            return ((HotSpotObjectConstantImpl) constant).object;
-        } else {
-            return ((JavaConstant) constant).asBoxedPrimitive();
-        }
-    }
-
-    private final Object object;
-    private final boolean compressed;
-
-    protected HotSpotObjectConstantImpl(Object object, boolean compressed) {
-        this.object = object;
+    HotSpotObjectConstantImpl(boolean compressed) {
         this.compressed = compressed;
-        assert object != null;
     }
 
     @Override
@@ -84,82 +46,54 @@
         return JavaKind.Object;
     }
 
-    /**
-     * Package-private accessor for the object represented by this constant.
-     */
-    Object object() {
-        return object;
-    }
-
     @Override
     public boolean isCompressed() {
         return compressed;
     }
 
     @Override
-    public JavaConstant compress() {
-        assert !compressed;
-        return new HotSpotObjectConstantImpl(object, true);
-    }
+    public abstract JavaConstant compress();
 
     @Override
-    public JavaConstant uncompress() {
-        assert compressed;
-        return new HotSpotObjectConstantImpl(object, false);
-    }
+    public abstract JavaConstant uncompress();
 
     @Override
     public HotSpotResolvedObjectType getType() {
-        return fromObjectClass(object.getClass());
+        return runtime().reflection.getType(this);
     }
 
     @Override
-    public int getIdentityHashCode() {
-        return System.identityHashCode(object);
-    }
+    public abstract int getIdentityHashCode();
 
     @Override
     public JavaConstant getCallSiteTarget(Assumptions assumptions) {
-        if (object instanceof CallSite) {
-            CallSite callSite = (CallSite) object;
-            MethodHandle target = callSite.getTarget();
-            JavaConstant targetConstant = HotSpotObjectConstantImpl.forObject(target);
-            if (!(callSite instanceof ConstantCallSite)) {
+        if (runtime().getCallSite().isInstance(this)) {
+            HotSpotObjectConstantImpl target = (HotSpotObjectConstantImpl) runtime().getHostJVMCIBackend().getConstantReflection().readFieldValue(
+                            HotSpotMethodHandleAccessProvider.Internals.instance().callSiteTargetField, this);
+            if (!runtime().getConstantCallSite().isInstance(this)) {
                 if (assumptions == null) {
                     return null;
                 }
-                assumptions.record(new Assumptions.CallSiteTargetValue(this, targetConstant));
+                assumptions.record(new Assumptions.CallSiteTargetValue(this, target));
             }
-
-            return targetConstant;
+            return target;
         }
         return null;
     }
 
     @Override
-    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
     public boolean isInternedString() {
-        if (object instanceof String) {
-            String s = (String) object;
-            return s.intern() == s;
-        }
-        return false;
+        return runtime().compilerToVm.isInternedString(this);
     }
 
     @Override
     public <T> T asObject(Class<T> type) {
-        if (type.isInstance(object)) {
-            return type.cast(object);
-        }
-        return null;
+        return runtime().reflection.asObject(this, type);
     }
 
     @Override
     public Object asObject(ResolvedJavaType type) {
-        if (type.isInstance(this)) {
-            return object;
-        }
-        return null;
+        return runtime().reflection.asObject(this, (HotSpotResolvedJavaType) type);
     }
 
     @Override
@@ -203,32 +137,40 @@
     }
 
     @Override
-    public int hashCode() {
-        return System.identityHashCode(object);
-    }
-
-    @Override
     public boolean equals(Object o) {
         if (o == this) {
             return true;
         } else if (o instanceof HotSpotObjectConstantImpl) {
             HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
-            return object == other.object && compressed == other.compressed;
+            return runtime().reflection.equals(this, other);
         }
         return false;
     }
 
     @Override
+    public int hashCode() {
+        return getIdentityHashCode();
+    }
+
+    @Override
     public String toValueString() {
-        if (object instanceof String) {
-            return "\"" + (String) object + "\"";
+        if (runtime().getJavaLangString().isInstance(this)) {
+            return "\"" + runtime().reflection.asString(this) + "\"";
         } else {
-            return JavaKind.Object.format(object);
+            return runtime().reflection.formatString(this);
         }
     }
 
     @Override
     public String toString() {
-        return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
+        return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + runtime().reflection.formatString(this) + "]";
+    }
+
+    public JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
+        return runtime().reflection.readFieldValue(this, field, isVolatile);
+    }
+
+    public ResolvedJavaType asJavaType() {
+        return runtime().reflection.asJavaType(this);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri May 03 14:59:32 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
@@ -22,15 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
-import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
-import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.util.HashMap;
+
+import jdk.internal.vm.annotation.Stable;
 
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaType;
@@ -44,7 +43,15 @@
 
     private final HotSpotResolvedObjectTypeImpl holder;
     private JavaType type;
+
+    /**
+     * Value of {@code fieldDescriptor::access_flags()}.
+     */
     private final int offset;
+
+    /**
+     * Value of {@code fieldDescriptor::index()}.
+     */
     private final short index;
 
     /**
@@ -68,7 +75,7 @@
         if (this == obj) {
             return true;
         }
-        if (obj instanceof HotSpotResolvedJavaField) {
+        if (obj instanceof HotSpotResolvedJavaFieldImpl) {
             HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj;
             if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
                 return false;
@@ -86,7 +93,7 @@
 
     @Override
     public int getModifiers() {
-        return modifiers & jvmFieldModifiers();
+        return modifiers & HotSpotModifiers.jvmFieldModifiers();
     }
 
     @Override
@@ -101,12 +108,12 @@
      *         {@code object}'s class
      */
     @Override
-    public boolean isInObject(JavaConstant constant) {
+    public boolean isInObject(JavaConstant object) {
         if (isStatic()) {
             return false;
         }
-        Object object = ((HotSpotObjectConstantImpl) constant).object();
-        return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass()));
+        HotSpotObjectConstant constant = (HotSpotObjectConstant) object;
+        return getDeclaringClass().isAssignableFrom(constant.getType());
     }
 
     @Override
@@ -127,12 +134,13 @@
         if (currentType instanceof UnresolvedJavaType) {
             // Don't allow unresolved types to hang around forever
             UnresolvedJavaType unresolvedType = (UnresolvedJavaType) currentType;
-            ResolvedJavaType resolved = holder.lookupType(unresolvedType, false);
-            if (resolved != null) {
+            JavaType resolved = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedType.getName(), holder, false);
+            if (resolved instanceof ResolvedJavaType) {
                 type = resolved;
             }
         }
         return type;
+
     }
 
     @Override
@@ -140,9 +148,17 @@
         return offset;
     }
 
+    /**
+     * Gets the value of this field's index (i.e. {@code fieldDescriptor::index()} in the encoded
+     * fields of the declaring class.
+     */
+    int getIndex() {
+        return index;
+    }
+
     @Override
     public String toString() {
-        return format("HotSpotField<%H.%n %t:") + offset + ">";
+        return format("HotSpotResolvedJavaFieldImpl<%H.%n %t:") + offset + ">";
     }
 
     @Override
@@ -151,9 +167,9 @@
     }
 
     /**
-     * Checks if this field has the {@code Stable} annotation.
+     * Checks if this field has the {@link Stable} annotation.
      *
-     * @return true if field has {@code Stable} annotation, false otherwise
+     * @return true if field has {@link Stable} annotation, false otherwise
      */
     @Override
     public boolean isStable() {
@@ -180,7 +196,7 @@
         if (!hasAnnotations()) {
             return new Annotation[0];
         }
-        return toJava().getAnnotations();
+        return runtime().reflection.getFieldAnnotations(this);
     }
 
     @Override
@@ -188,7 +204,7 @@
         if (!hasAnnotations()) {
             return new Annotation[0];
         }
-        return toJava().getDeclaredAnnotations();
+        return runtime().reflection.getFieldDeclaredAnnotations(this);
     }
 
     @Override
@@ -196,29 +212,6 @@
         if (!hasAnnotations()) {
             return null;
         }
-        return toJava().getAnnotation(annotationClass);
-    }
-
-    /**
-     * Gets a {@link Field} object corresponding to this object. This method always returns the same
-     * {@link Field} object for a given {@link HotSpotResolvedJavaFieldImpl}. This ensures
-     * {@link #getDeclaredAnnotations()}, {@link #getAnnotations()} and
-     * {@link #getAnnotation(Class)} are stable with respect to the identity of the
-     * {@link Annotation} objects they return.
-     */
-    private Field toJava() {
-        synchronized (holder) {
-            HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = holder.reflectionFieldCache;
-            if (cache == null) {
-                cache = new HashMap<>();
-                holder.reflectionFieldCache = cache;
-            }
-            Field reflect = cache.get(this);
-            if (reflect == null) {
-                reflect = compilerToVM().asReflectionField(holder, index);
-                cache.put(this, reflect);
-            }
-            return reflect;
-        }
+        return runtime().reflection.getFieldAnnotation(this, annotationClass);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri May 03 14:59:32 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
@@ -35,8 +35,6 @@
 import java.lang.reflect.Executable;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
 
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
@@ -58,23 +56,24 @@
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
  */
-final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceWrapperObject {
+final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceHandleObject {
 
     /**
-     * Reference to metaspace Method object.
+     * Handle to the metaspace {@code Method} object. The handle is in
+     * {@code JVMCI::_metadata_handles}.
      */
-    private final long metaspaceMethod;
+    private final long metadataHandle;
 
     private final HotSpotResolvedObjectTypeImpl holder;
     private final HotSpotConstantPool constantPool;
-    private final HotSpotSignature signature;
+    final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
 
     /**
-     * Cache for {@link #toJava()}.
+     * Cache for {@link HotSpotJDKReflection#getMethod}.
      */
-    private volatile Executable toJavaCache;
+    volatile Executable toJavaCache;
 
     /**
      * Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
@@ -85,35 +84,40 @@
     /**
      * Gets the holder of a HotSpot metaspace method native object.
      *
-     * @param metaspaceMethod a metaspace Method object
+     * @param metaspaceHandle a handle to a metaspace Method object
      * @return the {@link ResolvedJavaType} corresponding to the holder of the
      *         {@code metaspaceMethod}
      */
-    private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) {
+    private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceHandle) {
         HotSpotVMConfig config = config();
+        long metaspaceMethod = UNSAFE.getLong(metaspaceHandle);
+        assert metaspaceMethod != 0 : metaspaceHandle;
         final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset);
         final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset);
-        return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
+        HotSpotResolvedObjectTypeImpl result = compilerToVM().getResolvedJavaType(metaspaceConstantPool + config.constantPoolHolderOffset, false);
+        assert result != null;
+        return result;
     }
 
     /**
      * Gets the JVMCI mirror from a HotSpot method. The VM is responsible for ensuring that the
-     * Method* is kept alive for the duration of this call and the
-     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
-     *
+     * Method* is kept alive for the duration of this call and the {@link HotSpotJVMCIRuntime} keeps
+     * it alive after that.
+     * <p>
      * Called from the VM.
      *
-     * @param metaspaceMethod a metaspace Method object
+     * @param metaspaceHandle a handle to metaspace Method object
      * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
      */
     @SuppressWarnings("unused")
-    private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) {
-        HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceMethod);
-        return holder.createMethod(metaspaceMethod);
+    @VMEntryPoint
+    private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceHandle) {
+        HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceHandle);
+        return holder.createMethod(metaspaceHandle);
     }
 
-    HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
-        this.metaspaceMethod = metaspaceMethod;
+    HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceHandle) {
+        this.metadataHandle = metaspaceHandle;
         this.holder = holder;
 
         HotSpotVMConfig config = config();
@@ -133,6 +137,7 @@
 
         final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
         this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
+        HandleCleaner.create(this, metaspaceHandle);
     }
 
     /**
@@ -144,8 +149,7 @@
      * @return pointer to this method's ConstMethod
      */
     private long getConstMethod() {
-        assert metaspaceMethod != 0;
-        return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
+        return UNSAFE.getAddress(getMetaspaceMethod() + config().methodConstMethodOffset);
     }
 
     @Override
@@ -164,14 +168,14 @@
         }
         if (obj instanceof HotSpotResolvedJavaMethodImpl) {
             HotSpotResolvedJavaMethodImpl that = (HotSpotResolvedJavaMethodImpl) obj;
-            return that.metaspaceMethod == metaspaceMethod;
+            return that.getMetaspaceMethod() == getMetaspaceMethod();
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return (int) metaspaceMethod;
+        return (int) getMetaspaceMethod();
     }
 
     /**
@@ -180,7 +184,7 @@
      * @return flags of this method
      */
     private int getFlags() {
-        return UNSAFE.getShort(metaspaceMethod + config().methodFlagsOffset);
+        return UNSAFE.getShort(getMetaspaceMethod() + config().methodFlagsOffset);
     }
 
     /**
@@ -204,9 +208,17 @@
         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
     }
 
+    long getMetaspaceMethod() {
+        long metaspacePointer = getMetaspacePointer();
+        if (metaspacePointer == 0) {
+            throw new NullPointerException("Method* is null");
+        }
+        return metaspacePointer;
+    }
+
     @Override
-    public long getMetaspacePointer() {
-        return metaspaceMethod;
+    public long getMetadataHandle() {
+        return metadataHandle;
     }
 
     @Override
@@ -219,7 +231,7 @@
      * modifiers as well as the HotSpot internal modifiers.
      */
     public int getAllModifiers() {
-        return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset);
+        return UNSAFE.getInt(getMetaspaceMethod() + config().methodAccessFlagsOffset);
     }
 
     @Override
@@ -277,7 +289,7 @@
                 // Check for Throwable which catches everything.
                 if (catchType instanceof HotSpotResolvedObjectTypeImpl) {
                     HotSpotResolvedObjectTypeImpl resolvedType = (HotSpotResolvedObjectTypeImpl) catchType;
-                    if (resolvedType.mirror() == Throwable.class) {
+                    if (resolvedType.equals(runtime().getJavaLangThrowable())) {
                         catchTypeIndex = 0;
                         catchType = null;
                     }
@@ -424,7 +436,7 @@
      */
     private long getCompiledCode() {
         HotSpotVMConfig config = config();
-        return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset);
+        return UNSAFE.getAddress(getMetaspaceMethod() + config.methodCodeOffset);
     }
 
     /**
@@ -455,7 +467,7 @@
         ProfilingInfo info;
 
         if (Option.UseProfilingInformation.getBoolean() && methodData == null) {
-            long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
+            long metaspaceMethodData = UNSAFE.getAddress(getMetaspaceMethod() + config().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData, this);
                 String methodDataFilter = Option.TraceMethodDataFilter.getString();
@@ -490,14 +502,7 @@
         if (signature.getParameterCount(false) == 0) {
             return new ResolvedJavaMethod.Parameter[0];
         }
-        java.lang.reflect.Parameter[] javaParameters = toJava().getParameters();
-        Parameter[] res = new Parameter[javaParameters.length];
-        for (int i = 0; i < res.length; i++) {
-            java.lang.reflect.Parameter src = javaParameters[i];
-            String paramName = src.isNamePresent() ? src.getName() : null;
-            res[i] = new Parameter(paramName, src.getModifiers(), this, i);
-        }
-        return res;
+        return runtime().reflection.getParameters(this);
     }
 
     @Override
@@ -505,7 +510,7 @@
         if ((getConstMethodFlags() & config().constMethodHasParameterAnnotations) == 0) {
             return new Annotation[signature.getParameterCount(false)][0];
         }
-        return toJava().getParameterAnnotations();
+        return runtime().reflection.getParameterAnnotations(this);
     }
 
     @Override
@@ -513,7 +518,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return new Annotation[0];
         }
-        return toJava().getAnnotations();
+        return runtime().reflection.getMethodAnnotations(this);
     }
 
     @Override
@@ -521,7 +526,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return new Annotation[0];
         }
-        return toJava().getDeclaredAnnotations();
+        return runtime().reflection.getMethodDeclaredAnnotations(this);
     }
 
     @Override
@@ -529,7 +534,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return null;
         }
-        return toJava().getAnnotation(annotationClass);
+        return runtime().reflection.getMethodAnnotation(this, annotationClass);
     }
 
     @Override
@@ -559,19 +564,7 @@
         if (isClassInitializer()) {
             return new Type[0];
         }
-        return toJava().getGenericParameterTypes();
-    }
-
-    private Executable toJava() {
-        if (toJavaCache == null) {
-            assert !isClassInitializer() : this;
-            synchronized (this) {
-                if (toJavaCache == null) {
-                    toJavaCache = compilerToVM().asReflectionExecutable(this);
-                }
-            }
-        }
-        return toJavaCache;
+        return runtime().reflection.getGenericParameterTypes(this);
     }
 
     @Override
@@ -698,7 +691,7 @@
     private int getVtableIndex() {
         assert !holder.isInterface();
         HotSpotVMConfig config = config();
-        int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        int result = UNSAFE.getInt(getMetaspaceMethod() + config.methodVtableIndexOffset);
         assert result >= config.nonvirtualVtableIndex : "must be linked";
         return result;
     }
@@ -708,40 +701,16 @@
         return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
     }
 
-    /**
-     * The {@link SpeculationLog} for methods compiled by JVMCI hang off this per-declaring-type
-     * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
-     * never moves and b) we never read from it.
-     * <p>
-     * One implication is that we will preserve {@link SpeculationLog}s for methods that have been
-     * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot
-     * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
-     * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
-     */
-    private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<>() {
-        @Override
-        protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
-            return new HashMap<>(4);
-        }
-    };
-
     @Override
     public SpeculationLog getSpeculationLog() {
-        Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror());
-        synchronized (map) {
-            SpeculationLog log = map.get(this.metaspaceMethod);
-            if (log == null) {
-                log = new HotSpotSpeculationLog();
-                map.put(metaspaceMethod, log);
-            }
-            return log;
-        }
+        long address = compilerToVM().getFailedSpeculationsAddress(this);
+        return new HotSpotSpeculationLog(address);
     }
 
     @Override
     public int intrinsicId() {
         HotSpotVMConfig config = config();
-        return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset);
+        return UNSAFE.getChar(getMetaspaceMethod() + config.methodIntrinsicIdOffset);
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, 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
@@ -22,6 +22,7 @@
  */
 package jdk.vm.ci.hotspot;
 
+import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
@@ -30,20 +31,13 @@
         super(name);
     }
 
-    abstract Class<?> mirror();
-
     @Override
-    public final boolean equals(Object obj) {
-        if (!(obj instanceof HotSpotResolvedJavaType)) {
-            return false;
-        }
-        HotSpotResolvedJavaType that = (HotSpotResolvedJavaType) obj;
-        return this.mirror().equals(that.mirror());
-    }
+    public abstract boolean equals(Object obj);
 
     @Override
     public final int hashCode() {
         return getName().hashCode();
     }
 
+    abstract JavaConstant getJavaMirror();
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri May 03 14:59:32 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,10 +31,7 @@
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.nio.ByteOrder;
 import java.util.HashMap;
@@ -56,9 +53,11 @@
 import jdk.vm.ci.meta.UnresolvedJavaType;
 
 /**
- * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. This class is not
+ * an {@link MetaspaceHandleObject} because it doesn't have to be scanned for GC. It's liveness is
+ * maintained by a reference to the {@link Class} instance.
  */
-final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
+final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceObject {
 
     private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
     private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
@@ -66,94 +65,71 @@
     /**
      * The Java class this type represents.
      */
-    private final Class<?> javaClass;
+    private final long metadataPointer;
+
     private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
     private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
-    private HotSpotResolvedJavaField[] instanceFields;
-    private HotSpotResolvedObjectTypeImpl[] interfaces;
+    private volatile HotSpotResolvedJavaField[] instanceFields;
+    private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
     private HotSpotConstantPool constantPool;
-    final HotSpotJVMCIMetaAccessContext context;
     private HotSpotResolvedObjectType arrayOfType;
+    private final JavaConstant mirror;
+    private HotSpotResolvedObjectTypeImpl superClass;
 
     /**
-     * Managed exclusively by {@link HotSpotResolvedJavaFieldImpl#toJava}.
+     * Managed exclusively by {@link HotSpotJDKReflection#getField}.
      */
     HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
 
-    /**
-     * Gets the JVMCI mirror for a {@link Class} object.
-     *
-     * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
-     */
-    static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
-        return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
+    static HotSpotResolvedObjectTypeImpl getJavaLangObject() {
+        return runtime().getJavaLangObject();
     }
 
     /**
-     * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
-     * underlying Klass*, it is used instead of the raw Klass*.
+     * Gets the JVMCI mirror from a HotSpot type.
      *
      * Called from the VM.
      *
-     * @param javaClass a {@link Class} object
+     * @param klassPointer a native pointer to the Klass*
      * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
      */
     @SuppressWarnings("unused")
-    private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
-        return fromObjectClass(javaClass);
+    @VMEntryPoint
+    private static HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
+        return runtime().fromMetaspace(klassPointer, signature);
     }
 
     /**
      * Creates the JVMCI mirror for a {@link Class} object.
      *
-     * <p>
      * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
-     * {@link Class} type. Use {@link #fromObjectClass(Class)} or {@link #fromMetaspace(Class)}
-     * instead.
+     * {@link Class} type. {@link #fromMetaspace} instead.
      * </p>
      *
-     * @param javaClass the Class to create the mirror for
-     * @param context
+     * @param metadataPointer the Klass* to create the mirror for
      */
-    HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
-        super(getSignatureName(javaClass));
-        this.javaClass = javaClass;
-        this.context = context;
+    HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
+        super(name);
+        this.metadataPointer = metadataPointer;
+        this.mirror = runtime().compilerToVm.getJavaMirror(this);
+        assert metadataPointer != 0;
         assert getName().charAt(0) != '[' || isArray() : getName();
     }
 
     /**
-     * Returns the name of this type as it would appear in a signature.
-     */
-    private static String getSignatureName(Class<?> javaClass) {
-        if (javaClass.isArray()) {
-            return javaClass.getName().replace('.', '/');
-        }
-        return "L" + javaClass.getName().replace('.', '/') + ";";
-    }
-
-    /**
      * Gets the metaspace Klass for this type.
      */
     long getMetaspaceKlass() {
-        if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
-            return UNSAFE.getLong(javaClass, config().klassOffset);
+        long metaspacePointer = getMetaspacePointer();
+        if (metaspacePointer == 0) {
+            throw new NullPointerException("Klass* is null");
         }
-        return UNSAFE.getInt(javaClass, config().klassOffset) & 0xFFFFFFFFL;
+        return metaspacePointer;
     }
 
     @Override
     public long getMetaspacePointer() {
-        return getMetaspaceKlass();
-    }
-
-    /**
-     * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
-     * extra work is required.
-     */
-    @Override
-    public boolean isRegistered() {
-        return true;
+        return metadataPointer;
     }
 
     @Override
@@ -173,15 +149,18 @@
     @Override
     public HotSpotResolvedObjectType getArrayClass() {
         if (arrayOfType == null) {
-            arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
+            try {
+                arrayOfType = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + getName(), this, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
         }
         return arrayOfType;
     }
 
     @Override
     public ResolvedJavaType getComponentType() {
-        Class<?> javaComponentType = mirror().getComponentType();
-        return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
+        return runtime().compilerToVm.getComponentType(this);
     }
 
     @Override
@@ -279,19 +258,35 @@
 
     @Override
     public HotSpotResolvedObjectTypeImpl getSuperclass() {
-        Class<?> javaSuperclass = mirror().getSuperclass();
-        return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
+        if (isInterface()) {
+            return null;
+        }
+        HotSpotResolvedObjectTypeImpl javaLangObject = runtime().getJavaLangObject();
+        if (this.equals(javaLangObject)) {
+            return null;
+        }
+        if (isArray()) {
+            return javaLangObject;
+        }
+
+        // Cache result of native call
+        if (superClass == null) {
+            superClass = compilerToVM().getResolvedJavaType(this, config().superOffset, false);
+        }
+        return superClass;
     }
 
     @Override
     public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
         if (interfaces == null) {
-            Class<?>[] javaInterfaces = mirror().getInterfaces();
-            HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
-            for (int i = 0; i < javaInterfaces.length; i++) {
-                result[i] = fromObjectClass(javaInterfaces[i]);
+            if (isArray()) {
+                HotSpotResolvedObjectTypeImpl[] types = new HotSpotResolvedObjectTypeImpl[2];
+                types[0] = runtime().getJavaLangCloneable();
+                types[1] = runtime().getJavaLangSerializable();
+                this.interfaces = types;
+            } else {
+                interfaces = runtime().compilerToVm.getInterfaces(this);
             }
-            interfaces = result;
         }
         return interfaces;
     }
@@ -308,13 +303,14 @@
     public HotSpotResolvedObjectTypeImpl getSupertype() {
         if (isArray()) {
             ResolvedJavaType componentType = getComponentType();
-            if (mirror() == Object[].class || componentType.isPrimitive()) {
-                return fromObjectClass(Object.class);
+            if (componentType.equals(getJavaLangObject()) || componentType.isPrimitive()) {
+                return getJavaLangObject();
             }
-            return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
+            HotSpotResolvedObjectTypeImpl supertype = ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype();
+            return (HotSpotResolvedObjectTypeImpl) supertype.getArrayClass();
         }
         if (isInterface()) {
-            return fromObjectClass(Object.class);
+            return getJavaLangObject();
         }
         return getSuperclass();
     }
@@ -354,18 +350,14 @@
     }
 
     @Override
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    @Override
     public boolean isArray() {
-        return mirror().isArray();
+        return layoutHelper() < config().klassLayoutHelperNeutralValue;
     }
 
     @Override
     public boolean isEnum() {
-        return mirror().isEnum();
+        HotSpotResolvedObjectTypeImpl superclass = getSuperclass();
+        return superclass != null && superclass.equals(runtime().getJavaLangEnum());
     }
 
     @Override
@@ -392,7 +384,7 @@
     @Override
     public void initialize() {
         if (!isInitialized()) {
-            UNSAFE.ensureClassInitialized(mirror());
+            runtime().compilerToVm.ensureInitialized(this);
             assert isInitialized();
         }
     }
@@ -400,7 +392,7 @@
     @Override
     public boolean isInstance(JavaConstant obj) {
         if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
-            return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
+            return runtime().reflection.isInstance(this, (HotSpotObjectConstantImpl) obj);
         }
         return false;
     }
@@ -412,7 +404,7 @@
 
     @Override
     public boolean isInterface() {
-        return mirror().isInterface();
+        return (getAccessFlags() & config().jvmAccInterface) != 0;
     }
 
     @Override
@@ -420,7 +412,7 @@
         assert other != null;
         if (other instanceof HotSpotResolvedObjectTypeImpl) {
             HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
-            return mirror().isAssignableFrom(otherType.mirror());
+            return runtime().reflection.isAssignableFrom(this, otherType);
         }
         return false;
     }
@@ -435,7 +427,7 @@
 
     @Override
     public boolean isJavaLangObject() {
-        return javaClass.equals(Object.class);
+        return getName().equals("Ljava/lang/Object;");
     }
 
     @Override
@@ -501,6 +493,7 @@
     @Override
     public int layoutHelper() {
         HotSpotVMConfig config = config();
+        assert getMetaspaceKlass() != 0 : getName();
         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
     }
 
@@ -509,7 +502,8 @@
         return compilerToVM().getFingerprint(getMetaspaceKlass());
     }
 
-    synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
+    synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceHandle) {
+        long metaspaceMethod = UNSAFE.getLong(metaspaceHandle);
         // Maintain cache as array.
         if (methodCacheArray == null) {
             methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
@@ -519,11 +513,10 @@
         for (; i < methodCacheArray.length; ++i) {
             HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
             if (curMethod == null) {
-                HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+                HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
                 methodCacheArray[i] = newMethod;
-                context.add(newMethod);
                 return newMethod;
-            } else if (curMethod.getMetaspacePointer() == metaspaceMethod) {
+            } else if (curMethod.getMetaspaceMethod() == metaspaceMethod) {
                 return curMethod;
             }
         }
@@ -535,9 +528,8 @@
 
         HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
         if (lookupResult == null) {
-            HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+            HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
             methodCacheHashMap.put(metaspaceMethod, newMethod);
-            context.add(lookupResult);
             return newMethod;
         } else {
             return lookupResult;
@@ -599,6 +591,27 @@
         return new FieldInfo(index);
     }
 
+    public void ensureInitialized() {
+        runtime().compilerToVm.ensureInitialized(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof HotSpotResolvedObjectTypeImpl)) {
+            return false;
+        }
+        HotSpotResolvedObjectTypeImpl that = (HotSpotResolvedObjectTypeImpl) obj;
+        return getMetaspaceKlass() == that.getMetaspaceKlass();
+    }
+
+    @Override
+    JavaConstant getJavaMirror() {
+        return mirror;
+    }
+
     /**
      * This class represents the field information for one field contained in the fields array of an
      * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
@@ -782,11 +795,6 @@
     }
 
     @Override
-    public Class<?> mirror() {
-        return javaClass;
-    }
-
-    @Override
     public String getSourceFileName() {
         HotSpotVMConfig config = config();
         final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
@@ -798,17 +806,17 @@
 
     @Override
     public Annotation[] getAnnotations() {
-        return mirror().getAnnotations();
+        return runtime().reflection.getAnnotations(this);
     }
 
     @Override
     public Annotation[] getDeclaredAnnotations() {
-        return mirror().getDeclaredAnnotations();
+        return runtime().reflection.getDeclaredAnnotations(this);
     }
 
     @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        return mirror().getAnnotation(annotationClass);
+        return runtime().reflection.getAnnotation(this, annotationClass);
     }
 
     /**
@@ -828,12 +836,17 @@
         }
         if (elementType.getName().startsWith("Ljava/")) {
             // Classes in a java.* package can only be defined by the
-            // boot or platform class loader.
+            // boot class loader. This is enforced by ClassLoader.preDefineClass()
+            assert hasSameClassLoader(runtime().getJavaLangObject());
             return true;
         }
-        ClassLoader thisCl = mirror().getClassLoader();
-        ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
-        return thisCl == accessingClassCl;
+        HotSpotResolvedObjectTypeImpl otherMirror = ((HotSpotResolvedObjectTypeImpl) accessingClass);
+        return hasSameClassLoader(otherMirror);
+    }
+
+    private boolean hasSameClassLoader(HotSpotResolvedObjectTypeImpl otherMirror) {
+        return UnsafeAccess.UNSAFE.getAddress(getMetaspaceKlass() + config().classLoaderDataOffset) == UnsafeAccess.UNSAFE.getAddress(
+                        otherMirror.getMetaspaceKlass() + config().classLoaderDataOffset);
     }
 
     @Override
@@ -887,16 +900,15 @@
 
     private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
         for (ResolvedJavaField field : declaredFields) {
-            HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
-            long resolvedFieldOffset = resolvedField.getOffset();
+            long resolvedFieldOffset = field.getOffset();
             // @formatter:off
-            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN  &&
-                            expectedEntryKind.isPrimitive() &&
-                            !expectedEntryKind.equals(JavaKind.Void) &&
-                            resolvedField.getJavaKind().isPrimitive()) {
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
+                    expectedEntryKind.isPrimitive() &&
+                    !expectedEntryKind.equals(JavaKind.Void) &&
+                    field.getJavaKind().isPrimitive()) {
                 resolvedFieldOffset +=
-                                resolvedField.getJavaKind().getByteCount() -
-                                Math.min(resolvedField.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
+                        field.getJavaKind().getByteCount() -
+                                Math.min(field.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
             }
             if (resolvedFieldOffset == offset) {
                 return field;
@@ -908,40 +920,27 @@
 
     @Override
     public boolean isLocal() {
-        return mirror().isLocalClass();
+        return runtime().reflection.isLocalClass(this);
     }
 
     @Override
     public boolean isMember() {
-        return mirror().isMemberClass();
+        return runtime().reflection.isMemberClass(this);
     }
 
     @Override
-    public HotSpotResolvedObjectTypeImpl getEnclosingType() {
-        final Class<?> encl = mirror().getEnclosingClass();
-        return encl == null ? null : fromObjectClass(encl);
+    public HotSpotResolvedObjectType getEnclosingType() {
+        return runtime().reflection.getEnclosingClass(this);
     }
 
     @Override
     public ResolvedJavaMethod[] getDeclaredConstructors() {
-        Constructor<?>[] constructors = mirror().getDeclaredConstructors();
-        ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
-        for (int i = 0; i < constructors.length; i++) {
-            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
-            assert result[i].isConstructor();
-        }
-        return result;
+        return runtime().compilerToVm.getDeclaredConstructors(this);
     }
 
     @Override
     public ResolvedJavaMethod[] getDeclaredMethods() {
-        Method[] methods = mirror().getDeclaredMethods();
-        ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
-        for (int i = 0; i < methods.length; i++) {
-            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
-            assert !result[i].isConstructor();
-        }
-        return result;
+        return runtime().compilerToVm.getDeclaredMethods(this);
     }
 
     @Override
@@ -986,6 +985,10 @@
         return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
     }
 
+    JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
+        return runtime().reflection.readFieldValue(this, field, isVolatile);
+    }
+
     private int getMiscFlags() {
         return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, 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
@@ -23,12 +23,13 @@
 package jdk.vm.ci.hotspot;
 
 import static java.util.Objects.requireNonNull;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
 
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
@@ -42,22 +43,38 @@
  */
 public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType {
 
-    private final JavaKind kind;
+    @NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
+
+    private JavaKind kind;
+    private HotSpotResolvedObjectType arrayClass;
+    HotSpotObjectConstantImpl mirror;
 
     /**
      * Creates the JVMCI mirror for a primitive {@link JavaKind}.
      *
-     * <p>
-     * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
-     * {@link Class} type. Use {@link HotSpotJVMCIRuntime#fromClass(Class)} instead.
-     * </p>
-     *
      * @param kind the Kind to create the mirror for
      */
-    HotSpotResolvedPrimitiveType(JavaKind kind) {
+    private HotSpotResolvedPrimitiveType(JavaKind kind, HotSpotObjectConstantImpl mirror) {
         super(String.valueOf(kind.getTypeChar()));
+        this.mirror = mirror;
         this.kind = kind;
-        assert mirror().isPrimitive() : mirror() + " not a primitive type";
+    }
+
+    static HotSpotResolvedPrimitiveType forKind(JavaKind kind) {
+        HotSpotResolvedPrimitiveType primitive = primitives[kind.getBasicType()];
+        assert primitive != null : kind;
+        return primitive;
+    }
+
+    @VMEntryPoint
+    static HotSpotResolvedPrimitiveType fromMetaspace(HotSpotObjectConstantImpl mirror, char typeChar) {
+        JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(typeChar);
+        if (primitives == null) {
+            primitives = new HotSpotResolvedPrimitiveType[JavaKind.Void.getBasicType() + 1];
+        }
+        HotSpotResolvedPrimitiveType result = new HotSpotResolvedPrimitiveType(kind, mirror);
+        primitives[kind.getBasicType()] = result;
+        return result;
     }
 
     @Override
@@ -70,8 +87,14 @@
         if (kind == JavaKind.Void) {
             return null;
         }
-        Class<?> javaArrayMirror = Array.newInstance(mirror(), 0).getClass();
-        return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaArrayMirror);
+        if (arrayClass == null) {
+            try {
+                arrayClass = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + kind.getTypeChar(), null, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
+        }
+        return arrayClass;
     }
 
     @Override
@@ -241,11 +264,6 @@
     }
 
     @Override
-    Class<?> mirror() {
-        return kind.toJavaClass();
-    }
-
-    @Override
     public boolean isLocal() {
         return false;
     }
@@ -279,4 +297,18 @@
     public boolean isCloneableWithAllocation() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof HotSpotResolvedPrimitiveType)) {
+            return false;
+        }
+        HotSpotResolvedPrimitiveType that = (HotSpotResolvedPrimitiveType) obj;
+        return that.kind == kind;
+    }
+
+    @Override
+    JavaConstant getJavaMirror() {
+        return runtime().reflection.getJavaMirror(this);
+    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 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
@@ -27,7 +27,9 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
- * Implementation of {@link InstalledCode} for code installed as a RuntimeStub.
+ * Implementation of {@link InstalledCode} for code installed as a {@code RuntimeStub}. The address
+ * of the {@code RuntimeStub} is stored in {@link InstalledCode#address} and the value of
+ * {@code RuntimeStub::entry_point()} is in {@link InstalledCode#entryPoint}.
  */
 public class HotSpotRuntimeStub extends HotSpotInstalledCode {
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, 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
@@ -168,15 +168,17 @@
                 type = (ResolvedJavaType) result;
                 parameterTypes[index] = type;
             } else {
+                assert result != null;
                 return result;
             }
         }
+        assert type != null;
         return type;
     }
 
     @Override
     public String toMethodDescriptor() {
-        assert originalString.equals(Signature.super.toMethodDescriptor());
+        assert originalString.equals(Signature.super.toMethodDescriptor()) : originalString + " != " + Signature.super.toMethodDescriptor();
         return originalString;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,197 @@
+/*
+ * 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 jdk.vm.ci.hotspot;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+
+/**
+ * Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte
+ * array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the
+ * total length of data exceeds the length of a SHA-1 digest, then a SHA-1 digest of the data is
+ * produced instead.
+ */
+final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding {
+
+    private DataOutputStream dos = new DataOutputStream(this);
+    private byte[] result;
+
+    HotSpotSpeculationEncoding() {
+        super(SHA1_LENGTH);
+    }
+
+    private void checkOpen() {
+        if (result != null) {
+            throw new IllegalArgumentException("Cannot update closed speculation encoding");
+        }
+    }
+
+    private static final int NULL_METHOD = -1;
+    private static final int NULL_TYPE = -2;
+    private static final int NULL_STRING = -3;
+
+    @Override
+    public void addByte(int value) {
+        checkOpen();
+        try {
+            dos.writeByte(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addShort(int value) {
+        checkOpen();
+        try {
+            dos.writeShort(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addMethod(ResolvedJavaMethod method) {
+        if (!addNull(method, NULL_METHOD)) {
+            checkOpen();
+            if (method instanceof HotSpotResolvedJavaMethodImpl) {
+                try {
+                    dos.writeLong(((HotSpotResolvedJavaMethodImpl) method).getMetaspaceMethod());
+                } catch (IOException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                throw new IllegalArgumentException("Cannot encode unsupported type " + method.getClass().getName() + ": " + method.format("%H.%n(%p)"));
+            }
+        }
+    }
+
+    @Override
+    public void addType(ResolvedJavaType type) {
+        if (!addNull(type, NULL_TYPE)) {
+            checkOpen();
+            if (type instanceof HotSpotResolvedObjectTypeImpl) {
+                try {
+                    dos.writeLong(((HotSpotResolvedObjectTypeImpl) type).getMetaspaceKlass());
+                } catch (IOException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                throw new IllegalArgumentException("Cannot encode unsupported type " + type.getClass().getName() + ": " + type.toClassName());
+            }
+        }
+    }
+
+    @Override
+    public void addString(String value) {
+        if (!addNull(value, NULL_STRING)) {
+            checkOpen();
+            try {
+                dos.writeChars(value);
+            } catch (IOException e) {
+                throw new InternalError(e);
+            }
+        }
+    }
+
+    @Override
+    public void addInt(int value) {
+        checkOpen();
+        try {
+            dos.writeInt(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addLong(long value) {
+        checkOpen();
+        try {
+            dos.writeLong(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private boolean addNull(Object o, int nullValue) {
+        if (o == null) {
+            addInt(nullValue);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Prototype SHA1 digest that is cloned before use.
+     */
+    private static final MessageDigest SHA1 = getSHA1();
+    private static final int SHA1_LENGTH = SHA1.getDigestLength();
+
+    private static MessageDigest getSHA1() {
+        try {
+            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+            sha1.clone();
+            return sha1;
+        } catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
+            // Should never happen given that SHA-1 is mandated in a
+            // compliant Java platform implementation.
+            throw new JVMCIError("Expect a cloneable implementation of a SHA-1 message digest to be available", e);
+        }
+    }
+
+    /**
+     * Gets the final encoded byte array and closes this encoding such that any further attempts to
+     * update it result in an {@link IllegalArgumentException}.
+     */
+    byte[] getByteArray() {
+        if (result == null) {
+            if (count > SHA1_LENGTH) {
+                try {
+                    MessageDigest md = (MessageDigest) SHA1.clone();
+                    md.update(buf, 0, count);
+                    result = md.digest();
+                } catch (CloneNotSupportedException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                if (buf.length == count) {
+                    // No need to copy the byte array
+                    return buf;
+                }
+                result = Arrays.copyOf(buf, count);
+            }
+            dos = null;
+        }
+        return result;
+    }
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, 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
@@ -22,98 +22,340 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.List;
+
+import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.SpeculationLog;
 
+/**
+ * Implements a {@link SpeculationLog} that can be used to:
+ * <ul>
+ * <li>Query failed speculations recorded in a native linked list of {@code FailedSpeculation}s (see
+ * methodData.hpp).</li>
+ * <li>Make speculations during compilation and record them in compiled code. This must only be done
+ * on compilation-local {@link HotSpotSpeculationLog} objects.</li>
+ * </ul>
+ *
+ * The choice of constructor determines whether the native failed speculations list is
+ * {@linkplain #managesFailedSpeculations() managed} by a {@link HotSpotSpeculationLog} object.
+ */
 public class HotSpotSpeculationLog implements SpeculationLog {
+
+    private static final byte[] NO_FLATTENED_SPECULATIONS = {};
+
+    /**
+     * Creates a speculation log that manages a failed speculation list. That is, when this object
+     * dies, the native resources of the list are freed.
+     *
+     * @see #managesFailedSpeculations()
+     * @see #getFailedSpeculationsAddress()
+     */
+    public HotSpotSpeculationLog() {
+        managesFailedSpeculations = true;
+    }
+
+    /**
+     * Creates a speculation log that reads from an externally managed failed speculation list. That
+     * is, the lifetime of the list is independent of this object.
+     *
+     * @param failedSpeculationsAddress an address in native memory at which the pointer to the
+     *            externally managed sailed speculation list resides
+     */
+    public HotSpotSpeculationLog(long failedSpeculationsAddress) {
+        if (failedSpeculationsAddress == 0) {
+            throw new IllegalArgumentException("failedSpeculationsAddress cannot be 0");
+        }
+        this.failedSpeculationsAddress = failedSpeculationsAddress;
+        managesFailedSpeculations = false;
+    }
+
+    /**
+     * Gets the address of the pointer to the native failed speculations list.
+     *
+     * @see #managesFailedSpeculations()
+     */
+    public long getFailedSpeculationsAddress() {
+        if (managesFailedSpeculations) {
+            synchronized (this) {
+                if (failedSpeculationsAddress == 0L) {
+                    failedSpeculationsAddress = UnsafeAccess.UNSAFE.allocateMemory(HotSpotJVMCIRuntime.getHostWordKind().getByteCount());
+                    UnsafeAccess.UNSAFE.putAddress(failedSpeculationsAddress, 0L);
+                    LogCleaner c = new LogCleaner(this, failedSpeculationsAddress);
+                    assert c.address == failedSpeculationsAddress;
+                }
+            }
+        }
+        return failedSpeculationsAddress;
+    }
+
+    /**
+     * Adds {@code speculation} to the native list of failed speculations. To update this object's
+     * view of the failed speculations, {@link #collectFailedSpeculations()} must be called after
+     * this method returns.
+     *
+     * This method exists primarily for testing purposes. Speculations are normally only added to
+     * the list by HotSpot during deoptimization.
+     *
+     * @return {@code false} if the speculation could not be appended to the list
+     */
+    public boolean addFailedSpeculation(Speculation speculation) {
+        return compilerToVM().addFailedSpeculation(getFailedSpeculationsAddress(), ((HotSpotSpeculation) speculation).encoding);
+    }
+
+    /**
+     * Returns {@code true} if the value returned by {@link #getFailedSpeculationsAddress()} is only
+     * valid only as long as this object is alive, {@code false} otherwise.
+     */
+    public boolean managesFailedSpeculations() {
+        return managesFailedSpeculations;
+    }
+
     public static final class HotSpotSpeculation extends Speculation {
-        private JavaConstant encoding;
 
-        HotSpotSpeculation(SpeculationReason reason, JavaConstant encoding) {
+        /**
+         * A speculation id is a long encoding an offset (high 32 bits) and a length (low 32 bts).
+         * Combined, the index and length denote where the {@linkplain #encoding encoded
+         * speculation} is in a {@linkplain HotSpotSpeculationLog#getFlattenedSpeculations
+         * flattened} speculations array.
+         */
+        private final JavaConstant id;
+
+        private final byte[] encoding;
+
+        HotSpotSpeculation(SpeculationReason reason, JavaConstant id, byte[] encoding) {
             super(reason);
+            this.id = id;
             this.encoding = encoding;
         }
 
         public JavaConstant getEncoding() {
-            return encoding;
+            return id;
+        }
+
+        @Override
+        public String toString() {
+            long indexAndLength = id.asLong();
+            int index = decodeIndex(indexAndLength);
+            int length = decodeLength(indexAndLength);
+            return String.format("{0x%016x[index: %d, len: %d, hash: 0x%x]: %s}", indexAndLength, index, length, Arrays.hashCode(encoding), getReason());
         }
     }
 
-    /** Written by the C++ code that performs deoptimization. */
-    private volatile long lastFailed;
+    /**
+     * Address of a pointer to a set of failed speculations. The address is recorded in the nmethod
+     * compiled with this speculation log such that when it fails a speculation, the speculation is
+     * added to the list.
+     */
+    private long failedSpeculationsAddress;
+
+    private final boolean managesFailedSpeculations;
 
-    /** All speculations that have caused a deoptimization. */
-    private Set<SpeculationReason> failedSpeculations;
+    /**
+     * The list of failed speculations read from native memory via
+     * {@link CompilerToVM#getFailedSpeculations}.
+     */
+    private byte[][] failedSpeculations;
 
-    /** Strong references to all reasons embedded in the current nmethod. */
-    private HashMap<SpeculationReason, JavaConstant> speculations;
-
-    private long currentSpeculationID;
+    /**
+     * Speculations made during the compilation associated with this log.
+     */
+    private List<byte[]> speculations;
+    private List<SpeculationReason> speculationReasons;
 
     @Override
-    public synchronized void collectFailedSpeculations() {
-        if (lastFailed != 0) {
-            if (failedSpeculations == null) {
-                failedSpeculations = new HashSet<>(2);
-            }
-            if (speculations != null) {
-                SpeculationReason lastFailedSpeculation = lookupSpeculation(this.lastFailed);
-                if (lastFailedSpeculation != null) {
-                    failedSpeculations.add(lastFailedSpeculation);
-                }
-                lastFailed = 0;
-                speculations = null;
-            }
+    public void collectFailedSpeculations() {
+        if (failedSpeculationsAddress != 0 && UnsafeAccess.UNSAFE.getLong(failedSpeculationsAddress) != 0) {
+            failedSpeculations = compilerToVM().getFailedSpeculations(failedSpeculationsAddress, failedSpeculations);
+            assert failedSpeculations.getClass() == byte[][].class;
         }
     }
 
-    private SpeculationReason lookupSpeculation(long value) {
-        for (Map.Entry<SpeculationReason, JavaConstant> entry : speculations.entrySet()) {
-            if (value == entry.getValue().asLong()) {
-                return entry.getKey();
+    byte[] getFlattenedSpeculations(boolean validate) {
+        if (speculations == null) {
+            return NO_FLATTENED_SPECULATIONS;
+        }
+        if (validate) {
+            int newFailuresStart = failedSpeculations == null ? 0 : failedSpeculations.length;
+            collectFailedSpeculations();
+            if (failedSpeculations != null && failedSpeculations.length != newFailuresStart) {
+                for (SpeculationReason reason : speculationReasons) {
+                    byte[] encoding = encode(reason);
+                    // Only check against new failures
+                    if (contains(failedSpeculations, newFailuresStart, encoding)) {
+                        throw new BailoutException(false, "Speculation failed: " + reason);
+                    }
+                }
             }
         }
-        return null;
+        int size = 0;
+        for (byte[] s : speculations) {
+            size += s.length;
+        }
+        byte[] result = new byte[size];
+        size = 0;
+        for (byte[] s : speculations) {
+            System.arraycopy(s, 0, result, size, s.length);
+            size += s.length;
+        }
+        return result;
     }
 
     @Override
-    public synchronized boolean maySpeculate(SpeculationReason reason) {
-        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
-            return false;
+    public boolean maySpeculate(SpeculationReason reason) {
+        if (failedSpeculations == null) {
+            collectFailedSpeculations();
+        }
+        if (failedSpeculations != null && failedSpeculations.length != 0) {
+            byte[] encoding = encode(reason);
+            return !contains(failedSpeculations, 0, encoding);
         }
         return true;
     }
 
-    @Override
-    public synchronized Speculation speculate(SpeculationReason reason) {
-        if (speculations == null) {
-            speculations = new HashMap<>();
+    /**
+     * @return {@code true} if {@code needle} is in {@code haystack[fromIndex..haystack.length-1]}
+     */
+    private static boolean contains(byte[][] haystack, int fromIndex, byte[] needle) {
+        for (int i = fromIndex; i < haystack.length; i++) {
+            byte[] fs = haystack[i];
+
+            if (Arrays.equals(fs, needle)) {
+                return true;
+            }
         }
-        JavaConstant id = speculations.get(reason);
-        if (id == null) {
-            id = JavaConstant.forLong(++currentSpeculationID);
-            speculations.put(reason, id);
+        return false;
+    }
+
+    private static long encodeIndexAndLength(int index, int length) {
+        return ((long) index) << 32 | length;
+    }
+
+    private static int decodeIndex(long indexAndLength) {
+        return (int) (indexAndLength >>> 32);
+    }
+
+    private static int decodeLength(long indexAndLength) {
+        return (int) indexAndLength & 0xFFFFFFFF;
+    }
+
+    @Override
+    public Speculation speculate(SpeculationReason reason) {
+        byte[] encoding = encode(reason);
+        JavaConstant id;
+        if (speculations == null) {
+            speculations = new ArrayList<>();
+            speculationReasons = new ArrayList<>();
+            id = JavaConstant.forLong(encodeIndexAndLength(0, encoding.length));
+            speculations.add(encoding);
+            speculationReasons.add(reason);
+        } else {
+            id = null;
+            int flattenedIndex = 0;
+            for (byte[] fs : speculations) {
+                if (Arrays.equals(fs, encoding)) {
+                    id = JavaConstant.forLong(encodeIndexAndLength(flattenedIndex, fs.length));
+                    break;
+                }
+                flattenedIndex += fs.length;
+            }
+            if (id == null) {
+                id = JavaConstant.forLong(encodeIndexAndLength(flattenedIndex, encoding.length));
+                speculations.add(encoding);
+                speculationReasons.add(reason);
+            }
         }
-        return new HotSpotSpeculation(reason, id);
+
+        return new HotSpotSpeculation(reason, id, encoding);
+    }
+
+    private static byte[] encode(SpeculationReason reason) {
+        HotSpotSpeculationEncoding encoding = (HotSpotSpeculationEncoding) reason.encode(HotSpotSpeculationEncoding::new);
+        byte[] result = encoding == null ? null : encoding.getByteArray();
+        if (result == null) {
+            throw new IllegalArgumentException(HotSpotSpeculationLog.class.getName() + " expects " + reason.getClass().getName() + ".encode() to return a non-empty encoding");
+        }
+        return result;
+    }
+
+    @Override
+    public boolean hasSpeculations() {
+        return speculations != null;
     }
 
     @Override
-    public synchronized boolean hasSpeculations() {
-        return speculations != null && !speculations.isEmpty();
+    public Speculation lookupSpeculation(JavaConstant constant) {
+        if (constant.isDefaultForKind()) {
+            return NO_SPECULATION;
+        }
+        int flattenedIndex = decodeIndex(constant.asLong());
+        int index = 0;
+        for (byte[] s : speculations) {
+            if (flattenedIndex == 0) {
+                SpeculationReason reason = speculationReasons.get(index);
+                return new HotSpotSpeculation(reason, constant, s);
+            }
+            index++;
+            flattenedIndex -= s.length;
+        }
+        throw new IllegalArgumentException("Unknown encoded speculation: " + constant);
     }
 
     @Override
-    public synchronized Speculation lookupSpeculation(JavaConstant constant) {
-        if (constant.isDefaultForKind()) {
-            return NO_SPECULATION;
+    public String toString() {
+        Formatter buf = new Formatter();
+        buf.format("{managed:%s, failedSpeculationsAddress:0x%x, failedSpeculations:[", managesFailedSpeculations, failedSpeculationsAddress);
+
+        String sep = "";
+        if (failedSpeculations != null) {
+            for (int i = 0; i < failedSpeculations.length; i++) {
+                buf.format("%s{len:%d, hash:0x%x}", sep, failedSpeculations[i].length, Arrays.hashCode(failedSpeculations[i]));
+                sep = ", ";
+            }
+        }
+
+        buf.format("], speculations:[");
+
+        int size = 0;
+        if (speculations != null) {
+            sep = "";
+            for (int i = 0; i < speculations.size(); i++) {
+                byte[] s = speculations.get(i);
+                size += s.length;
+                buf.format("%s{len:%d, hash:0x%x, reason:{%s}}", sep, s.length, Arrays.hashCode(s), speculationReasons.get(i));
+                sep = ", ";
+            }
         }
-        SpeculationReason reason = lookupSpeculation(constant.asLong());
-        assert reason != null : "Speculation should have been registered";
-        return new HotSpotSpeculation(reason, constant);
+        buf.format("], len:%d, hash:0x%x}", size, Arrays.hashCode(getFlattenedSpeculations(false)));
+        return buf.toString();
+    }
+
+    /**
+     * Frees the native memory resources associated with {@link HotSpotSpeculationLog}s once they
+     * become reclaimable.
+     */
+    private static final class LogCleaner extends Cleaner {
+
+        LogCleaner(HotSpotSpeculationLog referent, long address) {
+            super(referent);
+            this.address = address;
+        }
+
+        @Override
+        void doCleanup() {
+            long pointer = UnsafeAccess.UNSAFE.getAddress(address);
+            if (pointer != 0) {
+                compilerToVM().releaseFailedSpeculations(address);
+            }
+            UnsafeAccess.UNSAFE.freeMemory(address);
+        }
+
+        final long address;
     }
 }
+
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri May 03 14:59:32 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
@@ -25,6 +25,7 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
+import jdk.vm.ci.services.Services;
 import jdk.internal.misc.Unsafe;
 
 /**
@@ -52,7 +53,7 @@
      * {@linkplain HotSpotJVMCIBackendFactory backend}.
      */
     String getHostArchitectureName() {
-        String arch = System.getProperty("os.arch");
+        String arch = Services.getSavedProperty("os.arch");
         switch (arch) {
             case "x86_64":
                 return "amd64";
@@ -70,16 +71,21 @@
 
     final int objectAlignment = getFlag("ObjectAlignmentInBytes", Integer.class);
 
+    final int hubOffset = getFieldOffset("oopDesc::_metadata._klass", Integer.class, "Klass*");
+
     final int prototypeMarkWordOffset = getFieldOffset("Klass::_prototype_header", Integer.class, "markOop");
     final int subklassOffset = getFieldOffset("Klass::_subklass", Integer.class, "Klass*");
+    final int superOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*");
     final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*");
     final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint");
     final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
 
+    final int classLoaderDataOffset = getFieldOffset("Klass::_class_loader_data", Integer.class, "ClassLoaderData*");
+
     /**
      * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
      */
-    final int classMirrorHandleOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "OopHandle");
+    final int javaMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "OopHandle");
 
     final int klassAccessFlagsOffset = getFieldOffset("Klass::_access_flags", Integer.class, "AccessFlags");
     final int klassLayoutHelperOffset = getFieldOffset("Klass::_layout_helper", Integer.class, "jint");
@@ -131,6 +137,7 @@
     final int jvmAccBridge = getConstant("JVM_ACC_BRIDGE", Integer.class);
     final int jvmAccVarargs = getConstant("JVM_ACC_VARARGS", Integer.class);
     final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class);
+    final int jvmAccInterface = getConstant("JVM_ACC_INTERFACE", Integer.class);
 
     // This is only valid on AMD64.
     final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, osArch.equals("amd64") ? null : 0);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri May 03 14:59:32 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
@@ -22,6 +22,9 @@
  */
 package jdk.vm.ci.hotspot;
 
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import jdk.vm.ci.common.JVMCIError;
 
 /**
@@ -50,8 +53,8 @@
             if (notPresent != null) {
                 return notPresent;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM symbol not found in " + store + ": " + name);
+            throw missingEntry("address", name, store.vmFlags.keySet());
+
         }
         return entry;
     }
@@ -82,8 +85,7 @@
             if (notPresent != null) {
                 return notPresent;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM constant not found in " + store + ": " + name);
+            throw missingEntry("constant", name, store.vmConstants.keySet());
         }
         return type.cast(convertValue(name, type, c, null));
     }
@@ -112,15 +114,23 @@
      * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
      */
     public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) {
-        assert type == Integer.class || type == Long.class;
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.address != 0) {
-            throw new JVMCIError("cannot get offset of static field " + name);
-        }
-        return type.cast(convertValue(name, type, entry.offset, cppType));
+        return getFieldOffset0(name, type, notPresent, cppType, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, T notPresent, String[] outCppType) {
+        return getFieldOffset0(name, type, notPresent, null, outCppType);
     }
 
     /**
@@ -134,7 +144,7 @@
      * @throws JVMCIError if the field is static or not present
      */
     public <T> T getFieldOffset(String name, Class<T> type, String cppType) {
-        return getFieldOffset(name, type, cppType, null);
+        return getFieldOffset0(name, type, null, cppType, null);
     }
 
     /**
@@ -147,7 +157,22 @@
      * @throws JVMCIError if the field is static or not present
      */
     public <T> T getFieldOffset(String name, Class<T> type) {
-        return getFieldOffset(name, type, null, null);
+        return getFieldOffset0(name, type, null, null, null);
+    }
+
+    private <T> T getFieldOffset0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) {
+        assert type == Integer.class || type == Long.class;
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address != 0) {
+            throw new JVMCIError("cannot get offset of static field " + name);
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return type.cast(convertValue(name, type, entry.offset, inCppType));
     }
 
     /**
@@ -160,14 +185,21 @@
      * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
      */
     public long getFieldAddress(String name, String cppType, Long notPresent) {
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.address == 0) {
-            throw new JVMCIError(name + " is not a static field");
-        }
-        return entry.address;
+        return getFieldAddress0(name, notPresent, cppType, null);
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public long getFieldAddress(String name, Long notPresent, String[] outCppType) {
+        return getFieldAddress0(name, notPresent, null, outCppType);
     }
 
     /**
@@ -179,7 +211,21 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public long getFieldAddress(String name, String cppType) {
-        return getFieldAddress(name, cppType, null);
+        return getFieldAddress0(name, null, cppType, null);
+    }
+
+    private long getFieldAddress0(String name, Long notPresent, String inCppType, String[] outCppType) {
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address == 0) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return entry.address;
     }
 
     /**
@@ -193,14 +239,7 @@
      * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
      */
     public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) {
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.value == null) {
-            throw new JVMCIError(name + " is not a static field");
-        }
-        return type.cast(convertValue(name, type, entry.value, cppType));
+        return getFieldValue0(name, type, notPresent, cppType, null);
     }
 
     /**
@@ -213,7 +252,22 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public <T> T getFieldValue(String name, Class<T> type, String cppType) {
-        return getFieldValue(name, type, cppType, null);
+        return getFieldValue0(name, type, null, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldValue(String name, Class<T> type, T notPresent, String[] outCppType) {
+        return getFieldValue0(name, type, notPresent, null, outCppType);
     }
 
     /**
@@ -225,7 +279,21 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public <T> T getFieldValue(String name, Class<T> type) {
-        return getFieldValue(name, type, null, null);
+        return getFieldValue0(name, type, null, null, null);
+    }
+
+    private <T> T getFieldValue0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) {
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.value == null) {
+            throw new JVMCIError(name + " is not a static field ");
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return type.cast(convertValue(name, type, entry.value, inCppType));
     }
 
     /**
@@ -243,8 +311,7 @@
             if (!required) {
                 return null;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM field not found in " + store + ": " + name);
+            throw missingEntry("field", name, store.vmFields.keySet());
         }
 
         // Make sure the native type is still the type we expect.
@@ -288,8 +355,7 @@
                 if (notPresent != null) {
                     return notPresent;
                 }
-                store.printConfig();
-                throw new JVMCIError("expected VM flag not found in " + store + ": " + name);
+                throw missingEntry("flag", name, store.vmFlags.keySet());
             } else {
                 cppType = null;
             }
@@ -300,6 +366,11 @@
         return type.cast(convertValue(name, type, value, cppType));
     }
 
+    private JVMCIError missingEntry(String category, String name, Set<String> keys) {
+        throw new JVMCIError("expected VM %s not found in %s: %s%nAvailable values:%n    %s", category, store, name,
+                        keys.stream().sorted().collect(Collectors.joining(System.lineSeparator() + "    ")));
+    }
+
     private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
         if (toType == Boolean.class) {
             if (value instanceof String) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl {
+    /**
+     * An object handle in {@code JVMCI::_jvmci_handles}.
+     */
+    final long objectHandle;
+    private int hashCode;
+
+    final IndirectHotSpotObjectConstantImpl base;
+
+    @VMEntryPoint
+    private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) {
+        super(compressed);
+        assert objectHandle != 0 && UnsafeAccess.UNSAFE.getLong(objectHandle) != 0;
+        this.objectHandle = objectHandle;
+        this.base = null;
+        if (!skipRegister) {
+            HandleCleaner.create(this, objectHandle);
+        }
+    }
+
+    private IndirectHotSpotObjectConstantImpl(IndirectHotSpotObjectConstantImpl base, boolean compressed) {
+        super(compressed);
+        // This is a variant of an original object that only varies in compress vs uncompressed.
+        // Instead of creating a new handle, reference that object and objectHandle.
+        this.objectHandle = base.objectHandle;
+        // There should only be on level of indirection to the base object.
+        assert base.base == null || base.base.base == null;
+        this.base = base.base != null ? base.base : base;
+    }
+
+    @Override
+    public JavaConstant compress() {
+        assert !compressed;
+        return new IndirectHotSpotObjectConstantImpl(this, true);
+    }
+
+    @Override
+    public JavaConstant uncompress() {
+        assert compressed;
+        return new IndirectHotSpotObjectConstantImpl(this, false);
+    }
+
+    @Override
+    public int getIdentityHashCode() {
+        int hash = hashCode;
+        if (hash == 0) {
+            hash = runtime().compilerToVm.getIdentityHashCode(this);
+            if (hash == 0) {
+                hash = 31;
+            }
+            hashCode = hash;
+        }
+        return hash;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceHandleObject.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * A tag interface indicating that this type is a handledized wrapper around a HotSpot metaspace
+ * object that requires GC interaction to keep alive.
+ *
+ * It would preferable if this were the base class containing the pointer but that would require
+ * mixins since most of the wrapper types have complex supertype hierarchies.
+ */
+interface MetaspaceHandleObject extends MetaspaceObject {
+
+    long getMetadataHandle();
+
+    @Override
+    default long getMetaspacePointer() {
+        return UnsafeAccess.UNSAFE.getLong(getMetadataHandle());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceObject.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * The marker interface for an object which wraps HotSpot Metadata.
+ */
+interface MetaspaceObject {
+    long getMetaspacePointer();
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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.
- */
-package jdk.vm.ci.hotspot;
-
-/**
- * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object that
- * requires GC interaction to keep alive.
- *
- * It would preferable if this were the base class containing the pointer but that would require
- * mixins since most of the wrapper types have complex supertype hierarchies.
- */
-interface MetaspaceWrapperObject {
-
-    long getMetaspacePointer();
-
-    /**
-     * Check if this object is properly registered for metadata tracking. All classes which
-     * implement this interface must be registered with the
-     * {@link HotSpotJVMCIMetaAccessContext#add} unless they are kept alive through other means.
-     * Currently the only type which doesn't require explicit registration is
-     * {@link HotSpotResolvedObjectTypeImpl} since it's kept alive by references to the
-     * {@link Class}.
-     *
-     * @return true if this object is properly registered for meta data tracking.
-     */
-    default boolean isRegistered() {
-        return HotSpotJVMCIRuntime.runtime().metaAccessContext.isRegistered(this);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,360 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link HotSpotJVMCIReflection} when running in a JVMCI shared library.
+ */
+class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
+
+    @Override
+    Object resolveObject(HotSpotObjectConstantImpl objectHandle) {
+        throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve handle in a JVMCI shared library to a raw object: " + objectHandle);
+    }
+
+    @Override
+    boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj) {
+        if (obj instanceof DirectHotSpotObjectConstantImpl) {
+            ResolvedJavaType type = getType(obj);
+            return holder.isAssignableFrom(type);
+        }
+        return runtime().compilerToVm.isInstance(holder, obj);
+    }
+
+    @Override
+    boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType) {
+        return runtime().compilerToVm.isAssignableFrom(holder, otherType);
+    }
+
+    @Override
+    boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isLocalClass()");
+    }
+
+    @Override
+    boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isMemberClass()");
+    }
+
+    @Override
+    HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingClass()");
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
+        JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(holder, field, isVolatile);
+        if (javaConstant == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return javaConstant;
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            // cannot read fields from objects due to lack of
+            // general reflection support in native image
+            return null;
+        }
+        JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(object, field, isVolatile);
+        if (javaConstant == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return javaConstant;
+    }
+
+    @Override
+    boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) {
+        if (x == y) {
+            return true;
+        }
+        if (x.compressed != y.compressed) {
+            return false;
+        }
+        if (x instanceof DirectHotSpotObjectConstantImpl && y instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl xd = (DirectHotSpotObjectConstantImpl) x;
+            DirectHotSpotObjectConstantImpl yd = (DirectHotSpotObjectConstantImpl) y;
+            return (xd.object == yd.object);
+        }
+        if (x instanceof DirectHotSpotObjectConstantImpl || y instanceof DirectHotSpotObjectConstantImpl) {
+            // Mixing of constant types is always inequal
+            return false;
+        }
+        IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
+        IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y;
+        return runtime().compilerToVm.equals(x, indirectX.objectHandle, y, indirectY.objectHandle);
+    }
+
+    @Override
+    JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedPrimitiveType) {
+        return runtime().compilerToVm.getJavaMirror(hotSpotResolvedPrimitiveType);
+    }
+
+    @Override
+    ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
+        // ResolvedJavaMethod.getParameters allows a return value of null
+        return null;
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Annotation[] getClassAnnotations(String className) {
+        throw new InternalError("missing substitution: " + className);
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Annotation[][] getParameterAnnotations(String className, String methodName) {
+        throw new InternalError("missing substitution: " + className + " " + methodName);
+    }
+
+    @Override
+    Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        return getClassAnnotations(holder.getName());
+    }
+
+    @Override
+    Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getParameterAnnotations(javaMethod.getDeclaringClass().getName(), javaMethod.getName());
+    }
+
+    @Override
+    Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethodAnnotationsInternal(javaMethod);
+    }
+
+    @Override
+    <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
+        Annotation[] methodAnnotations = getMethodAnnotations(javaMethod);
+        if (methodAnnotations != null) {
+            for (Annotation ann : methodAnnotations) {
+                if (annotationClass.isInstance(ann)) {
+                    return annotationClass.cast(ann);
+                }
+            }
+        }
+        return null;
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    @SuppressWarnings("unused")
+    private static Annotation[] getMethodAnnotationsInternal(ResolvedJavaMethod javaMethod) {
+        throw new InternalError("missing substitution");
+    }
+
+    @Override
+    Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            Class<?> theClass = ((DirectHotSpotObjectConstantImpl) object).object.getClass();
+            try {
+                String name = theClass.getName().replace('.', '/');
+                HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(name, null, true);
+                if (type == null) {
+                    throw new InternalError(name);
+                }
+                return type;
+            } catch (ClassNotFoundException e) {
+                throw new InternalError(e);
+            }
+        }
+        return runtime().compilerToVm.getResolvedJavaType(object, runtime().getConfig().hubOffset, false);
+    }
+
+    @Override
+    String asString(HotSpotObjectConstantImpl object) {
+        if (object instanceof IndirectHotSpotObjectConstantImpl) {
+            return runtime().compilerToVm.asString(object);
+        }
+        Object value = ((DirectHotSpotObjectConstantImpl) object).object;
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return null;
+    }
+
+    @Override
+    ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            if (direct.object instanceof Class) {
+                Class<?> javaClass = (Class<?>) direct.object;
+                return runtime().fromClass(javaClass);
+            }
+            if (direct.object instanceof ResolvedJavaType) {
+                return (ResolvedJavaType) convertUnknownValue(direct.object);
+            }
+            return null;
+        }
+        return runtime().compilerToVm.asJavaType(object);
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Object convertUnknownValue(Object object) {
+        return object;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            Object theObject = ((DirectHotSpotObjectConstantImpl) object).object;
+            if (type.isInstance(theObject)) {
+                return (T) convertUnknownValue(type.cast(theObject));
+            }
+        }
+        return null;
+    }
+
+    @Override
+    Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
+        throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve a shared library JVMCI object handle to a " +
+                        "raw object as it may be in another runtime");
+    }
+
+    @Override
+    String formatString(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            return "CompilerObject<" + direct.object.getClass().getName() + ">";
+        }
+        return "Instance<" + object.getType().toJavaName() + ">";
+    }
+
+    @Override
+    Integer getLength(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            if (direct.object.getClass().isArray()) {
+                return Array.getLength(direct.object);
+            }
+            return null;
+        }
+        int length = runtime().compilerToVm.getArrayLength(object);
+        if (length >= 0) {
+            return length;
+        }
+        return null;
+    }
+
+    @Override
+    JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
+        Object result = runtime().compilerToVm.readArrayElement(arrayObject, index);
+        if (result == null) {
+            return null;
+        }
+        if (result instanceof JavaConstant) {
+            return (JavaConstant) result;
+        }
+        JavaConstant constant = JavaConstant.forBoxedPrimitive(result);
+        if (constant == null) {
+            throw new InternalError("Unexpected value " + result);
+        }
+        return constant;
+    }
+
+    @Override
+    JavaConstant forObject(Object value) {
+        return DirectHotSpotObjectConstantImpl.forObject(value, false);
+    }
+
+    @Override
+    JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
+        Object box = runtime().compilerToVm.unboxPrimitive(source);
+        return JavaConstant.forBoxedPrimitive(box);
+    }
+
+    @Override
+    JavaConstant boxPrimitive(JavaConstant source) {
+        return runtime().compilerToVm.boxPrimitive(source.asBoxedPrimitive());
+    }
+
+    @Override
+    int getInt(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getInt(object, displacement);
+    }
+
+    @Override
+    byte getByte(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getByte(object, displacement);
+    }
+
+    @Override
+    short getShort(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getShort(object, displacement);
+    }
+
+    @Override
+    long getLong(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getLong(object, displacement);
+    }
+
+    @Override
+    void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.Objects;
+
+/**
+ * Support for translating exceptions between different runtime heaps.
+ */
+@SuppressWarnings("serial")
+final class TranslatedException extends Exception {
+
+    private TranslatedException(String message) {
+        super(message);
+    }
+
+    private TranslatedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * No need to record an initial stack trace since it will be manually overwritten.
+     */
+    @SuppressWarnings("sync-override")
+    @Override
+    public Throwable fillInStackTrace() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return getMessage();
+    }
+
+    private static TranslatedException create(String className, String message) {
+        if (className.equals(TranslatedException.class.getName())) {
+            // Chop the class name when boxing another TranslatedException
+            return new TranslatedException(message);
+        }
+        if (message == null) {
+            return new TranslatedException(className);
+        }
+        return new TranslatedException(className + ": " + message);
+    }
+
+    private static String encodedString(String value) {
+        return Objects.toString(value, "").replace('|', '_');
+    }
+
+    /**
+     * Encodes {@code throwable} including its stack and causes as a string. The encoding format of
+     * a single exception with its cause is:
+     *
+     * <pre>
+     * <exception class name> '|' <exception message> '|' <stack size> '|' [<class> '|' <method> '|' <file> '|' <line> '|' ]*
+     * </pre>
+     *
+     * Each cause is appended after the exception is it the cause of.
+     */
+    @VMEntryPoint
+    static String encodeThrowable(Throwable throwable) throws Throwable {
+        try {
+            Formatter enc = new Formatter();
+            Throwable current = throwable;
+            do {
+                enc.format("%s|%s|", current.getClass().getName(), encodedString(current.getMessage()));
+                StackTraceElement[] stackTrace = current.getStackTrace();
+                if (stackTrace == null) {
+                    stackTrace = new StackTraceElement[0];
+                }
+                enc.format("%d|", stackTrace.length);
+                for (int i = 0; i < stackTrace.length; i++) {
+                    StackTraceElement frame = stackTrace[i];
+                    if (frame != null) {
+                        enc.format("%s|%s|%s|%d|", frame.getClassName(), frame.getMethodName(),
+                                        encodedString(frame.getFileName()), frame.getLineNumber());
+                    }
+                }
+                current = current.getCause();
+            } while (current != null);
+            return enc.toString();
+        } catch (Throwable e) {
+            try {
+                return e.getClass().getName() + "|" + encodedString(e.getMessage()) + "|0|";
+            } catch (Throwable e2) {
+                return "java.lang.Throwable|too many errors during encoding|0|";
+            }
+        }
+    }
+
+    /**
+     * Gets the stack of the current thread without the frames between this call and the one just
+     * below the frame of the first method in {@link CompilerToVM}. The chopped frames are specific
+     * to the implementation of {@link HotSpotJVMCIRuntime#decodeThrowable(String)}.
+     */
+    private static StackTraceElement[] getStackTraceSuffix() {
+        StackTraceElement[] stack = new Exception().getStackTrace();
+        for (int i = 0; i < stack.length; i++) {
+            StackTraceElement e = stack[i];
+            if (e.getClassName().equals(CompilerToVM.class.getName())) {
+                return Arrays.copyOfRange(stack, i, stack.length);
+            }
+        }
+        // This should never happen but since we're in exception handling
+        // code, just return a safe value instead raising a nested exception.
+        return new StackTraceElement[0];
+    }
+
+    /**
+     * Decodes {@code encodedThrowable} into a {@link TranslatedException}.
+     *
+     * @param encodedThrowable an encoded exception in the format specified by
+     *            {@link #encodeThrowable}
+     */
+    @VMEntryPoint
+    static Throwable decodeThrowable(String encodedThrowable) {
+        try {
+            int i = 0;
+            String[] parts = encodedThrowable.split("\\|");
+            Throwable parent = null;
+            Throwable result = null;
+            while (i != parts.length) {
+                String exceptionClassName = parts[i++];
+                String exceptionMessage = parts[i++];
+                Throwable throwable = create(exceptionClassName, exceptionMessage);
+                int stackTraceDepth = Integer.parseInt(parts[i++]);
+
+                StackTraceElement[] suffix = parent == null ? new StackTraceElement[0] : getStackTraceSuffix();
+                StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
+                for (int j = 0; j < stackTraceDepth; j++) {
+                    String className = parts[i++];
+                    String methodName = parts[i++];
+                    String fileName = parts[i++];
+                    int lineNumber = Integer.parseInt(parts[i++]);
+                    if (fileName.isEmpty()) {
+                        fileName = null;
+                    }
+                    stackTrace[j] = new StackTraceElement(className, methodName, fileName, lineNumber);
+                }
+                System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length);
+                throwable.setStackTrace(stackTrace);
+                if (parent != null) {
+                    parent.initCause(throwable);
+                } else {
+                    result = throwable;
+                }
+                parent = throwable;
+            }
+            return result;
+        } catch (Throwable t) {
+            return new TranslatedException("Error decoding exception: " + encodedThrowable, t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMEntryPoint.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Marker interface for methods which are called from the JVM.
+ */
+@interface VMEntryPoint {
+    /**
+     * An optional comment describing the caller.
+     */
+    String value() default "";
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Fri May 03 14:59:32 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
@@ -63,19 +63,20 @@
     }
 
     /**
-     * Creates a description of a field.
+     * Creates a description of a non-static field.
      */
-    VMField(String name, String type, long address, Object value) {
+    @VMEntryPoint
+    VMField(String name, String type, long offset, long address, Object value) {
         this.name = name;
         this.type = type;
-        this.offset = 0;
+        this.offset = offset;
         this.address = address;
         this.value = value;
     }
 
     @Override
     public String toString() {
-        String val = value == null ? "null" : String.format("0x%x", value);
+        String val = value == null ? "null" : (type.contains("*") ? String.format("0x%x", value) : String.format("%s", value));
         return String.format("Field[name=%s, type=%s, offset=%d, address=0x%x, value=%s]", name, type, offset, address, val);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Fri May 03 14:59:32 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
@@ -42,6 +42,7 @@
      */
     public final Object value;
 
+    @VMEntryPoint
     VMFlag(String name, String type, Object value) {
         this.name = name;
         this.type = type;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Fri May 03 14:59:32 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
@@ -54,6 +54,7 @@
      */
     public final int id;
 
+    @VMEntryPoint
     VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id) {
         this.declaringClass = declaringClass;
         this.name = name;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, 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
@@ -22,6 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 
 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
@@ -146,7 +147,7 @@
 
         public ProfiledType(ResolvedJavaType type, double probability) {
             super(type, probability);
-            assert type.isArray() || type.isConcrete() : type;
+            assert type.isArray() || type.isConcrete() : type + " " + Modifier.toString(type.getModifiers());
         }
 
         /**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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,14 +102,25 @@
      */
     JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
 
+    /**
+     * Gets a constant that denotes {@code speculation}. The constant can passed to the
+     * deoptimization handler (e.g., through a thread local) to indicate a failed speculation.
+     */
     JavaConstant encodeSpeculation(Speculation speculation);
 
+    /**
+     * Decodes {@code constant} back to a {@link Speculation} object.
+     *
+     * @throws IllegalArgumentException if {@code constant} can only be decoded through a
+     *             {@link SpeculationLog} and {@code speculationLog} does not contain the
+     *             speculation denoted by {@code constant}
+     */
+    Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog);
+
     DeoptimizationReason decodeDeoptReason(JavaConstant constant);
 
     DeoptimizationAction decodeDeoptAction(JavaConstant constant);
 
-    Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog);
-
     int decodeDebugId(JavaConstant constant);
 
     int getArrayBaseOffset(JavaKind elementKind);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, 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
@@ -46,6 +46,10 @@
         assert kind.isPrimitive() || kind == JavaKind.Illegal;
     }
 
+    static PrimitiveConstant forTypeChar(char kind, long i) {
+        return JavaConstant.forIntegerKind(JavaKind.fromPrimitiveOrVoidTypeChar(kind), i);
+    }
+
     @Override
     public JavaKind getJavaKind() {
         return kind;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, 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
@@ -25,7 +25,6 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
@@ -39,7 +38,8 @@
     /**
      * Returns the bytecode of this method, if the method has code. The returned byte array does not
      * contain breakpoints or non-Java bytecodes. This may return null if the
-     * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
+     * {@linkplain #getDeclaringClass() declaring class} is not
+     * {@linkplain ResolvedJavaType#isLinked() linked}.
      *
      * The contained constant pool indices may not be the ones found in the original class file but
      * they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
@@ -439,13 +439,15 @@
     }
 
     /**
-     * Checks whether the method has bytecodes associated with it. Methods without bytecodes are
-     * either abstract or native methods.
+     * Checks whether the method has bytecodes associated with it. Note that even if this method
+     * returns {@code true}, {@link #getCode} can return {@code null} if
+     * {@linkplain #getDeclaringClass() declaring class} is not
+     * {@linkplain ResolvedJavaType#isLinked() linked}.
      *
-     * @return whether the definition of this method is Java bytecodes
+     * @return {@code this.getCodeSize() != 0}
      */
     default boolean hasBytecodes() {
-        return isConcrete() && !isNative();
+        return getCodeSize() != 0;
     }
 
     /**
@@ -464,16 +466,11 @@
         return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
     }
 
+    /**
+     * Gets a speculation log that can be used when compiling this method to make new speculations
+     * and query previously failed speculations. The implementation may return a new
+     * {@link SpeculationLog} object each time this method is called so its the caller's
+     * responsibility to ensure the same speculation log is used throughout a compilation.
+     */
     SpeculationLog getSpeculationLog();
-
-    /**
-     *
-     * @param object
-     * @param args
-     * @throws InvocationTargetException
-     * @throws IllegalAccessException
-     */
-    default JavaConstant invoke(JavaConstant object, JavaConstant... args) throws InvocationTargetException, IllegalAccessException {
-        throw new InternalError("unimplemented");
-    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -22,19 +22,72 @@
  */
 package jdk.vm.ci.meta;
 
+import java.util.Map;
+import java.util.function.Supplier;
+
 /**
- * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be
- * invalidated at run time. Subsequent compilations then should not speculate again on such
- * invalidated reasons to avoid repeated deoptimization.
- *
- * All methods of this interface are called by the compiler. There is no need for API to register
- * failed speculations during deoptimization, since every VM has different needs there.
+ * Manages unique {@link SpeculationReason} objects that denote why a deoptimization occurred.
+ * Reasons are embedded in compiled code for a method. If the compiled code deoptimizes at a
+ * position associated with a {@link SpeculationReason}, the reason is added to a set of failed
+ * speculations associated with the method. A subsequent compilation of the method can query the
+ * failed speculations via a {@link SpeculationLog} to avoid making a speculation based on
+ * invalidated reasons. This avoids repeated deoptimizations.
  */
 public interface SpeculationLog {
     /**
-     * Marker interface for speculation objects that can be added to the speculation log.
+     * The specific attributes of a speculation that a compiler uses to denote a speculation in a
+     * compiled method. Typical attributes of a speculation are a bytecode position, type
+     * information about a variable being speculated on and an enum denoting the type of operation
+     * to which the speculation applies. A {@link SpeculationReason} is used as a key in a
+     * {@link Map} and so it must implement {@link Object#equals(Object)} and
+     * {@link Object#hashCode()} in terms of its attributes.
+     *
+     * A JVMCI implementation may serialize speculations for storage off heap (e.g. in native memory
+     * associated with an nmethod). For this reason, the attributes of a {@link SpeculationReason}
+     * are restricted to those supported by the {@code add...} methods of
+     * {@link SpeculationReasonEncoding}.
      */
     public interface SpeculationReason {
+
+        /**
+         * Encodes the attributes of this reason using a {@link SpeculationReasonEncoding}. For
+         * efficiency, a {@link SpeculationReason} implementation should cache the returned value
+         * and return it for all subsequent calls to this method. This also underlines the
+         * requirement that the encoding for a specific reason instance should be stable.
+         *
+         * @param encodingSupplier source of a {@link SpeculationReasonEncoding}
+         * @return a {@link SpeculationReasonEncoding} that encodes all the attributes that uniquely
+         *         identify this reason
+         */
+        default SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            return null;
+        }
+    }
+
+    /**
+     * Provides a facility for encoding the attributes of a {@link SpeculationReason}. The encoding
+     * format is determined by the implementation of this interface.
+     */
+    public interface SpeculationReasonEncoding {
+        void addByte(int value);
+
+        void addShort(int value);
+
+        void addInt(int value);
+
+        void addLong(long value);
+
+        void addMethod(ResolvedJavaMethod method);
+
+        void addType(ResolvedJavaType type);
+
+        void addString(String value);
+
+        default void addField(ResolvedJavaField field) {
+            addType(field.getDeclaringClass());
+            addInt(field.getModifiers());
+            addInt(field.getOffset());
+        }
     }
 
     /**
@@ -44,7 +97,7 @@
     }
 
     class Speculation {
-        private SpeculationReason reason;
+        private final SpeculationReason reason;
 
         public Speculation(SpeculationReason reason) {
             this.reason = reason;
@@ -77,7 +130,8 @@
     Speculation NO_SPECULATION = new Speculation(new NoSpeculationReason());
 
     /**
-     * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}.
+     * Updates the set of failed speculations recorded in this log. This must be called before
+     * compilation.
      */
     void collectFailedSpeculations();
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Fri May 03 14:59:32 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
@@ -24,40 +24,57 @@
 
 import java.util.Formatter;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.services.Services;
+
 public class JVMCI {
 
-    private static final JVMCIRuntime runtime;
+    /**
+     * Singleton instance lazily initialized via double-checked locking.
+     */
+    @NativeImageReinitialize private static volatile JVMCIRuntime runtime;
 
-    private static native JVMCIRuntime initializeRuntime();
+    @NativeImageReinitialize private static boolean initializing;
 
     public static void initialize() {
         // force static initializer
     }
 
+    private static native JVMCIRuntime initializeRuntime();
+
     /**
      * Gets the singleton {@link JVMCIRuntime} instance available to the application.
      *
      * @throws UnsupportedOperationException if JVMCI is not supported
      */
     public static JVMCIRuntime getRuntime() {
-        if (runtime == null) {
-            String javaHome = System.getProperty("java.home");
-            String vmName = System.getProperty("java.vm.name");
-            Formatter errorMessage = new Formatter();
-            errorMessage.format("The VM does not support the JVMCI API.%n");
-            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
-            errorMessage.format("Currently used VM configuration is: %s", vmName);
-            throw new UnsupportedOperationException(errorMessage.toString());
+        JVMCIRuntime result = runtime;
+        if (result == null) {
+            synchronized (JVMCI.class) {
+                result = runtime;
+                if (result == null) {
+                    if (initializing) {
+                        // In recursive call from HotSpotJVMCIRuntime.runtime
+                        // so no need to re-enter initializeRuntime below. This
+                        // path is only entered if JVMCI initialization starts
+                        // with JVMCI.getRuntime().
+                        return null;
+                    }
+                    initializing = true;
+                    try {
+                        runtime = result = initializeRuntime();
+                    } catch (UnsatisfiedLinkError e) {
+                        String javaHome = Services.getSavedProperty("java.home");
+                        String vmName = Services.getSavedProperty("java.vm.name");
+                        Formatter errorMessage = new Formatter();
+                        errorMessage.format("The VM does not support the JVMCI API.%n");
+                        errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+                        errorMessage.format("Currently used VM configuration is: %s", vmName);
+                        throw new UnsupportedOperationException(errorMessage.toString());
+                    }
+                }
+            }
         }
-        return runtime;
-    }
-
-    static {
-        JVMCIRuntime rt = null;
-        try {
-            rt = initializeRuntime();
-        } catch (UnsatisfiedLinkError e) {
-        }
-        runtime = rt;
+        return result;
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
-    Checkstyle-Configuration: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <module name="TreeWalker">
-    <property name="tabWidth" value="4"/>
-    <module name="JavadocStyle">
-      <property name="checkHtml" value="false"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-    <module name="ParameterName"/>
-    <module name="TypeName">
-      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
-    </module>
-    <module name="RedundantImport"/>
-    <module name="LineLength">
-      <property name="max" value="250"/>
-    </module>
-    <module name="MethodParamPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <module name="AvoidStarImport">
-       <property name="allowClassImports" value="false"/>
-       <property name="allowStaticMemberImports" value="false"/>
-    </module>
-    <module name="NoWhitespaceBefore">
-      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
-    </module>
-    <module name="ParenPad"/>
-    <module name="TypecastParenPad">
-      <property name="tokens" value="RPAREN,TYPECAST"/>
-    </module>
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
-    </module>
-    <module name="RedundantModifier"/>
-    <module name="AvoidNestedBlocks">
-      <property name="allowInSwitchCase" value="true"/>
-    </module>
-    <module name="EmptyBlock">
-      <property name="option" value="text"/>
-      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly"/>
-    <module name="NeedBraces"/>
-    <module name="RightCurly"/>
-    <module name="EmptyStatement"/>
-    <module name="HiddenField">
-      <property name="severity" value="ignore"/>
-      <property name="ignoreConstructorParameter" value="true"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="FinalClass"/>
-    <module name="HideUtilityClassConstructor">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ArrayTypeStyle"/>
-    <module name="UpperEll"/>
-    <module name="FallThrough"/>
-    <module name="FinalLocalVariable">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="MultipleVariableDeclarations"/>
-    <module name="StringLiteralEquality">
-      <property name="severity" value="error"/>
-    </module>
-    <module name="SuperFinalize"/>
-    <module name="UnnecessaryParentheses">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="Indentation">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="StaticVariableName">
-      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="EmptyForInitializerPad"/>
-    <module name="EmptyForIteratorPad"/>
-    <module name="ModifierOrder"/>
-    <module name="DefaultComesLast"/>
-    <module name="InnerAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="format" value="\s$"/>
-      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
-      <property name="checkFormat" value="ConstantNameCheck"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
-      <property name="checkFormat" value="MethodName"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
-      <property name="checkFormat" value="ParameterAssignment"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
-      <property name="checkFormat" value="FinalLocalVariable"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop"/>
-      <property name="onCommentFormat" value="Checkstyle: resume"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
-      <property name="checkFormat" value="InnerAssignment"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
-      <property name="checkFormat" value="MemberName"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-      <property name="checkFormat" value=".*Header"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
-      <property name="checkFormat" value="LineLength"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: start generated"/>
-      <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-      <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop"/>
-      <property name="onCommentFormat" value="Checkstyle: resume"/>
-      <property name="checkFormat" value=".*"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="@formatter:off"/>
-      <property name="onCommentFormat" value="@formatter:on"/>
-      <property name="checkFormat" value=".*"/>
-    </module>
-  </module>
-  <module name="RegexpHeader">
-    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="FileTabCharacter">
-    <property name="severity" value="error"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="NewlineAtEndOfFile">
-    <property name="lineSeparator" value="lf"/>
-  </module>
-  <module name="Translation"/>
-  <module name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-</module>
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Fri May 03 14:59:32 2019 -0400
@@ -22,6 +22,9 @@
  */
 package jdk.vm.ci.services;
 
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.ServiceLoader;
@@ -68,6 +71,26 @@
      */
     protected abstract <S> S getProvider(Class<S> service);
 
+    private static volatile List<JVMCIServiceLocator> cachedLocators;
+
+    private static Iterable<JVMCIServiceLocator> getJVMCIServiceLocators() {
+        Iterable<JVMCIServiceLocator> result = cachedLocators;
+        if (result != null) {
+            return result;
+        }
+        result = ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader());
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            ArrayList<JVMCIServiceLocator> l = new ArrayList<>();
+            for (JVMCIServiceLocator locator: result) {
+                l.add(locator);
+            }
+            l.trimToSize();
+            cachedLocators = l;
+            return l;
+        }
+        return result;
+    }
+
     /**
      * Gets the providers of the service defined by {@code service} by querying the available
      * {@link JVMCIServiceLocator} providers.
@@ -82,7 +105,7 @@
             sm.checkPermission(new JVMCIPermission());
         }
         List<S> providers = new ArrayList<>();
-        for (JVMCIServiceLocator access : ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader())) {
+        for (JVMCIServiceLocator access : getJVMCIServiceLocators()) {
             S provider = access.getProvider(service);
             if (provider != null) {
                 providers.add(provider);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Fri May 03 14:59:32 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
@@ -22,10 +22,23 @@
  */
 package jdk.vm.ci.services;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Properties;
+import java.util.ServiceLoader;
 import java.util.Set;
 
 import jdk.internal.misc.VM;
+import jdk.internal.reflect.Reflection;
 
 /**
  * Provides utilities needed by JVMCI clients.
@@ -36,35 +49,32 @@
     // processors while building JDK 9 so use of API added in JDK 9 is made via reflection.
 
     /**
-     * Guards code that should be run when building a native image but should be excluded from
-     * (being compiled into) the image. Such code must be directly guarded by an {@code if}
+     * Guards code that should be run when building an JVMCI shared library but should be excluded
+     * from (being compiled into) the library. Such code must be directly guarded by an {@code if}
      * statement on this field - the guard cannot be behind a method call.
      */
-    public static final boolean IS_BUILDING_NATIVE_IMAGE;
+    public static final boolean IS_BUILDING_NATIVE_IMAGE = Boolean.parseBoolean(VM.getSavedProperty("jdk.vm.ci.services.aot"));
 
     /**
-     * Guards code that should only be run in native image. Such code must be directly guarded by an
-     * {@code if} statement on this field - the guard cannot be behind a method call.
+     * Guards code that should only be run in a JVMCI shared library. Such code must be directly
+     * guarded by an {@code if} statement on this field - the guard cannot be behind a method call.
      *
-     * The value of this field seen during analysis and compilation of an SVM image must be
-     * {@code true}.
+     * The value of this field in a JVMCI shared library runtime must be {@code true}.
      */
     public static final boolean IS_IN_NATIVE_IMAGE;
-
     static {
         /*
-         * Prevents javac from constant folding use of this field. It is set to true in the SVM
-         * image via substitution during image building.
+         * Prevents javac from constant folding use of this field. It is set to true by the process
+         * that builds the shared library.
          */
         IS_IN_NATIVE_IMAGE = false;
-        IS_BUILDING_NATIVE_IMAGE = false;
     }
 
     private Services() {
     }
 
-    static final Map<String, String> SAVED_PROPERTIES = VM.getSavedProperties();
-    static final boolean JVMCI_ENABLED = Boolean.parseBoolean(SAVED_PROPERTIES.get("jdk.internal.vm.ci.enabled"));
+    private static volatile Map<String, String> savedProperties = VM.getSavedProperties();
+    static final boolean JVMCI_ENABLED = Boolean.parseBoolean(savedProperties.get("jdk.internal.vm.ci.enabled"));
 
     /**
      * Checks that JVMCI is enabled in the VM and throws an error if it isn't.
@@ -84,7 +94,21 @@
         if (sm != null) {
             sm.checkPermission(new JVMCIPermission());
         }
-        return SAVED_PROPERTIES;
+        return savedProperties;
+    }
+
+    /**
+     * Helper method equivalent to {@link #getSavedProperties()}{@code .getOrDefault(name, def)}.
+     */
+    public static String getSavedProperty(String name, String def) {
+        return Services.getSavedProperties().getOrDefault(name, def);
+    }
+
+    /**
+     * Helper method equivalent to {@link #getSavedProperties()}{@code .get(name)}.
+     */
+    public static String getSavedProperty(String name) {
+        return Services.getSavedProperties().get(name);
     }
 
     /**
@@ -99,6 +123,83 @@
         }
     }
 
+    private static boolean jvmciEnabled = true;
+
+    /**
+     * When {@code -XX:-UseJVMCIClassLoader} is in use, JVMCI classes are loaded via the boot class
+     * loader. When {@code null} is the second argument to
+     * {@link ServiceLoader#load(Class, ClassLoader)}, service lookup will use the system class
+     * loader and thus find application classes which violates the API of {@link #load} and
+     * {@link #loadSingle}. To avoid this, a class loader that simply delegates to the boot class
+     * loader is used.
+     */
+    static class LazyBootClassPath {
+        static final ClassLoader bootClassPath = new ClassLoader(null) {
+        };
+    }
+
+    private static ClassLoader findBootClassLoaderChild(ClassLoader start) {
+        ClassLoader cl = start;
+        while (cl.getParent() != null) {
+            cl = cl.getParent();
+        }
+        return cl;
+    }
+
+    private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
+
+    @SuppressWarnings("unchecked")
+    private static <S> Iterable<S> load0(Class<S> service) {
+        if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
+            List<?> list = servicesCache.get(service);
+            if (list != null) {
+                return (Iterable<S>) list;
+            }
+            if (IS_IN_NATIVE_IMAGE) {
+                throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
+            }
+        }
+
+        Iterable<S> providers = Collections.emptyList();
+        if (jvmciEnabled) {
+            ClassLoader cl = null;
+            try {
+                cl = getJVMCIClassLoader();
+                if (cl == null) {
+                    cl = LazyBootClassPath.bootClassPath;
+                    // JVMCI classes are loaded via the boot class loader.
+                    // If we use null as the second argument to ServiceLoader.load,
+                    // service loading will use the system class loader
+                    // and find classes on the application class path. Since we
+                    // don't want this, we use a loader that is as close to the
+                    // boot class loader as possible (since it is impossible
+                    // to force service loading to use only the boot class loader).
+                    cl = findBootClassLoaderChild(ClassLoader.getSystemClassLoader());
+                }
+                providers = ServiceLoader.load(service, cl);
+            } catch (UnsatisfiedLinkError e) {
+                jvmciEnabled = false;
+            } catch (InternalError e) {
+                if (e.getMessage().equals("JVMCI is not enabled")) {
+                    jvmciEnabled = false;
+                } else {
+                    throw e;
+                }
+            }
+        }
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            synchronized (servicesCache) {
+                ArrayList<S> providersList = new ArrayList<>();
+                for (S provider : providers) {
+                    providersList.add(provider);
+                }
+                servicesCache.put(service, providersList);
+                providers = providersList;
+            }
+        }
+        return providers;
+    }
+
     /**
      * Opens all JVMCI packages to {@code otherModule}.
      */
@@ -114,4 +215,123 @@
             }
         }
     }
+
+    /**
+     * Gets an {@link Iterable} of the JVMCI providers available for a given service.
+     *
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    public static <S> Iterable<S> load(Class<S> service) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        return load0(service);
+    }
+
+    /**
+     * Gets the JVMCI provider for a given service for which at most one provider must be available.
+     *
+     * @param service the service whose provider is being requested
+     * @param required specifies if an {@link InternalError} should be thrown if no provider of
+     *            {@code service} is available
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    public static <S> S loadSingle(Class<S> service, boolean required) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        Iterable<S> providers = load0(service);
+
+        S singleProvider = null;
+        for (S provider : providers) {
+            if (singleProvider != null) {
+                throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
+            }
+            singleProvider = provider;
+        }
+        if (singleProvider == null && required) {
+            String javaHome = Services.getSavedProperty("java.home");
+            String vmName = Services.getSavedProperty("java.vm.name");
+            Formatter errorMessage = new Formatter();
+            errorMessage.format("The VM does not expose required service %s.%n", service.getName());
+            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+            errorMessage.format("Currently used VM configuration is: %s", vmName);
+            throw new UnsupportedOperationException(errorMessage.toString());
+        }
+        return singleProvider;
+    }
+
+    static {
+        Reflection.registerMethodsToFilter(Services.class, Set.of("getJVMCIClassLoader"));
+    }
+
+    /**
+     * Gets the JVMCI class loader.
+     *
+     * @throws InternalError with the {@linkplain Throwable#getMessage() message}
+     *             {@code "JVMCI is not enabled"} iff JVMCI is not enabled
+     */
+    private static ClassLoader getJVMCIClassLoader() {
+        if (IS_IN_NATIVE_IMAGE) {
+            return null;
+        }
+        return ClassLoader.getSystemClassLoader();
+    }
+
+    /**
+     * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for
+     * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
+     * properties in the JVMCI shared library.
+     */
+    @VMEntryPoint
+    private static byte[] serializeSavedProperties() throws IOException {
+        if (IS_IN_NATIVE_IMAGE) {
+            throw new InternalError("Can only serialize saved properties in HotSpot runtime");
+        }
+        Map<String, String> props = Services.getSavedProperties();
+
+        // Compute size of output on the assumption that
+        // all system properties have ASCII names and values
+        int estimate = 4;
+        for (Map.Entry<String, String> e : props.entrySet()) {
+            String name = e.getKey();
+            String value = e.getValue();
+            estimate += (2 + (name.length())) + (2 + (value.length()));
+        }
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate);
+        DataOutputStream out = new DataOutputStream(baos);
+        out.writeInt(props.size());
+        for (Map.Entry<String, String> e : props.entrySet()) {
+            String name = e.getKey();
+            String value = e.getValue();
+            out.writeUTF(name);
+            out.writeUTF(value);
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * Initialized the {@linkplain #getSavedProperties() saved system properties} in the JVMCI
+     * shared library from the {@linkplain #serializeSavedProperties() serialized saved properties}
+     * in the HotSpot runtime.
+     */
+    @VMEntryPoint
+    private static void initializeSavedProperties(byte[] serializedProperties) throws IOException {
+        if (!IS_IN_NATIVE_IMAGE) {
+            throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
+        }
+        DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties));
+        Map<String, String> props = new HashMap<>(in.readInt());
+        while (in.available() != 0) {
+            String name = in.readUTF();
+            String value = in.readUTF();
+            props.put(name, value);
+        }
+        savedProperties = Collections.unmodifiableMap(props);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/VMEntryPoint.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.services;
+
+/**
+ * Marker interface for methods which are called from the JVM.
+ */
+@interface VMEntryPoint {
+    /**
+     * An optional comment describing the caller.
+     */
+    String value() default "";
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Fri May 03 14:59:32 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
@@ -313,7 +313,7 @@
             case Double:
                 return SPARCKind.DOUBLE;
             default:
-                throw new IllegalArgumentException("Unknown JavaKind: " + javaKind);
+                return null;
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java	Fri May 03 14:59:32 2019 -0400
@@ -22,11 +22,11 @@
  */
 /*
  @ApiInfo(
- group="Graal SDK"
+ group="GraalVM SDK"
  )
  */
 /**
- * The Graal-SDK collections package contains memory efficient data structures.
+ * The GraalVM SDK collections package contains memory efficient data structures.
  *
  * @see jdk.internal.vm.compiler.collections.EconomicMap
  * @see jdk.internal.vm.compiler.collections.EconomicSet
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java	Fri May 03 14:59:32 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.
+ */
+
+
+package jdk.internal.vm.compiler.libgraal;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.services.Services;
+
+/**
+ * JDK13+ version of {@code LibGraal}.
+ */
+public class LibGraal {
+
+    public static boolean isAvailable() {
+        return isCurrentRuntime() || libgraalIsolate != 0L;
+    }
+
+    public static boolean isCurrentRuntime() {
+        return Services.IS_IN_NATIVE_IMAGE;
+    }
+
+    public static long getIsolate() {
+        if (isCurrentRuntime() || !isAvailable()) {
+            throw new IllegalStateException();
+        }
+        return libgraalIsolate;
+    }
+
+    public static long getIsolateThread() {
+        if (isCurrentRuntime()) {
+            throw new IllegalStateException();
+        }
+        return CURRENT_ISOLATE_THREAD.get();
+    }
+
+    @SuppressWarnings("unused")
+    public static long[] registerNativeMethods(HotSpotJVMCIRuntime runtime, Class<?> clazz) {
+        if (clazz.isPrimitive()) {
+            throw new IllegalArgumentException();
+        }
+        if (isCurrentRuntime() || !isAvailable()) {
+            throw new IllegalStateException();
+        }
+        // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623
+        // return runtime.registerNativeMethods(clazz);
+        throw new IllegalStateException("Requires JDK-8220623");
+    }
+
+    @SuppressWarnings("unused")
+    public static long translate(HotSpotJVMCIRuntime runtime, Object obj) {
+        if (!isAvailable()) {
+            throw new IllegalStateException();
+        }
+        // return runtime.translate(obj);
+        throw new IllegalStateException("Requires JDK-8220623");
+    }
+
+    @SuppressWarnings("unused")
+    public static <T> T unhand(HotSpotJVMCIRuntime runtime, Class<T> type, long handle) {
+        if (!isAvailable()) {
+            throw new IllegalStateException();
+        }
+        // return runtime.unhand(type, handle);
+        throw new IllegalStateException("Requires JDK-8220623");
+    }
+
+    private static final ThreadLocal<Long> CURRENT_ISOLATE_THREAD = new ThreadLocal<>() {
+        @Override
+        protected Long initialValue() {
+            return attachThread(libgraalIsolate);
+        }
+    };
+
+    private static final long libgraalIsolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal();
+
+    private static long initializeLibgraal() {
+        try {
+            // Initialize JVMCI to ensure JVMCI opens its packages to
+            // Graal otherwise the call to HotSpotJVMCIRuntime.runtime()
+            // below will fail on JDK13+.
+            Services.initializeJVMCI();
+
+            // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623
+            // HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+            // long[] nativeInterface = runtime.registerNativeMethods(LibGraal.class);
+            // return nativeInterface[1];
+            return 0L;
+        } catch (UnsupportedOperationException e) {
+            return 0L;
+        }
+    }
+
+    /**
+     * Attaches the current thread to a thread in {@code isolate}.
+     *
+     * @param isolate
+     */
+    private static native long attachThread(long isolate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+
+package jdk.internal.vm.compiler.libgraal;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Facilities for encoding/decoding a set of options to/from a byte array.
+ */
+public final class OptionsEncoder {
+
+    private OptionsEncoder() {
+    }
+
+    /**
+     * Determines if {@code value} is supported by {@link #encode(Map)}.
+     */
+    public static boolean isValueSupported(Object value) {
+        if (value == null) {
+            return false;
+        }
+        Class<?> valueClass = value.getClass();
+        return valueClass == Boolean.class ||
+                        valueClass == Byte.class ||
+                        valueClass == Short.class ||
+                        valueClass == Character.class ||
+                        valueClass == Integer.class ||
+                        valueClass == Long.class ||
+                        valueClass == Float.class ||
+                        valueClass == Double.class ||
+                        valueClass == String.class ||
+                        value.getClass().isEnum();
+    }
+
+    /**
+     * Encodes {@code options} into a byte array.
+     *
+     * @throws IllegalArgumentException if any value in {@code options} is not
+     *             {@linkplain #isValueSupported(Object) supported}
+     */
+    public static byte[] encode(final Map<String, Object> options) {
+        try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) {
+            try (DataOutputStream out = new DataOutputStream(baout)) {
+                out.writeInt(options.size());
+                for (Map.Entry<String, Object> e : options.entrySet()) {
+                    final String key = e.getKey();
+                    out.writeUTF(key);
+                    final Object value = e.getValue();
+                    final Class<?> valueClz = value.getClass();
+                    if (valueClz == Boolean.class) {
+                        out.writeByte('Z');
+                        out.writeBoolean((Boolean) value);
+                    } else if (valueClz == Byte.class) {
+                        out.writeByte('B');
+                        out.writeByte((Byte) value);
+                    } else if (valueClz == Short.class) {
+                        out.writeByte('S');
+                        out.writeShort((Short) value);
+                    } else if (valueClz == Character.class) {
+                        out.writeByte('C');
+                        out.writeChar((Character) value);
+                    } else if (valueClz == Integer.class) {
+                        out.writeByte('I');
+                        out.writeInt((Integer) value);
+                    } else if (valueClz == Long.class) {
+                        out.writeByte('J');
+                        out.writeLong((Long) value);
+                    } else if (valueClz == Float.class) {
+                        out.writeByte('F');
+                        out.writeFloat((Float) value);
+                    } else if (valueClz == Double.class) {
+                        out.writeByte('D');
+                        out.writeDouble((Double) value);
+                    } else if (valueClz == String.class) {
+                        out.writeByte('U');
+                        out.writeUTF((String) value);
+                    } else if (valueClz.isEnum()) {
+                        out.writeByte('U');
+                        out.writeUTF(((Enum<?>) value).name());
+                    } else {
+                        throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", key, value, valueClz));
+                    }
+                }
+            }
+            return baout.toByteArray();
+        } catch (IOException ioe) {
+            throw new IllegalArgumentException(ioe);
+        }
+    }
+
+    /**
+     * Decodes {@code input} into a name/value map.
+     *
+     * @throws IllegalArgumentException if {@code input} cannot be decoded
+     */
+    public static Map<String, Object> decode(byte[] input) {
+        Map<String, Object> res = new HashMap<>();
+        try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(input))) {
+            final int size = in.readInt();
+            for (int i = 0; i < size; i++) {
+                final String key = in.readUTF();
+                final Object value;
+                final byte type = in.readByte();
+                switch (type) {
+                    case 'Z':
+                        value = in.readBoolean();
+                        break;
+                    case 'B':
+                        value = in.readByte();
+                        break;
+                    case 'S':
+                        value = in.readShort();
+                        break;
+                    case 'C':
+                        value = in.readChar();
+                        break;
+                    case 'I':
+                        value = in.readInt();
+                        break;
+                    case 'J':
+                        value = in.readLong();
+                        break;
+                    case 'F':
+                        value = in.readFloat();
+                        break;
+                    case 'D':
+                        value = in.readDouble();
+                        break;
+                    case 'U':
+                        value = in.readUTF();
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Unsupported value type: " + Integer.toHexString(type));
+                }
+                res.put(key, value);
+            }
+        } catch (IOException ioe) {
+            throw new IllegalArgumentException(ioe);
+        }
+        return res;
+    }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java	Fri May 03 14:59:32 2019 -0400
@@ -22,7 +22,7 @@
  */
 /*
  @ApiInfo(
- group="Graal SDK"
+ group="GraalVM SDK"
  )
  */
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.asm.aarch64.test;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.junit.Assume.assumeTrue;
+
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.asm.test.AssemblerTest;
+import org.graalvm.compiler.code.CompilationResult;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.JavaKind;
+
+public class AArch64BitCountAssemblerTest extends AssemblerTest {
+    @Before
+    public void checkAArch64() {
+        assumeTrue("skipping non AArch64 specific test", codeCache.getTarget().arch instanceof AArch64);
+    }
+
+    public interface AArch64CodeGenTestCase {
+        CodeGenTest create();
+
+        int getExpected();
+    }
+
+    private class AArch64BitCountCodeGenTestCase<T extends Number> implements AArch64CodeGenTestCase {
+        final T value;
+        final int size;
+
+        AArch64BitCountCodeGenTestCase(T x, int size) {
+            assert x instanceof Integer || x instanceof Long;
+            this.value = x;
+            this.size = size;
+        }
+
+        T getValue() {
+            return value;
+        }
+
+        @Override
+        public CodeGenTest create() {
+            return (CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) -> {
+                AArch64MacroAssembler masm = new AArch64MacroAssembler(target);
+                Register dst = registerConfig.getReturnRegister(JavaKind.Int);
+                Register src = asRegister(cc.getArgument(0));
+                RegisterArray registers = registerConfig.filterAllocatableRegisters(AArch64Kind.V64_BYTE, registerConfig.getAllocatableRegisters());
+                masm.popcnt(size, dst, src, registers.get(registers.size() - 1));
+                masm.ret(AArch64.lr);
+                return masm.close(true);
+            };
+        }
+
+        @Override
+        public int getExpected() {
+            if (value instanceof Integer) {
+                return Integer.bitCount((Integer) value);
+            } else if (value instanceof Long) {
+                return Long.bitCount((Long) value);
+            }
+            return -1;
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testBitCount() {
+        AArch64CodeGenTestCase[] tests = {
+                        new AArch64BitCountCodeGenTestCase<>(0, JavaKind.Int.getByteCount() * Byte.SIZE),
+                        new AArch64BitCountCodeGenTestCase<>(1522767384, JavaKind.Int.getByteCount() * Byte.SIZE),
+                        new AArch64BitCountCodeGenTestCase<>(0L, JavaKind.Long.getByteCount() * Byte.SIZE),
+                        new AArch64BitCountCodeGenTestCase<>(81985529216486895L, JavaKind.Long.getByteCount() * Byte.SIZE),
+        };
+
+        assertReturn("intStub", tests[0].create(), tests[0].getExpected(), ((AArch64BitCountCodeGenTestCase<Integer>) tests[0]).getValue());
+        assertReturn("intStub", tests[1].create(), tests[1].getExpected(), ((AArch64BitCountCodeGenTestCase<Integer>) tests[1]).getValue());
+        assertReturn("longStub", tests[2].create(), tests[2].getExpected(), ((AArch64BitCountCodeGenTestCase<Long>) tests[2]).getValue());
+        assertReturn("longStub", tests[3].create(), tests[3].getExpected(), ((AArch64BitCountCodeGenTestCase<Long>) tests[3]).getValue());
+    }
+
+    @SuppressWarnings("unused")
+    public static int intStub(int x) {
+        return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public static int longStub(long x) {
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64InstructionEncodingTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.asm.aarch64.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.nio.ByteBuffer;
+
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.test.GraalTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.runtime.JVMCI;
+
+public class AArch64InstructionEncodingTest extends GraalTest {
+    @Before
+    public void checkAArch64() {
+        assumeTrue("skipping non AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64);
+    }
+
+    private abstract class AArch64InstructionEncodingTestCase {
+        private byte[] actual;
+        private byte[] expected;
+        TestProtectedAssembler assembler;
+
+        AArch64InstructionEncodingTestCase(int expected) {
+            this.expected = ByteBuffer.allocate(Integer.BYTES).putInt(expected).array();
+            TargetDescription target = JVMCI.getRuntime().getHostJVMCIBackend().getTarget();
+            assembler = new TestProtectedAssembler(target);
+        }
+
+        int getExpected() {
+            return ByteBuffer.wrap(expected).getInt();
+        }
+
+        int getActual() {
+            return ByteBuffer.wrap(actual).getInt();
+        }
+
+        void closeAssembler() {
+            this.actual = assembler.close(true);
+        }
+    }
+
+    private class CntEncodingTestCase extends AArch64InstructionEncodingTestCase {
+        CntEncodingTestCase(int expected, int size, Register dst, Register src) {
+            super(expected);
+            assembler.cnt(size, dst, src);
+            closeAssembler();
+        }
+    }
+
+    private class AddvEncodingTestCase extends AArch64InstructionEncodingTestCase {
+        AddvEncodingTestCase(int expected, int size, AArch64Assembler.SIMDElementSize laneWidth, Register dst, Register src) {
+            super(expected);
+            assembler.addv(size, laneWidth, dst, src);
+            closeAssembler();
+        }
+    }
+
+    private class UmovEncodingTestCase extends AArch64InstructionEncodingTestCase {
+        UmovEncodingTestCase(int expected, int size, Register dst, int srcIdx, Register src) {
+            super(expected);
+            assembler.umov(size, dst, srcIdx, src);
+            closeAssembler();
+        }
+    }
+
+    private static final int invalidInstructionCode = 0x00000000;
+
+    private void assertWrapper(AArch64InstructionEncodingTestCase testCase) {
+        assertDeepEquals(testCase.getActual(), testCase.getExpected());
+    }
+
+    @Test
+    public void testCnt() {
+        assertWrapper(new CntEncodingTestCase(0x0058200e, 64, AArch64.v0, AArch64.v0));
+        assertWrapper(new CntEncodingTestCase(0x3f58204e, 128, AArch64.v31, AArch64.v1));
+    }
+
+    @Test(expected = AssertionError.class)
+    @SuppressWarnings("unused")
+    public void testCntWithInvalidDataSize() {
+        new CntEncodingTestCase(invalidInstructionCode, 32, AArch64.v5, AArch64.v5);
+    }
+
+    @Test
+    public void testAddv() {
+        assertWrapper(new AddvEncodingTestCase(0x20b8310e, 64, AArch64Assembler.SIMDElementSize.Byte, AArch64.v0, AArch64.v1));
+        assertWrapper(new AddvEncodingTestCase(0x42b8314e, 128, AArch64Assembler.SIMDElementSize.Byte, AArch64.v2, AArch64.v2));
+        assertWrapper(new AddvEncodingTestCase(0xd2ba710e, 64, AArch64Assembler.SIMDElementSize.HalfWord, AArch64.v18, AArch64.v22));
+        assertWrapper(new AddvEncodingTestCase(0x77ba714e, 128, AArch64Assembler.SIMDElementSize.HalfWord, AArch64.v23, AArch64.v19));
+        assertWrapper(new AddvEncodingTestCase(0x18bbb14e, 128, AArch64Assembler.SIMDElementSize.Word, AArch64.v24, AArch64.v24));
+    }
+
+    @Test(expected = AssertionError.class)
+    @SuppressWarnings("unused")
+    public void testAddvWithInvalidSizeLaneCombo() {
+        new AddvEncodingTestCase(invalidInstructionCode, 64, AArch64Assembler.SIMDElementSize.Word, AArch64.v0, AArch64.v1);
+    }
+
+    @Test(expected = AssertionError.class)
+    @SuppressWarnings("unused")
+    public void testAddvWithInvalidDataSize() {
+        new AddvEncodingTestCase(invalidInstructionCode, 32, AArch64Assembler.SIMDElementSize.Word, AArch64.v0, AArch64.v1);
+    }
+
+    @Test(expected = AssertionError.class)
+    @SuppressWarnings("unused")
+    public void testAddvWithInvalidLane() {
+        new AddvEncodingTestCase(invalidInstructionCode, 128, AArch64Assembler.SIMDElementSize.DoubleWord, AArch64.v0, AArch64.v1);
+    }
+
+    @Test
+    public void testUmov() {
+        assertWrapper(new UmovEncodingTestCase(0x1f3c084e, 64, AArch64.r31, 0, AArch64.v0));
+        assertWrapper(new UmovEncodingTestCase(0xe13f184e, 64, AArch64.r1, 1, AArch64.v31));
+
+        assertWrapper(new UmovEncodingTestCase(0x5d3c040e, 32, AArch64.r29, 0, AArch64.v2));
+        assertWrapper(new UmovEncodingTestCase(0x833f1c0e, 32, AArch64.r3, 3, AArch64.v28));
+
+        assertWrapper(new UmovEncodingTestCase(0x4b3d020e, 16, AArch64.r11, 0, AArch64.v10));
+        assertWrapper(new UmovEncodingTestCase(0x893d1e0e, 16, AArch64.r9, 7, AArch64.v12));
+
+        assertWrapper(new UmovEncodingTestCase(0x0d3d010e, 8, AArch64.r13, 0, AArch64.v8));
+        assertWrapper(new UmovEncodingTestCase(0xc73d1f0e, 8, AArch64.r7, 15, AArch64.v14));
+    }
+
+    @Test(expected = AssertionError.class)
+    @SuppressWarnings("unused")
+    public void testUmovInvalidSrcIdx() {
+        new UmovEncodingTestCase(invalidInstructionCode, 64, AArch64.r0, 2, AArch64.v0);
+    }
+
+    @Test(expected = GraalError.class)
+    @SuppressWarnings("unused")
+    public void testUmovInvalidDataSize() {
+        new UmovEncodingTestCase(invalidInstructionCode, 31, AArch64.r0, 3, AArch64.v0);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Fri May 03 14:59:32 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
@@ -549,4 +549,19 @@
     public void ensureUniquePC() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void cnt(int size, Register dst, Register src) {
+        super.cnt(size, dst, src);
+    }
+
+    @Override
+    public void addv(int size, SIMDElementSize laneWidth, Register dst, Register src) {
+        super.addv(size, laneWidth, dst, src);
+    }
+
+    @Override
+    public void umov(int size, Register dst, int srcIdx, Register src) {
+        super.umov(size, dst, srcIdx, src);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Fri May 03 14:59:32 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.
  * Copyright (c) 2018, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -25,9 +25,15 @@
 
 package org.graalvm.compiler.asm.aarch64;
 
+import static jdk.vm.ci.aarch64.AArch64.CPU;
+import static jdk.vm.ci.aarch64.AArch64.SIMD;
 import static jdk.vm.ci.aarch64.AArch64.cpuRegisters;
+import static jdk.vm.ci.aarch64.AArch64.r0;
+import static jdk.vm.ci.aarch64.AArch64.sp;
+import static jdk.vm.ci.aarch64.AArch64.zr;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDV;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADRP;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND;
@@ -44,6 +50,7 @@
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CNT;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSEL;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSINC;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG;
@@ -107,27 +114,24 @@
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUB;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUBS;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SWP;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBNZ;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBZ;
-import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBNZ;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UBFM;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UDIV;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UMOV;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP32;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP64;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General32;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.General64;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.floatFromSize;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.generalFromSize;
-import static jdk.vm.ci.aarch64.AArch64.CPU;
-import static jdk.vm.ci.aarch64.AArch64.SIMD;
-import static jdk.vm.ci.aarch64.AArch64.r0;
-import static jdk.vm.ci.aarch64.AArch64.sp;
-import static jdk.vm.ci.aarch64.AArch64.zr;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.simdFromSize;
 
 import java.util.Arrays;
 
 import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 import org.graalvm.compiler.debug.GraalError;
 
 import jdk.vm.ci.aarch64.AArch64;
@@ -371,15 +375,41 @@
     }
 
     /**
+     * Enumeration of all different lane types of SIMD register.
+     *
+     * Byte(B):8b/lane; HalfWord(H):16b/lane; Word(S):32b/lane; DoubleWord(D):64b/lane.
+     */
+    public enum SIMDElementSize {
+        Byte(0, 8),
+        HalfWord(1, 16),
+        Word(2, 32),
+        DoubleWord(3, 64);
+
+        public final int encoding;
+        public final int nbits;
+
+        SIMDElementSize(int encoding, int nbits) {
+            this.encoding = encoding;
+            this.nbits = nbits;
+        }
+    }
+
+    /**
      * Enumeration of all different instruction kinds: General32/64 are the general instructions
      * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for
-     * the 32/64bit float operations
+     * the 32/64bit float operations. SIMDByte/HalfWord/Word/DoubleWord is the encoding for SIMD
+     * instructions
      */
     protected enum InstructionType {
         General32(0b00 << 30, 32, true),
         General64(0b10 << 30, 64, true),
         FP32(0x00000000, 32, false),
-        FP64(0x00400000, 64, false);
+        FP64(0x00400000, 64, false),
+
+        SIMDByte(0x01, 8, false),
+        SIMDHalfWord(0x02, 16, false),
+        SIMDWord(0x04, 32, false),
+        SIMDDoubleWord(0x08, 64, false);
 
         public final int encoding;
         public final int width;
@@ -401,6 +431,20 @@
             return size == 32 ? FP32 : FP64;
         }
 
+        public static InstructionType simdFromSize(int size) {
+            switch (size) {
+                case 8:
+                    return SIMDByte;
+                case 16:
+                    return SIMDHalfWord;
+                case 32:
+                    return SIMDWord;
+                case 64:
+                    return SIMDDoubleWord;
+                default:
+                    throw GraalError.shouldNotReachHere();
+            }
+        }
     }
 
     private static final int ImmediateOffset = 10;
@@ -493,6 +537,10 @@
     private static final int LDADDAcquireOffset = 23;
     private static final int LDADDReleaseOffset = 22;
 
+    private static final int SIMDImm5Offset = 16;
+    private static final int SIMDQBitOffset = 30;
+    private static final int SIMDSizeOffset = 22;
+
     /**
      * Encoding for all instructions.
      */
@@ -611,7 +659,7 @@
         FCSEL(0x1E200C00),
 
         INS(0x4e081c00),
-        UMOV(0x4e083c00),
+        UMOV(0x0e003c00),
 
         CNT(0xe205800),
         USRA(0x6f001400),
@@ -626,7 +674,9 @@
         MRS(0xD5300000),
         MSR(0xD5100000),
 
-        BLR_NATIVE(0xc0000000);
+        BLR_NATIVE(0xc0000000),
+
+        ADDV(0x0e31b800);
 
         public final int encoding;
 
@@ -2957,4 +3007,45 @@
         }
     }
 
+    /**
+     * dst[0...n] = countBitCountOfEachByte(src[0...n]), n = size/8.
+     *
+     * @param size register size. Has to be 64 or 128.
+     * @param dst SIMD register. Should not be null.
+     * @param src SIMD register. Should not be null.
+     */
+    public void cnt(int size, Register dst, Register src) {
+        assert 64 == size || 128 == size : "Invalid size for cnt";
+        emitInt((size >> 7) << SIMDQBitOffset | CNT.encoding | rd(dst) | rs1(src));
+    }
+
+    /**
+     * dst = src[0] + ....+ src[n].
+     *
+     * @param size register size. Has to be 64 or 128.
+     * @param laneWidth the width that SIMD register is treated as different lanes with.
+     * @param dst SIMD register. Should not be null.
+     * @param src SIMD register. Should not be null.
+     */
+    public void addv(int size, SIMDElementSize laneWidth, Register dst, Register src) {
+        assert 64 == size || 128 == size : "Invalid size for addv";
+        assert SIMDElementSize.DoubleWord != laneWidth : "Invalid lane width for addv";
+        assert 64 != size || SIMDElementSize.Word != laneWidth : "Invalid size and lane combination for addv";
+        emitInt((size >> 7) << SIMDQBitOffset | laneWidth.encoding << SIMDSizeOffset | ADDV.encoding | rd(dst) | rs1(src));
+    }
+
+    /**
+     * dst = src[srcIdx].
+     *
+     * @param size register size. Can be 8, 16, 32 or 64.
+     * @param dst general purpose register. Should not be null or zero-register.
+     * @param srcIdx lane index of source register that dest data is from.
+     * @param src SIMD register. Should not be null.
+     */
+    public void umov(int size, Register dst, int srcIdx, Register src) {
+        assert (srcIdx + 1) * size <= 128 : "Invalid src vectRegister index";
+        InstructionType simdDataType = simdFromSize(size);
+        int imm5 = simdDataType.encoding | srcIdx << Integer.numberOfTrailingZeros(simdDataType.encoding) + 1;
+        emitInt((size >> 6) << SIMDQBitOffset | imm5 << SIMDImm5Offset | UMOV.encoding | rd(dst) | rs1(src));
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Fri May 03 14:59:32 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
@@ -1437,7 +1437,7 @@
             int offset = label.position() - position();
             super.adr(dst, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             // Encode condition flag so that we know how to patch the instruction later
             emitInt(PatchLabelKind.ADR.encoding | dst.encoding << PatchLabelKind.INFORMATION_OFFSET);
         }
@@ -1456,7 +1456,7 @@
             int offset = label.position() - position();
             super.cbnz(size, cmp, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1);
             int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET;
             // Encode condition flag so that we know how to patch the instruction later
@@ -1477,7 +1477,7 @@
             int offset = label.position() - position();
             super.cbz(size, cmp, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 1);
             int sizeEncoding = (size == 64 ? 1 : 0) << PatchLabelKind.INFORMATION_OFFSET;
             // Encode condition flag so that we know how to patch the instruction later
@@ -1498,7 +1498,7 @@
             int offset = label.position() - position();
             super.tbnz(cmp, uimm6, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET;
             int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6);
             emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding);
@@ -1518,7 +1518,7 @@
             int offset = label.position() - position();
             super.tbz(cmp, uimm6, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET;
             int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6);
             emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding);
@@ -1537,7 +1537,7 @@
             int offset = label.position() - position();
             super.b(condition, offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             // Encode condition flag so that we know how to patch the instruction later
             emitInt(PatchLabelKind.BRANCH_CONDITIONALLY.encoding | condition.encoding << PatchLabelKind.INFORMATION_OFFSET);
         }
@@ -1565,7 +1565,7 @@
             int offset = label.position() - position();
             super.b(offset);
         } else {
-            label.addPatchAt(position());
+            label.addPatchAt(position(), this);
             emitInt(PatchLabelKind.BRANCH_UNCONDITIONALLY.encoding);
         }
     }
@@ -1783,6 +1783,23 @@
         a.lea(this, d);
     }
 
+    /**
+     * Count the set bits of src register.
+     *
+     * @param size src register size. Has to be 32 or 64.
+     * @param dst general purpose register. Should not be null or zero-register.
+     * @param src general purpose register. Should not be null.
+     * @param vreg SIMD register. Should not be null.
+     */
+    public void popcnt(int size, Register dst, Register src, Register vreg) {
+        assert 32 == size || 64 == size : "Invalid data size";
+        fmov(size, vreg, src);
+        final int fixedSize = 64;
+        cnt(fixedSize, vreg, vreg);
+        addv(fixedSize, SIMDElementSize.Byte, vreg, vreg);
+        umov(fixedSize, dst, 0, vreg);
+    }
+
     public interface MacroInstruction {
         void patch(int codePos, int relative, byte[] code);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Fri May 03 14:59:32 2019 -0400
@@ -75,7 +75,6 @@
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.debug.GraalError;
 
@@ -1882,7 +1881,7 @@
             // is the same however, seems to be rather unlikely case.
             // Note: use jccb() if label to be bound is very close to get
             // an 8-bit displacement
-            l.addPatchAt(position());
+            l.addPatchAt(position(), this);
             emitByte(0x0F);
             emitByte(0x80 | cc.getValue());
             emitInt(0);
@@ -1900,7 +1899,7 @@
             emitByte(0x70 | cc.getValue());
             emitByte((int) ((disp - shortSize) & 0xFF));
         } else {
-            l.addPatchAt(position());
+            l.addPatchAt(position(), this);
             emitByte(0x70 | cc.getValue());
             emitByte(0);
         }
@@ -1929,7 +1928,7 @@
             // the forward jump will not run beyond 256 bytes, use jmpb to
             // force an 8-bit displacement.
 
-            l.addPatchAt(position());
+            l.addPatchAt(position(), this);
             emitByte(0xE9);
             emitInt(0);
         }
@@ -1950,14 +1949,13 @@
     public final void jmpb(Label l) {
         if (l.isBound()) {
             int shortSize = 2;
-            int entry = l.position();
-            assert isByte((entry - position()) + shortSize) : "Dispacement too large for a short jmp";
-            long offs = entry - position();
+            // Displacement is relative to byte just after jmpb instruction
+            int displacement = l.position() - position() - shortSize;
+            GraalError.guarantee(isByte(displacement), "Displacement too large to be encoded as a byte: %d", displacement);
             emitByte(0xEB);
-            emitByte((int) ((offs - shortSize) & 0xFF));
+            emitByte(displacement & 0xFF);
         } else {
-
-            l.addPatchAt(position());
+            l.addPatchAt(position(), this);
             emitByte(0xEB);
             emitByte(0);
         }
@@ -3397,9 +3395,7 @@
              * Since a wrongly patched short branch can potentially lead to working but really bad
              * behaving code we should always fail with an exception instead of having an assert.
              */
-            if (!NumUtil.isByte(imm8)) {
-                throw new InternalError("branch displacement out of range: " + imm8);
-            }
+            GraalError.guarantee(isByte(imm8), "Displacement too large to be encoded as a byte: %d", imm8);
             emitByte(imm8, branch + 1);
 
         } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Fri May 03 14:59:32 2019 -0400
@@ -1851,7 +1851,7 @@
     }
 
     protected int patchUnbound(Label label) {
-        label.addPatchAt(position());
+        label.addPatchAt(position(), this);
         return 0;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java	Fri May 03 14:59:32 2019 -0400
@@ -54,6 +54,11 @@
     private List<LabelHint> jumpDisplacementHints;
 
     /**
+     * Labels with instructions to be patched when it is {@linkplain Label#bind bound}.
+     */
+    Label labelsWithPatches;
+
+    /**
      * Backing code buffer.
      */
     private final Buffer codeBuffer;
@@ -151,13 +156,26 @@
      * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true}
      */
     public byte[] close(boolean trimmedCopy) {
+        checkAndClearLabelsWithPatches();
         return codeBuffer.close(trimmedCopy);
     }
 
+    private void checkAndClearLabelsWithPatches() throws InternalError {
+        Label label = labelsWithPatches;
+        while (label != null) {
+            if (label.patchPositions != null) {
+                throw new InternalError("Label used by instructions at following offsets has not been bound: " + label.patchPositions);
+            }
+            Label next = label.nextWithPatches;
+            label.nextWithPatches = null;
+            label = next;
+        }
+        labelsWithPatches = null;
+    }
+
     public void bind(Label l) {
         assert !l.isBound() : "can bind label only once";
-        l.bind(position());
-        l.patchInstructions(this);
+        l.bind(position(), this);
     }
 
     public abstract void align(int modulus);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java	Fri May 03 14:59:32 2019 -0400
@@ -35,10 +35,15 @@
     private int blockId = -1;
 
     /**
-     * References to instructions that jump to this unresolved label. These instructions need to be
-     * patched when the label is bound using the {@link #patchInstructions(Assembler)} method.
+     * Positions of instructions that jump to this unresolved label. These instructions are patched
+     * when the label is bound.
      */
-    private ArrayList<Integer> patchPositions = null;
+    ArrayList<Integer> patchPositions;
+
+    /**
+     * Link in list of labels with instructions to be patched.
+     */
+    Label nextWithPatches;
 
     /**
      * Returns the position of this label in the code buffer.
@@ -62,36 +67,33 @@
     }
 
     /**
-     * Binds the label to the specified position.
-     *
-     * @param pos the position
+     * Binds the label to {@code pos} and patches all instructions added by
+     * {@link #addPatchAt(int, Assembler)}.
      */
-    protected void bind(int pos) {
+    protected void bind(int pos, Assembler asm) {
+        assert pos >= 0;
         this.position = pos;
-        assert isBound();
+        if (patchPositions != null) {
+            for (int i = 0; i < patchPositions.size(); ++i) {
+                asm.patchJumpTarget(patchPositions.get(i), position);
+            }
+            patchPositions = null;
+        }
     }
 
     public boolean isBound() {
         return position >= 0;
     }
 
-    public void addPatchAt(int branchLocation) {
+    public void addPatchAt(int branchLocation, Assembler asm) {
         assert !isBound() : "Label is already bound " + this + " " + branchLocation + " at position " + position;
         if (patchPositions == null) {
             patchPositions = new ArrayList<>(2);
+            nextWithPatches = asm.labelsWithPatches;
+            asm.labelsWithPatches = this;
         }
         patchPositions.add(branchLocation);
-    }
 
-    protected void patchInstructions(Assembler masm) {
-        assert isBound() : "Label should be bound";
-        if (patchPositions != null) {
-            int target = position;
-            for (int i = 0; i < patchPositions.size(); ++i) {
-                int pos = patchPositions.get(i);
-                masm.patchJumpTarget(pos, target);
-            }
-        }
     }
 
     public void reset() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java	Fri May 03 14:59:32 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
@@ -24,10 +24,9 @@
 
 package org.graalvm.compiler.core.aarch64.test;
 
-import static org.junit.Assume.assumeTrue;
-
-import java.util.function.Predicate;
-
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.Value;
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.lir.LIR;
@@ -48,9 +47,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import jdk.vm.ci.aarch64.AArch64;
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.Value;
+import java.util.function.Predicate;
+
+import static org.junit.Assume.assumeTrue;
 
 public class AArch64TestBitAndBranchTest extends LIRTest {
     private static final Predicate<LIRInstruction> checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp);
@@ -62,7 +61,7 @@
     }
 
     public static long testBit42Snippet(long a, long b, long c) {
-        if ((a & (1 << 42)) == 0) {
+        if ((a & (1L << 42)) == 0) {
             return b;
         } else {
             return c;
@@ -71,12 +70,12 @@
 
     @Test
     public void testBit42() {
-        test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE);
-        test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE);
+        test("testBit42Snippet", 1L << 42, Long.MAX_VALUE, Long.MIN_VALUE);
+        test("testBit42Snippet", ~(1L << 42), Long.MAX_VALUE, Long.MIN_VALUE);
         checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1);
     }
 
-    private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2);
+    private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2) - 10, 2);
 
     /**
      * Tests the graceful case, where the estimation for
@@ -99,7 +98,7 @@
         checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1);
     }
 
-    private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8);
+    private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2) - 10, 8);
 
     /**
      * Tests the case, where the estimation for
@@ -122,6 +121,73 @@
         checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1);
     }
 
+    private static final float trueTarget = Float.MAX_VALUE;
+    private static final float falseTarget = Float.MIN_VALUE;
+
+    public static float testLessThanZeroSnippet(long a, long b) {
+        if (b + a - b < 0) {
+            return trueTarget - a;
+        } else {
+            return falseTarget + a;
+        }
+    }
+
+    @Test
+    public void testLessThanZero() {
+        test("testLessThanZeroSnippet", 1L, 777L);
+        test("testLessThanZeroSnippet", 0L, 777L);
+        test("testLessThanZeroSnippet", -1L, 777L);
+        checkLIR("testLessThanZeroSnippet", checkForBitTestAndBranchOp, 1);
+    }
+
+    public static float testLessThanEqualZeroSnippet(long a) {
+        if (a <= 0) {
+            return trueTarget - a;
+        } else {
+            return falseTarget + a;
+        }
+    }
+
+    @Test
+    public void testLessThanEqualZero() {
+        test("testLessThanEqualZeroSnippet", 1L);
+        test("testLessThanEqualZeroSnippet", 0L);
+        test("testLessThanEqualZeroSnippet", -1L);
+        checkLIR("testLessThanEqualZeroSnippet", checkForBitTestAndBranchOp, 0);
+    }
+
+    public static float testGreaterThanZeroSnippet(int a) {
+        if (a > 0) {
+            return trueTarget - a;
+        } else {
+            return falseTarget + a;
+        }
+    }
+
+    @Test
+    public void testGreaterThanZero() {
+        test("testGreaterThanZeroSnippet", 1);
+        test("testGreaterThanZeroSnippet", 0);
+        test("testGreaterThanZeroSnippet", -1);
+        checkLIR("testGreaterThanZeroSnippet", checkForBitTestAndBranchOp, 0);
+    }
+
+    public static float testGreaterThanEqualZeroSnippet(int a) {
+        if (a >= 0) {
+            return trueTarget - a;
+        } else {
+            return falseTarget + a;
+        }
+    }
+
+    @Test
+    public void testGreaterThanEqualZero() {
+        test("testGreaterThanEqualZeroSnippet", 1);
+        test("testGreaterThanEqualZeroSnippet", 0);
+        test("testGreaterThanEqualZeroSnippet", -1);
+        checkLIR("testGreaterThanEqualZeroSnippet", checkForBitTestAndBranchOp, 1);
+    }
+
     private static class LargeOpSpec extends LIRTestSpecification {
         private final int n;
         private final int nopCount;
@@ -172,7 +238,9 @@
 
     public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> {
         @Override
-        protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) {
+        protected void run(
+                        TargetDescription target, LIRGenerationResult lirGenRes,
+                        PreAllocationOptimizationContext context) {
             lir = lirGenRes.getLIR();
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Fri May 03 14:59:32 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
@@ -32,6 +32,7 @@
 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
+import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.POPCNT;
 
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.core.common.LIRKind;
@@ -432,27 +433,30 @@
 
     @Override
     public Value emitBitCount(Value operand) {
-        throw GraalError.unimplemented("AArch64 ISA does not offer way to implement this more efficiently than a simple Java algorithm.");
+        assert ((AArch64Kind) operand.getPlatformKind()).isInteger();
+        Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(AArch64Kind.DWORD));
+        getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), POPCNT, result, asAllocatable(operand)));
+        return result;
     }
 
     @Override
     public Value emitBitScanReverse(Value value) {
         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
-        getLIRGen().append(new AArch64BitManipulationOp(BSR, result, asAllocatable(value)));
+        getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), BSR, result, asAllocatable(value)));
         return result;
     }
 
     @Override
     public Value emitCountLeadingZeros(Value value) {
         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
-        getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value)));
+        getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), CLZ, result, asAllocatable(value)));
         return result;
     }
 
     @Override
     public Value emitCountTrailingZeros(Value value) {
         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
-        getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value)));
+        getLIRGen().append(new AArch64BitManipulationOp(getLIRGen(), CTZ, result, asAllocatable(value)));
         return result;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Fri May 03 14:59:32 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
@@ -25,6 +25,7 @@
 
 package org.graalvm.compiler.core.aarch64;
 
+import jdk.vm.ci.aarch64.AArch64Kind;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.Value;
@@ -32,6 +33,7 @@
 import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
 import org.graalvm.compiler.core.gen.NodeMatchRules;
 import org.graalvm.compiler.core.match.ComplexMatchResult;
 import org.graalvm.compiler.core.match.MatchRule;
@@ -44,12 +46,14 @@
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.IfNode;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.calc.AddNode;
 import org.graalvm.compiler.nodes.calc.AndNode;
 import org.graalvm.compiler.nodes.calc.BinaryNode;
+import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
 import org.graalvm.compiler.nodes.calc.NotNode;
 import org.graalvm.compiler.nodes.calc.OrNode;
@@ -59,8 +63,6 @@
 import org.graalvm.compiler.nodes.calc.XorNode;
 import org.graalvm.compiler.nodes.memory.Access;
 
-import jdk.vm.ci.aarch64.AArch64Kind;
-
 public class AArch64NodeMatchRules extends NodeMatchRules {
     private static final EconomicMap<Class<? extends Node>, AArch64ArithmeticOp> nodeOpMap;
 
@@ -99,7 +101,8 @@
         return getLIRGeneratorTool().moveSp(value);
     }
 
-    private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift, boolean isShiftNot) {
+    private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift,
+                    boolean isShiftNot) {
         AArch64MacroAssembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass());
         assert shiftType != null;
         assert value.getStackKind().isNumericInteger();
@@ -118,6 +121,18 @@
         };
     }
 
+    private ComplexMatchResult emitBitTestAndBranch(FixedNode trueSuccessor, FixedNode falseSuccessor,
+                    ValueNode value, double trueProbability, int nbits) {
+        return builder -> {
+            LabelRef trueDestination = getLIRBlock(trueSuccessor);
+            LabelRef falseDestination = getLIRBlock(falseSuccessor);
+            AllocatableValue src = moveSp(gen.asAllocatable(operand(value)));
+            gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src,
+                            trueProbability, nbits));
+            return null;
+        };
+    }
+
     @MatchRule("(Add=binary a (LeftShift=shift b Constant))")
     @MatchRule("(Add=binary a (RightShift=shift b Constant))")
     @MatchRule("(Add=binary a (UnsignedRightShift=shift b Constant))")
@@ -189,20 +204,27 @@
         if (value.getStackKind().isNumericInteger()) {
             long constant = a.asJavaConstant().asLong();
             if (Long.bitCount(constant) == 1) {
-                int bitToTest = Long.numberOfTrailingZeros(constant);
-                return builder -> {
-                    LabelRef trueDestination = getLIRBlock(root.trueSuccessor());
-                    LabelRef falseDestination = getLIRBlock(root.falseSuccessor());
-                    AllocatableValue src = moveSp(gen.asAllocatable(operand(value)));
-                    double trueDestinationProbability = root.getTrueSuccessorProbability();
-                    gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest));
-                    return null;
-                };
+                return emitBitTestAndBranch(root.trueSuccessor(), root.falseSuccessor(), value,
+                                root.getTrueSuccessorProbability(), Long.numberOfTrailingZeros(constant));
             }
         }
         return null;
     }
 
+    /**
+     * if x < 0 <=> tbz x, sizeOfBits(x) - 1, label.
+     */
+    @MatchRule("(If (IntegerLessThan=lessNode x Constant=y))")
+    public ComplexMatchResult checkNegativeAndBranch(IfNode root, IntegerLessThanNode lessNode, ValueNode x, ConstantNode y) {
+        JavaKind xKind = x.getStackKind();
+        assert xKind.isNumericInteger();
+        if (y.isJavaConstant() && (0 == y.asJavaConstant().asLong()) && lessNode.condition().equals(CanonicalCondition.LT)) {
+            return emitBitTestAndBranch(root.falseSuccessor(), root.trueSuccessor(), x,
+                            1.0 - root.getTrueSuccessorProbability(), xKind.getBitCount() - 1);
+        }
+        return null;
+    }
+
     @Override
     public AArch64LIRGenerator getLIRGeneratorTool() {
         return (AArch64LIRGenerator) gen;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Fri May 03 14:59:32 2019 -0400
@@ -282,4 +282,6 @@
     @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.")
     public static final OptionKey<Boolean> UseGraalStubs = new OptionKey<>(true);
 
+    @Option(help = "Encode and decode snippets and substitutions before parsing to test libgraal code path. This option is ignored in the context of libgraal.")
+    public static final OptionKey<Boolean> UseEncodedGraphs = new OptionKey<>(false);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -61,4 +61,9 @@
      * Gets the linkage for a foreign call.
      */
     ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor);
+
+    /**
+     * Return true if the foreign call has a binding.
+     */
+    boolean isAvailable(ForeignCallDescriptor descriptor);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java	Fri May 03 14:59:32 2019 -0400
@@ -643,7 +643,7 @@
                             IntegerStamp b = (IntegerStamp) stamp2;
 
                             int bits = a.getBits();
-                            assert bits == b.getBits();
+                            assert bits == b.getBits() : String.format("stamp1.bits=%d, stamp2.bits=%d", bits, b.getBits());
 
                             if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) {
                                 long value = CodeUtil.convert(a.lowerBound() + b.lowerBound(), a.getBits(), false);
@@ -1298,6 +1298,15 @@
                             }
                         }
 
+                        private boolean testNoSignChangeAfterShifting(int bits, long value, int shiftAmount) {
+                            long removedBits = -1L << (bits - shiftAmount - 1);
+                            if (value < 0) {
+                                return (value & removedBits) == removedBits;
+                            } else {
+                                return (value & removedBits) == 0;
+                            }
+                        }
+
                         @Override
                         public Stamp foldStamp(Stamp stamp, IntegerStamp shift) {
                             IntegerStamp value = (IntegerStamp) stamp;
@@ -1318,13 +1327,15 @@
                                     return value;
                                 }
                                 // the mask of bits that will be lost or shifted into the sign bit
-                                long removedBits = -1L << (bits - shiftAmount - 1);
-                                if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) {
+                                if (testNoSignChangeAfterShifting(bits, value.lowerBound(), shiftAmount) && testNoSignChangeAfterShifting(bits, value.upperBound(), shiftAmount)) {
                                     /*
                                      * use a better stamp if neither lower nor upper bound can lose
                                      * bits
                                      */
-                                    return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount);
+                                    IntegerStamp result = new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount,
+                                                    (value.downMask() << shiftAmount) & CodeUtil.mask(bits),
+                                                    (value.upMask() << shiftAmount) & CodeUtil.mask(bits));
+                                    return result;
                                 }
                             }
                             if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/AbstractTypeReader.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,64 @@
+/*
+ * 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.common.util;
+
+public abstract class AbstractTypeReader implements TypeReader {
+    @Override
+    public long getSV() {
+        return decodeSign(read());
+    }
+
+    @Override
+    public long getUV() {
+        return read();
+    }
+
+    public static long decodeSign(long value) {
+        return (value >>> 1) ^ -(value & 1);
+    }
+
+    private long read() {
+        int b0 = getU1();
+        if (b0 < UnsafeArrayTypeWriter.NUM_LOW_CODES) {
+            return b0;
+        } else {
+            return readPacked(b0);
+        }
+    }
+
+    private long readPacked(int b0) {
+        assert b0 >= UnsafeArrayTypeWriter.NUM_LOW_CODES;
+        long sum = b0;
+        long shift = UnsafeArrayTypeWriter.HIGH_WORD_SHIFT;
+        for (int i = 2;; i++) {
+            long b = getU1();
+            sum += b << shift;
+            if (b < UnsafeArrayTypeWriter.NUM_LOW_CODES || i == UnsafeArrayTypeWriter.MAX_BYTES) {
+                return sum;
+            }
+            shift += UnsafeArrayTypeWriter.HIGH_WORD_SHIFT;
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeReader.java	Fri May 03 14:59:32 2019 -0400
@@ -60,21 +60,7 @@
      * Reads a signed value that has been written using {@link TypeWriter#putSV variable byte size
      * encoding}.
      */
-    default long getSV() {
-        long result = 0;
-        int shift = 0;
-        long b;
-        do {
-            b = getU1();
-            result |= (b & 0x7f) << shift;
-            shift += 7;
-        } while ((b & 0x80) != 0);
-
-        if ((b & 0x40) != 0 && shift < 64) {
-            result |= -1L << shift;
-        }
-        return result;
-    }
+    long getSV();
 
     /**
      * Reads a signed variable byte size encoded value that is known to fit into the range of int.
@@ -87,18 +73,7 @@
      * Reads an unsigned value that has been written using {@link TypeWriter#putSV variable byte
      * size encoding}.
      */
-    default long getUV() {
-        long result = 0;
-        int shift = 0;
-        long b;
-        do {
-            b = getU1();
-            result |= (b & 0x7f) << shift;
-            shift += 7;
-        } while ((b & 0x80) != 0);
-
-        return result;
-    }
+    long getUV();
 
     /**
      * Reads an unsigned variable byte size encoded value that is known to fit into the range of
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/TypeWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,6 @@
  * bytes.
  */
 public interface TypeWriter {
-
     /**
      * Returns the number of bytes that have been written, i.e., the byte index of the next byte to
      * be written.
@@ -51,40 +50,18 @@
     /** Writes a signed 4 byte value. */
     void putS4(long value);
 
+    /** Patches a previously written signed 4 byte value at a given offset. */
+    void patchS4(long value, long offset);
+
     /** Writes an unsigned 4 byte value. */
     void putU4(long value);
 
     /** Writes a signed 8 byte value. */
     void putS8(long value);
 
-    /**
-     * Writes a signed value in a variable byte size encoding.
-     */
-    default void putSV(long value) {
-        long cur = value;
-        while (true) {
-            if (cur >= -64 && cur < 64) {
-                putU1(cur & 0x7f);
-                return;
-            }
-            putU1(0x80 | (cur & 0x7f));
-            cur = cur >> 7;
-        }
-    }
+    /** Writes a signed value in a variable byte size encoding. */
+    void putSV(long value);
 
-    /**
-     * Writes an unsigned value in a variable byte size encoding.
-     */
-    default void putUV(long value) {
-        long cur = value;
-        while (true) {
-            assert cur >= 0;
-            if (cur < 128) {
-                putU1(cur & 0x7f);
-                return;
-            }
-            putU1(0x80 | (cur & 0x7f));
-            cur = cur >> 7;
-        }
-    }
+    /** Writes an unsigned value in a variable byte size encoding. */
+    void putUV(long value);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java	Fri May 03 14:59:32 2019 -0400
@@ -40,7 +40,7 @@
  * architectures that support unaligned memory accesses; the value {@code false} is the safe
  * fallback that works on every hardware.
  */
-public abstract class UnsafeArrayTypeReader implements TypeReader {
+public abstract class UnsafeArrayTypeReader extends AbstractTypeReader {
 
     private static final Unsafe UNSAFE = getUnsafe();
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java	Fri May 03 14:59:32 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
@@ -32,6 +32,8 @@
 import static org.graalvm.compiler.core.common.util.TypeConversion.asU4;
 import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
 
+import org.graalvm.compiler.core.common.calc.UnsignedMath;
+
 import sun.misc.Unsafe;
 
 /**
@@ -45,11 +47,16 @@
  * fallback that works on every hardware.
  */
 public abstract class UnsafeArrayTypeWriter implements TypeWriter {
-
     private static final Unsafe UNSAFE = getUnsafe();
     private static final int MIN_CHUNK_LENGTH = 200;
     private static final int MAX_CHUNK_LENGTH = 16000;
 
+    // Constants for UNSIGNED5 coding of Pack200
+    public static final long HIGH_WORD_SHIFT = 6;
+    public static final long NUM_HIGH_CODES = 1 << HIGH_WORD_SHIFT; // number of high codes (64)
+    public static final long NUM_LOW_CODES = (1 << Byte.SIZE) - NUM_HIGH_CODES;
+    public static final long MAX_BYTES = 11;
+
     static class Chunk {
         protected final byte[] data;
         protected int size;
@@ -118,6 +125,30 @@
         putS4(asU4(value));
     }
 
+    @Override
+    public void putS2(long value) {
+        long offset = writeOffset(Short.BYTES);
+        putS2(value, writeChunk, offset);
+    }
+
+    @Override
+    public void putS4(long value) {
+        long offset = writeOffset(Integer.BYTES);
+        putS4(value, writeChunk, offset);
+    }
+
+    @Override
+    public void putS8(long value) {
+        long offset = writeOffset(Long.BYTES);
+        putS8(value, writeChunk, offset);
+    }
+
+    protected abstract void putS2(long value, Chunk chunk, long offset);
+
+    protected abstract void putS4(long value, Chunk chunk, long offset);
+
+    protected abstract void putS8(long value, Chunk chunk, long offset);
+
     protected long writeOffset(int writeBytes) {
         if (writeChunk.size + writeBytes >= writeChunk.data.length) {
             Chunk newChunk = new Chunk(Math.min(writeChunk.data.length * 2, MAX_CHUNK_LENGTH));
@@ -134,27 +165,76 @@
 
         return result;
     }
+
+    @Override
+    public void patchS4(long value, long offset) {
+        long chunkStartOffset = 0;
+        Chunk chunk = firstChunk;
+        while (chunkStartOffset + chunk.size <= offset) {
+            chunkStartOffset += chunk.size;
+            chunk = chunk.next;
+        }
+
+        long targetOffset = offset - chunkStartOffset;
+        assert targetOffset + Integer.BYTES <= chunk.size : "out of bounds";
+        putS4(value, chunk, Unsafe.ARRAY_BYTE_BASE_OFFSET + targetOffset);
+    }
+
+    @Override
+    public void putSV(long value) {
+        // this is a modified version of the SIGNED5 encoding from Pack200
+        write(encodeSign(value));
+    }
+
+    @Override
+    public void putUV(long value) {
+        // this is a modified version of the UNSIGNED5 encoding from Pack200
+        write(value);
+    }
+
+    private static long encodeSign(long value) {
+        return (value << 1) ^ (value >> 63);
+    }
+
+    private void write(long value) {
+        if (UnsignedMath.belowThan(value, NUM_LOW_CODES)) {
+            putU1(value);
+        } else {
+            writePacked(value);
+        }
+    }
+
+    private void writePacked(long value) {
+        long sum = value;
+        for (int i = 1; UnsignedMath.aboveOrEqual(sum, NUM_LOW_CODES) && i < MAX_BYTES; i++) {
+            sum -= NUM_LOW_CODES;
+            long u1 = NUM_LOW_CODES + (sum & (NUM_HIGH_CODES - 1)); // this is a "high code"
+            sum >>>= HIGH_WORD_SHIFT; // extracted 6 bits
+            putU1(u1);
+        }
+
+        // remainder is either a "low code" or the last byte
+        assert sum == (sum & 0xFF) : "not a byte";
+        putU1(sum & 0xFF);
+    }
 }
 
 final class UnalignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter {
     private static final Unsafe UNSAFE = getUnsafe();
 
     @Override
-    public void putS2(long value) {
-        long offset = writeOffset(Short.BYTES);
-        UNSAFE.putShort(writeChunk.data, offset, asS2(value));
+    protected void putS2(long value, Chunk chunk, long offset) {
+        UNSAFE.putShort(chunk.data, offset, asS2(value));
     }
 
     @Override
-    public void putS4(long value) {
-        long offset = writeOffset(Integer.BYTES);
-        UNSAFE.putInt(writeChunk.data, offset, asS4(value));
+    protected void putS4(long value, Chunk chunk, long offset) {
+        UNSAFE.putInt(chunk.data, offset, asS4(value));
     }
 
     @Override
-    public void putS8(long value) {
-        long offset = writeOffset(Long.BYTES);
-        UNSAFE.putLong(writeChunk.data, offset, value);
+    protected void putS8(long value, Chunk chunk, long offset) {
+        UNSAFE.putLong(chunk.data, offset, value);
     }
 }
 
@@ -162,31 +242,28 @@
     private static final Unsafe UNSAFE = getUnsafe();
 
     @Override
-    public void putS2(long value) {
-        long offset = writeOffset(Short.BYTES);
-        UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
-        UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
+    protected void putS2(long value, Chunk chunk, long offset) {
+        UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0));
+        UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8));
     }
 
     @Override
-    public void putS4(long value) {
-        long offset = writeOffset(Integer.BYTES);
-        UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
-        UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
-        UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16));
-        UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24));
+    protected void putS4(long value, Chunk chunk, long offset) {
+        UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0));
+        UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8));
+        UNSAFE.putByte(chunk.data, offset + 2, (byte) (value >> 16));
+        UNSAFE.putByte(chunk.data, offset + 3, (byte) (value >> 24));
     }
 
     @Override
-    public void putS8(long value) {
-        long offset = writeOffset(Long.BYTES);
-        UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
-        UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
-        UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16));
-        UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24));
-        UNSAFE.putByte(writeChunk.data, offset + 4, (byte) (value >> 32));
-        UNSAFE.putByte(writeChunk.data, offset + 5, (byte) (value >> 40));
-        UNSAFE.putByte(writeChunk.data, offset + 6, (byte) (value >> 48));
-        UNSAFE.putByte(writeChunk.data, offset + 7, (byte) (value >> 56));
+    protected void putS8(long value, Chunk chunk, long offset) {
+        UNSAFE.putByte(chunk.data, offset + 0, (byte) (value >> 0));
+        UNSAFE.putByte(chunk.data, offset + 1, (byte) (value >> 8));
+        UNSAFE.putByte(chunk.data, offset + 2, (byte) (value >> 16));
+        UNSAFE.putByte(chunk.data, offset + 3, (byte) (value >> 24));
+        UNSAFE.putByte(chunk.data, offset + 4, (byte) (value >> 32));
+        UNSAFE.putByte(chunk.data, offset + 5, (byte) (value >> 40));
+        UNSAFE.putByte(chunk.data, offset + 6, (byte) (value >> 48));
+        UNSAFE.putByte(chunk.data, offset + 7, (byte) (value >> 56));
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BasePhaseBinaryGraphTest.java	Fri May 03 14:59:32 2019 -0400
@@ -24,11 +24,12 @@
 
 package org.graalvm.compiler.core.test;
 
+import static org.junit.Assert.assertEquals;
+
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.phases.BasePhase;
 import org.graalvm.compiler.printer.BinaryGraphPrinter;
-import static org.junit.Assert.assertEquals;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -43,7 +44,7 @@
 
     @Before
     public void createPrinter() throws Exception {
-        printer = new BinaryGraphPrinter(DebugContext.DISABLED, null);
+        printer = new BinaryGraphPrinter(DebugContext.disabled(null), null);
     }
 
     @Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java	Fri May 03 14:59:32 2019 -0400
@@ -51,7 +51,7 @@
         StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES, debug);
         boolean resetSucceeded = false;
         try (Scope scope = debug.scope("some scope")) {
-            graph.resetDebug(DebugContext.DISABLED);
+            graph.resetDebug(DebugContext.disabled(getInitialOptions()));
             resetSucceeded = true;
         } catch (AssertionError expected) {
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java	Fri May 03 14:59:32 2019 -0400
@@ -141,13 +141,13 @@
         test01(false);
     }
 
-    private static void checkSignedSize(TypeWriter writer, long value, int expectedSize) {
+    private static void checkSignedSize(TypeWriter writer, long value, long expectedSize) {
         long sizeBefore = writer.getBytesWritten();
         writer.putSV(value);
         Assert.assertEquals(expectedSize, writer.getBytesWritten() - sizeBefore);
     }
 
-    private static void checkUnsignedSize(TypeWriter writer, long value, int expectedSize) {
+    private static void checkUnsignedSize(TypeWriter writer, long value, long expectedSize) {
         long sizeBefore = writer.getBytesWritten();
         writer.putUV(value);
         Assert.assertEquals(expectedSize, writer.getBytesWritten() - sizeBefore);
@@ -155,23 +155,24 @@
 
     private static void checkSizes(TypeWriter writer) {
         checkSignedSize(writer, 0, 1);
-        checkSignedSize(writer, 63, 1);
-        checkSignedSize(writer, -64, 1);
-        checkSignedSize(writer, 64, 2);
-        checkSignedSize(writer, -65, 2);
-        checkSignedSize(writer, 8191, 2);
-        checkSignedSize(writer, -8192, 2);
+        checkSignedSize(writer, 95, 1);
+        checkSignedSize(writer, -96, 1);
+        checkSignedSize(writer, 96, 2);
+        checkSignedSize(writer, -97, 2);
+        checkSignedSize(writer, 6239, 2);
+        checkSignedSize(writer, -6240, 2);
         checkSignedSize(writer, 8192, 3);
         checkSignedSize(writer, -8193, 3);
-        checkSignedSize(writer, Long.MAX_VALUE, 10);
-        checkSignedSize(writer, Long.MIN_VALUE, 10);
+        checkSignedSize(writer, Long.MAX_VALUE, UnsafeArrayTypeWriter.MAX_BYTES);
+        checkSignedSize(writer, Long.MIN_VALUE, UnsafeArrayTypeWriter.MAX_BYTES);
 
         checkUnsignedSize(writer, 0, 1);
-        checkUnsignedSize(writer, 127, 1);
-        checkUnsignedSize(writer, 128, 2);
-        checkUnsignedSize(writer, 16383, 2);
-        checkUnsignedSize(writer, 16384, 3);
-        checkUnsignedSize(writer, Long.MAX_VALUE, 9);
+        checkUnsignedSize(writer, 191, 1);
+        checkUnsignedSize(writer, 192, 2);
+        checkUnsignedSize(writer, 12479, 2);
+        checkUnsignedSize(writer, 12480, 3);
+        checkUnsignedSize(writer, Long.MAX_VALUE, UnsafeArrayTypeWriter.MAX_BYTES);
+        checkUnsignedSize(writer, Long.MIN_VALUE, UnsafeArrayTypeWriter.MAX_BYTES);
     }
 
     @Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -252,7 +252,7 @@
 
             if (!state.canProduceBytecodeFrame()) {
                 // This typically means a snippet or intrinsic frame state made it to the backend
-                StackTraceElement ste = state.getCode().asStackTraceElement(state.bci);
+                String ste = state.getCode() != null ? state.getCode().asStackTraceElement(state.bci).toString() : state.toString();
                 throw new GraalError("Frame state for %s cannot be converted to a BytecodeFrame since the frame state's code is " +
                                 "not the same as the frame state method's code", ste);
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Fri May 03 14:59:32 2019 -0400
@@ -311,9 +311,19 @@
     }
 
     /**
-     * Shared object used to represent a disabled debug context.
+     * Singleton used to represent a disabled debug context.
+     */
+    private static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS);
+
+    /**
+     * Create a DebugContext with debugging disabled.
      */
-    public static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS);
+    public static DebugContext disabled(OptionValues options) {
+        if (options == null || options.getMap().isEmpty()) {
+            return DISABLED;
+        }
+        return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), NO_CONFIG_CUSTOMIZERS);
+    }
 
     /**
      * Gets the debug context for the current thread. This should only be used when there is no
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Fri May 03 14:59:32 2019 -0400
@@ -192,6 +192,11 @@
          * {@code true}.
          */
         boolean injectedStampIsNonNull() default false;
+
+        /**
+         * If {@code true} then this is lowered into a node that has side effects.
+         */
+        boolean hasSideEffect() default false;
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java	Fri May 03 14:59:32 2019 -0400
@@ -201,16 +201,24 @@
         size = other.size;
     }
 
-    public boolean equals(NodeList<T> other) {
-        if (size != other.size) {
-            return false;
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
         }
-        for (int i = 0; i < size; i++) {
-            if (nodes[i] != other.nodes[i]) {
+        if (other instanceof List<?>) {
+            List<?> otherList = (List<?>) other;
+            if (size != otherList.size()) {
                 return false;
             }
+            for (int i = 0; i < size; i++) {
+                if (nodes[i] != otherList.get(i)) {
+                    return false;
+                }
+            }
+            return true;
         }
-        return true;
+        return false;
     }
 
     @SuppressWarnings("unchecked")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64.test/src/org/graalvm/compiler/hotspot/aarch64/test/AArch64UncompressPointerTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.aarch64.test;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.runtime.JVMCI;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotMove;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+public class AArch64UncompressPointerTest extends GraalCompilerTest {
+
+    private AArch64MacroAssembler masm1;
+    private AArch64MacroAssembler masm2;
+    private Register input;
+    private Register result;
+
+    @Before
+    public void checkAArch64() {
+        assumeTrue("skipping AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64);
+    }
+
+    @Before
+    public void setupEnvironment() {
+        TargetDescription target = JVMCI.getRuntime().getHostJVMCIBackend().getTarget();
+        masm1 = new AArch64MacroAssembler(target);
+        masm2 = new AArch64MacroAssembler(target);
+        input = AArch64.r10;
+        result = AArch64.r11;
+    }
+
+    private void emitUncompressPointer(Register base, int shift) {
+        AArch64HotSpotMove.UncompressPointer.emitUncompressCode(masm2, input, result, base, shift, true);
+    }
+
+    private void compareAssembly() {
+        byte[] expected = masm1.close(false);
+        byte[] actual = masm2.close(false);
+        assertArrayEquals(expected, actual);
+    }
+
+    @Test
+    public void testUncompressPointerWithBase() {
+        Register base = AArch64.r12;
+        int shift = 3;
+        masm1.add(64, result, base, input, AArch64Assembler.ShiftType.LSL, shift);
+        emitUncompressPointer(base, shift);
+        compareAssembly();
+    }
+
+    @Test
+    public void testUncompressPointerWithZeroBase() {
+        int shift = 3;
+        masm1.shl(64, result, input, shift);
+        emitUncompressPointer(null, shift);
+        compareAssembly();
+    }
+
+    @Test
+    public void testUncompressPointerWithZeroBaseAndShift() {
+        masm1.or(64, result, AArch64.zr, input);
+        emitUncompressPointer(null, 0);
+        compareAssembly();
+    }
+
+    static class A {
+        String str;
+
+        A(String str) {
+            this.str = str;
+        }
+    }
+
+    public static String getObjectField(A a) {
+        return a.str;
+    }
+
+    @Test
+    public void testGetObjectField() {
+        test("getObjectField", new A("asfghjkjhgfd"));
+    }
+
+    static String[] strings = {"asf", "egfda", "fsdasere", "eqwred", "fgdadgtre", "qwrrtreety"};
+
+    public static String getArrayMember(int index) {
+        return strings[index];
+    }
+
+    @Test
+    public void testGetArrayMember() {
+        test("getArrayMember", 4);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -144,10 +144,10 @@
                 bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
             }
             try (InitTimer rt = timer("create Replacements provider")) {
-                replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider);
+                replacements = createReplacements(p, snippetReflection, bytecodeProvider);
             }
             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
-                plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
+                plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, graalRuntime.getOptions());
                 replacements.setGraphBuilderPlugins(plugins);
             }
             try (InitTimer rt = timer("create Suites provider")) {
@@ -156,6 +156,7 @@
             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
                             snippetReflection, wordTypes,
                             plugins);
+            replacements.setProviders(providers);
         }
         try (InitTimer rt = timer("instantiate backend")) {
             return createBackend(config, graalRuntime, providers);
@@ -164,8 +165,8 @@
 
     protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection,
                     HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection,
-                    HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
-        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
+                    HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) {
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options);
         AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false, //
                         /* registerMathPlugins */true);
         return plugins;
@@ -179,8 +180,8 @@
         return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp);
     }
 
-    protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
-        return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
+    protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
+        return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
     }
 
     protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java	Fri May 03 14:59:32 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
@@ -194,9 +194,19 @@
         }
 
         public static void emitUncompressCode(AArch64MacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
+            // result = ptr << shift
+            if (baseReg == null) {
+                if (shift != 0) {
+                    masm.shl(64, resReg, inputRegister, shift);
+                } else if (!resReg.equals(inputRegister)) {
+                    masm.movx(resReg, inputRegister);
+                }
+                return;
+            }
+
             // result = base + (ptr << shift)
-            if (nonNull || baseReg == null) {
-                masm.add(64, resReg, baseReg == null ? zr : baseReg, inputRegister, AArch64Assembler.ShiftType.LSL, shift);
+            if (nonNull) {
+                masm.add(64, resReg, baseReg, inputRegister, AArch64Assembler.ShiftType.LSL, shift);
             } else {
                 // if ptr is null it has to be null after decompression
                 Label done = new Label();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Fri May 03 14:59:32 2019 -0400
@@ -234,7 +234,7 @@
     public void test() {
         HotSpotProviders providers = (HotSpotProviders) getProviders();
         HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls();
-        HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallLinkage.Transition.LEAF_NOFP, HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE);
+        HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO, HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE);
         linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage));
         runTest("testStub");
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -138,10 +138,10 @@
                 bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
             }
             try (InitTimer rt = timer("create Replacements provider")) {
-                replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
+                replacements = createReplacements(p, snippetReflection, bytecodeProvider);
             }
             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
-                plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
+                plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options);
                 replacements.setGraphBuilderPlugins(plugins);
             }
             try (InitTimer rt = timer("create Suites provider")) {
@@ -159,8 +159,8 @@
 
     protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target,
                     HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
-                    HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
-        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
+                    HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) {
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options);
         AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
         return plugins;
     }
@@ -173,8 +173,8 @@
         return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
     }
 
-    protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
-        return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
+    protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
+        return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
     }
 
     protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -36,7 +36,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
-import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
 import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
@@ -89,15 +89,15 @@
         RegisterValue exception = rax.asValue(LIRKind.reference(word));
         RegisterValue exceptionPc = rdx.asValue(LIRKind.value(word));
         CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc);
-        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
-        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
+        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
+        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
 
         if (config.useCRC32Intrinsics) {
             // This stub does callee saving
-            registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+            registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
         }
         if (config.useCRC32CIntrinsics) {
-            registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+            registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
         }
 
         link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES, options, providers,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
 
 import org.graalvm.compiler.api.replacements.Snippet;
@@ -66,7 +67,7 @@
     @Override
     public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
         convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
-        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier
+        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)
                         ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
                         : null;
         mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -51,6 +51,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 import org.graalvm.compiler.nodes.spi.Replacements;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.common.AddressLoweringPhase;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.phases.util.Providers;
@@ -103,21 +104,22 @@
         Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider);
         HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
         BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
-        HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target);
-        Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes);
+        HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target);
+        Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes, runtime.getOptions());
         replacements.setGraphBuilderPlugins(plugins);
         HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements);
         HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
                         snippetReflection,
                         wordTypes, plugins);
+        replacements.setProviders(providers);
 
         return createBackend(config, runtime, providers);
     }
 
     protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess,
                     HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls,
-                    HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
-        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
+                    HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) {
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options);
         SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false);
         return plugins;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -35,7 +35,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
-import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
 import static jdk.internal.vm.compiler.word.LocationIdentity.any;
@@ -84,16 +84,16 @@
         RegisterValue incomingExceptionPc = i1.asValue(LIRKind.value(word));
         CallingConvention outgoingExceptionCc = new CallingConvention(0, ILLEGAL, outgoingException, outgoingExceptionPc);
         CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc);
-        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any()));
-        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc,
+        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc, incomingExceptionCc, any()));
+        register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, outgoingExceptionCc,
                         incomingExceptionCc, any()));
 
         if (config.useCRC32Intrinsics) {
             // This stub does callee saving
-            registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+            registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
         }
         if (config.useCRC32CIntrinsics) {
-            registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+            registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
         }
 
         super.initialize(providers, options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java	Fri May 03 14:59:32 2019 -0400
@@ -162,7 +162,7 @@
     }
 
     /**
-     * Tests {@link ArrayCopySnippets#arraycopyCheckcastSnippet}.
+     * Tests {@link ArrayCopySnippets#arraycopyGenericSnippet} with checkcast.
      */
     @Test
     public void testArrayStoreException() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Fri May 03 14:59:32 2019 -0400
@@ -381,8 +381,11 @@
         if (isJDK11OrHigher()) {
             // Relevant for Java flight recorder
             add(toBeInvestigated,
-                            "java/util/Base64$Encoder.encodeBlock([BII[BIZ)V",
                             "jdk/jfr/internal/JVM.getEventWriter()Ljava/lang/Object;");
+            if (!config.useBase64Intrinsics()) {
+                add(ignore,
+                                "java/util/Base64$Encoder.encodeBlock([BII[BIZ)V");
+            }
         }
 
         if (isJDK12OrHigher()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Fri May 03 14:59:32 2019 -0400
@@ -32,7 +32,9 @@
 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
+import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
 
+import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
@@ -73,10 +75,11 @@
 import java.util.stream.Collectors;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
-import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.bytecode.Bytecodes;
 import org.graalvm.compiler.core.CompilerThreadFactory;
+import org.graalvm.compiler.core.phases.HighTier;
 import org.graalvm.compiler.core.test.ReflectionOptionDescriptors;
 import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.debug.GraalError;
@@ -86,11 +89,15 @@
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.test.CompileTheWorld.LibGraalParams.StackTraceBuffer;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
+import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+import jdk.internal.vm.compiler.libgraal.LibGraal;
+import jdk.internal.vm.compiler.libgraal.OptionsEncoder;
 
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@@ -102,6 +109,7 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCICompiler;
+import sun.misc.Unsafe;
 
 /**
  * This class implements compile-the-world functionality with JVMCI.
@@ -127,17 +135,19 @@
      *            Ignored if null.
      */
     public static EconomicMap<OptionKey<?>, Object> parseOptions(String options) {
+        EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
         if (options != null) {
             EconomicMap<String, String> optionSettings = EconomicMap.create();
             for (String optionSetting : options.split("\\s+|#")) {
                 OptionsParser.parseOptionSettingTo(optionSetting, optionSettings);
             }
-            EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
             ServiceLoader<OptionDescriptors> loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader());
             OptionsParser.parseOptions(optionSettings, values, loader);
-            return values;
         }
-        return EconomicMap.create();
+        if (!values.containsKey(HighTier.Options.Inline)) {
+            values.put(HighTier.Options.Inline, false);
+        }
+        return values;
     }
 
     private final HotSpotJVMCIRuntime jvmciRuntime;
@@ -165,6 +175,13 @@
      */
     private final int stopAt;
 
+    /**
+     * Max classes to compile.
+     *
+     * @see Options#MaxClasses
+     */
+    private final int maxClasses;
+
     /** Only compile methods matching one of the filters in this array if the array is non-null. */
     private final MethodFilter[] methodFilters;
 
@@ -186,8 +203,130 @@
 
     private ThreadPoolExecutor threadPool;
 
-    private OptionValues currentOptions;
-    private final UnmodifiableEconomicMap<OptionKey<?>, Object> compilationOptions;
+    /**
+     * Values for {@link CompileTheWorld.Options}.
+     */
+    private final OptionValues harnessOptions;
+
+    /**
+     * Option values used during compilation.
+     */
+    private final OptionValues compilerOptions;
+
+    /**
+     * Manages native memory buffers for passing arguments into libgraal and receiving return
+     * values. The native memory buffers are freed when this object is {@linkplain #close() closed}.
+     */
+    static class LibGraalParams implements AutoCloseable {
+
+        static {
+            LibGraal.registerNativeMethods(HotSpotJVMCIRuntime.runtime(), CompileTheWorld.class);
+        }
+
+        /**
+         * Native memory containing {@linkplain OptionsEncoder encoded} {@link OptionValues}.
+         */
+        static class OptionsBuffer {
+            private long address;
+            final int size;
+            final int hash;
+
+            OptionsBuffer(OptionValues options) {
+                Map<String, Object> map = new HashMap<>();
+                UnmodifiableMapCursor<OptionKey<?>, Object> cursor = options.getMap().getEntries();
+                while (cursor.advance()) {
+                    final OptionKey<?> key = cursor.getKey();
+                    Object value = cursor.getValue();
+                    map.put(key.getName(), value);
+                }
+
+                byte[] encoded = OptionsEncoder.encode(map);
+                size = encoded.length;
+                hash = Arrays.hashCode(encoded);
+                address = UNSAFE.allocateMemory(encoded.length);
+                UNSAFE.copyMemory(encoded, ARRAY_BYTE_BASE_OFFSET, null, address, size);
+            }
+
+            long getAddress() {
+                if (address == 0) {
+                    throw new IllegalStateException();
+                }
+                return address;
+            }
+
+            void free() {
+                if (address != 0) {
+                    UNSAFE.freeMemory(address);
+                    address = 0;
+                }
+            }
+        }
+
+        /**
+         * Manages native memory for receiving a {@linkplain Throwable#printStackTrace() stack
+         * trace} from libgraal serialized via {@link ByteArrayOutputStream} to a byte array.
+         */
+        static class StackTraceBuffer {
+            final int size;
+            private long address;
+
+            StackTraceBuffer(int size) {
+                this.size = size;
+                address = UNSAFE.allocateMemory(size);
+            }
+
+            void free() {
+                if (address != 0L) {
+                    UNSAFE.freeMemory(address);
+                    address = 0L;
+                }
+            }
+
+            long getAddress() {
+                if (address == 0) {
+                    throw new IllegalStateException();
+                }
+                return address;
+            }
+        }
+
+        final OptionsBuffer options;
+
+        private final List<StackTraceBuffer> stackTraceBuffers = new ArrayList<>();
+
+        /**
+         * Gets a stack trace buffer for the current thread.
+         */
+        StackTraceBuffer getStackTraceBuffer() {
+            return stackTraceBuffer.get();
+        }
+
+        private final ThreadLocal<StackTraceBuffer> stackTraceBuffer = new ThreadLocal<StackTraceBuffer>() {
+            @Override
+            protected StackTraceBuffer initialValue() {
+                StackTraceBuffer buffer = new StackTraceBuffer(10_000);
+                synchronized (stackTraceBuffers) {
+                    stackTraceBuffers.add(buffer);
+                }
+                return buffer;
+            }
+        };
+
+        LibGraalParams(OptionValues options) {
+            this.options = new OptionsBuffer(options);
+        }
+
+        @Override
+        public void close() {
+            options.free();
+            synchronized (stackTraceBuffers) {
+                for (StackTraceBuffer buffer : stackTraceBuffers) {
+                    buffer.free();
+                }
+                stackTraceBuffers.clear();
+            }
+        }
+    }
 
     /**
      * Creates a compile-the-world instance.
@@ -195,73 +334,99 @@
      * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile
      * @param startAt index of the class file to start compilation at
      * @param stopAt index of the class file to stop compilation at
+     * @param maxClasses maximum number of classes to process
      * @param methodFilters
      * @param excludeMethodFilters
+     * @param harnessOptions values for {@link CompileTheWorld.Options}
+     * @param compilerOptions option values used by the compiler
      */
-    public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters,
-                    boolean verbose, OptionValues initialOptions, EconomicMap<OptionKey<?>, Object> compilationOptions) {
+    public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime,
+                    HotSpotGraalCompiler compiler,
+                    String files,
+                    int startAt,
+                    int stopAt,
+                    int maxClasses,
+                    String methodFilters,
+                    String excludeMethodFilters,
+                    boolean verbose,
+                    OptionValues harnessOptions,
+                    OptionValues compilerOptions) {
         this.jvmciRuntime = jvmciRuntime;
         this.compiler = compiler;
         this.inputClassPath = files;
-        this.startAt = startAt;
-        this.stopAt = stopAt;
+        this.startAt = Math.max(startAt, 1);
+        this.stopAt = Math.max(stopAt, 1);
+        this.maxClasses = Math.max(maxClasses, 1);
         this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters);
         this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters);
         this.verbose = verbose;
-        this.currentOptions = initialOptions;
+        this.harnessOptions = harnessOptions;
 
         // Copy the initial options and add in any extra options
-        EconomicMap<OptionKey<?>, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap());
-        compilationOptionsCopy.putAll(compilationOptions);
+        EconomicMap<OptionKey<?>, Object> compilerOptionsMap = EconomicMap.create(compilerOptions.getMap());
 
         // We want to see stack traces when a method fails to compile
-        CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
-        CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
+        CompilationBailoutAsFailure.putIfAbsent(compilerOptionsMap, true);
+        CompilationFailureAction.putIfAbsent(compilerOptionsMap, Print);
 
         // By default only report statistics for the CTW threads themselves
-        DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld");
-        this.compilationOptions = compilationOptionsCopy;
+        DebugOptions.MetricsThreadFilter.putIfAbsent(compilerOptionsMap, "^CompileTheWorld");
+        this.compilerOptions = new OptionValues(compilerOptionsMap);
     }
 
-    public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) {
-        this(jvmciRuntime, compiler, Options.Classpath.getValue(options),
-                        Options.StartAt.getValue(options),
-                        Options.StopAt.getValue(options),
-                        Options.MethodFilter.getValue(options),
-                        Options.ExcludeMethodFilter.getValue(options),
-                        Options.Verbose.getValue(options),
-                        options,
-                        parseOptions(Options.Config.getValue(options)));
+    public CompileTheWorld(HotSpotJVMCIRuntime jvmciRuntime,
+                    HotSpotGraalCompiler compiler,
+                    OptionValues harnessOptions,
+                    OptionValues compilerOptions) {
+        this(jvmciRuntime, compiler, Options.Classpath.getValue(harnessOptions),
+                        Options.StartAt.getValue(harnessOptions),
+                        Options.StopAt.getValue(harnessOptions),
+                        Options.MaxClasses.getValue(harnessOptions),
+                        Options.MethodFilter.getValue(harnessOptions),
+                        Options.ExcludeMethodFilter.getValue(harnessOptions),
+                        Options.Verbose.getValue(harnessOptions),
+                        harnessOptions,
+                        new OptionValues(compilerOptions, parseOptions(Options.Config.getValue(harnessOptions))));
     }
 
     /**
      * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath}
      * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used.
      */
+    @SuppressWarnings("try")
     public void compile() throws Throwable {
-        if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
-            String bcpEntry = null;
-            if (Java8OrEarlier) {
-                final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
-                for (int i = 0; i < entries.length && bcpEntry == null; i++) {
-                    String entry = entries[i];
-                    File entryFile = new File(entry);
-                    if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) {
-                        bcpEntry = entry;
+        try (LibGraalParams libgraal = LibGraal.isAvailable() ? new LibGraalParams(compilerOptions) : null) {
+            if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
+                String bcpEntry = null;
+                if (Java8OrEarlier) {
+                    final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
+                    for (int i = 0; i < entries.length && bcpEntry == null; i++) {
+                        String entry = entries[i];
+                        File entryFile = new File(entry);
+                        if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) {
+                            bcpEntry = entry;
+                        }
                     }
+                    if (bcpEntry == null) {
+                        throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH));
+                    }
+                } else {
+                    bcpEntry = JRT_CLASS_PATH_ENTRY;
                 }
-                if (bcpEntry == null) {
-                    throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH));
-                }
+                compile(bcpEntry, libgraal);
             } else {
-                bcpEntry = JRT_CLASS_PATH_ENTRY;
+                compile(inputClassPath, libgraal);
             }
-            compile(bcpEntry);
-        } else {
-            compile(inputClassPath);
         }
     }
 
+    private AutoCloseable enterCompilation() {
+        if (!LibGraal.isAvailable()) {
+            return null;
+        }
+        return new LibGraalParams(compilerOptions);
+    }
+
     public void println() {
         println("");
     }
@@ -486,6 +651,19 @@
         return true;
     }
 
+    private ClassPathEntry openClassPathEntry(String entry) throws IOException {
+        if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
+            return new JarClassPathEntry(entry);
+        } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
+            return new JRTClassPathEntry(entry, Options.LimitModules.getValue(harnessOptions));
+        } else {
+            if (!new File(entry).isDirectory()) {
+                return null;
+            }
+            return new DirClassPathEntry(entry);
+        }
+    }
+
     /**
      * Compiles all methods in all classes in a given class path.
      *
@@ -493,23 +671,25 @@
      * @throws IOException
      */
     @SuppressWarnings("try")
-    private void compile(String classPath) throws IOException {
+    private void compile(String classPath, LibGraalParams libgraal) throws IOException {
         final String[] entries = classPath.split(File.pathSeparator);
         long start = System.currentTimeMillis();
         Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces();
 
-        try {
-            // compile dummy method to get compiler initialized outside of the
-            // config debug override.
-            HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(
-                            CompileTheWorld.class.getDeclaredMethod("dummy"));
-            int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
-            boolean useProfilingInfo = false;
-            boolean installAsDefault = false;
-            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions);
-            task.runCompilation();
-        } catch (NoSuchMethodException | SecurityException e1) {
-            printStackTrace(e1);
+        if (libgraal == null) {
+            try {
+                // compile dummy method to get compiler initialized outside of the
+                // config debug override.
+                HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(
+                                CompileTheWorld.class.getDeclaredMethod("dummy"));
+                int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
+                boolean useProfilingInfo = false;
+                boolean installAsDefault = false;
+                CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault);
+                task.runCompilation(compilerOptions);
+            } catch (NoSuchMethodException | SecurityException e1) {
+                printStackTrace(e1);
+            }
         }
 
         /*
@@ -517,8 +697,8 @@
          * DebugValueThreadFilter to filter on the thread names.
          */
         int threadCount = 1;
-        if (Options.MultiThreaded.getValue(currentOptions)) {
-            threadCount = Options.Threads.getValue(currentOptions);
+        if (Options.MultiThreaded.getValue(harnessOptions)) {
+            threadCount = Options.Threads.getValue(harnessOptions);
             if (threadCount == 0) {
                 threadCount = Runtime.getRuntime().availableProcessors();
             }
@@ -526,26 +706,37 @@
             running = true;
         }
 
-        OptionValues savedOptions = currentOptions;
-        currentOptions = new OptionValues(compilationOptions);
         threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new CompilerThreadFactory("CompileTheWorld"));
 
-        try {
-            for (int i = 0; i < entries.length; i++) {
-                final String entry = entries[i];
+        int compileStartAt = startAt;
+        int compileStopAt = stopAt;
+        int compileStep = 1;
+        if (maxClasses != Integer.MAX_VALUE) {
+            int totalClassFileCount = 0;
+            for (String entry : entries) {
+                try (ClassPathEntry cpe = openClassPathEntry(entry)) {
+                    if (cpe != null) {
+                        totalClassFileCount += cpe.getClassNames().size();
+                    }
+                }
+            }
 
-                ClassPathEntry cpe;
-                if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
-                    cpe = new JarClassPathEntry(entry);
-                } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
-                    cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions));
-                } else {
-                    if (!new File(entry).isDirectory()) {
-                        println("CompileTheWorld : Skipped classes in " + entry);
-                        println();
-                        continue;
-                    }
-                    cpe = new DirClassPathEntry(entry);
+            int lastClassFile = totalClassFileCount - 1;
+            compileStartAt = Math.min(startAt, lastClassFile);
+            compileStopAt = Math.min(stopAt, lastClassFile);
+            int range = compileStopAt - compileStartAt + 1;
+            if (maxClasses < range) {
+                compileStep = range / maxClasses;
+            }
+        }
+
+        for (int i = 0; i < entries.length; i++) {
+            final String entry = entries[i];
+            try (ClassPathEntry cpe = openClassPathEntry(entry)) {
+                if (cpe == null) {
+                    println("CompileTheWorld : Skipped classes in " + entry);
+                    println();
+                    continue;
                 }
 
                 if (methodFilters == null || methodFilters.length == 0) {
@@ -565,12 +756,16 @@
                 for (String className : cpe.getClassNames()) {
 
                     // Are we done?
-                    if (classFileCounter >= stopAt) {
+                    if (classFileCounter >= compileStopAt) {
                         break;
                     }
 
                     classFileCounter++;
 
+                    if (compileStep > 1 && ((classFileCounter - compileStartAt) % compileStep) != 0) {
+                        continue;
+                    }
+
                     if (className.startsWith("jdk.management.") ||
                                     className.startsWith("jdk.internal.cmm.*") ||
                                     // GR-5881: The class initializer for
@@ -606,28 +801,29 @@
                         }
 
                         // Are we compiling this class?
-                        if (classFileCounter >= startAt) {
-                            println("CompileTheWorld (%d) : %s", classFileCounter, className);
+                        if (classFileCounter >= compileStartAt) {
 
+                            long start0 = System.currentTimeMillis();
                             // Compile each constructor/method in the class.
                             for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
                                 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor);
                                 if (canBeCompiled(javaMethod, constructor.getModifiers())) {
-                                    compileMethod(javaMethod);
+                                    compileMethod(javaMethod, libgraal);
                                 }
                             }
                             for (Method method : javaClass.getDeclaredMethods()) {
                                 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
                                 if (canBeCompiled(javaMethod, method.getModifiers())) {
-                                    compileMethod(javaMethod);
+                                    compileMethod(javaMethod, libgraal);
                                 }
                             }
 
                             // Also compile the class initializer if it exists
                             HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer();
                             if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) {
-                                compileMethod(clinit);
+                                compileMethod(clinit, libgraal);
                             }
+                            println("CompileTheWorld (%d) : %s (%d ms)", classFileCounter, className, System.currentTimeMillis() - start0);
                         }
                     } catch (Throwable t) {
                         if (isClassIncluded(className)) {
@@ -636,10 +832,7 @@
                         }
                     }
                 }
-                cpe.close();
             }
-        } finally {
-            currentOptions = savedOptions;
         }
 
         if (!running) {
@@ -661,11 +854,12 @@
         long elapsedTime = System.currentTimeMillis() - start;
 
         println();
-        if (Options.MultiThreaded.getValue(currentOptions)) {
-            TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime,
+        int compiledClasses = classFileCounter > compileStartAt ? classFileCounter - compileStartAt : 0;
+        if (Options.MultiThreaded.getValue(harnessOptions)) {
+            TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), elapsedTime,
                             compileTime.get(), memoryUsed.get());
         } else {
-            TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get());
+            TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", compiledClasses, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get());
         }
 
         // Apart from the main thread, there should be only be daemon threads
@@ -712,7 +906,7 @@
     }
 
     @SuppressWarnings("try")
-    private void compileMethod(HotSpotResolvedJavaMethod method) throws InterruptedException, ExecutionException {
+    private void compileMethod(HotSpotResolvedJavaMethod method, LibGraalParams libgraal) throws InterruptedException, ExecutionException {
         if (methodFilters != null && !MethodFilter.matches(methodFilters, method)) {
             return;
         }
@@ -723,13 +917,7 @@
             @Override
             public void run() {
                 waitToRun();
-                OptionValues savedOptions = currentOptions;
-                currentOptions = new OptionValues(compilationOptions);
-                try {
-                    compileMethod(method, classFileCounter);
-                } finally {
-                    currentOptions = savedOptions;
-                }
+                compileMethod(method, classFileCounter, libgraal);
             }
         });
         if (threadPool.getCorePoolSize() == 1) {
@@ -737,23 +925,66 @@
         }
     }
 
+    private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
+
+    static native long compileMethodInLibgraal(long isolateThread,
+                    long methodHandle,
+                    boolean useProfilingInfo,
+                    boolean installAsDefault,
+                    long optionsAddress,
+                    int optionsSize,
+                    int optionsHash,
+                    long encodedThrowableBufferAddress,
+                    int encodedThrowableBufferSize);
+
     /**
      * Compiles a method and gathers some statistics.
      */
-    private void compileMethod(HotSpotResolvedJavaMethod method, int counter) {
+    private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) {
         try {
             long start = System.currentTimeMillis();
             long allocatedAtStart = getCurrentThreadAllocatedBytes();
-            int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
-            HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
             // For more stable CTW execution, disable use of profiling information
             boolean useProfilingInfo = false;
             boolean installAsDefault = false;
-            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions);
-            task.runCompilation();
+            HotSpotInstalledCode installedCode;
+            if (libgraal != null) {
+                HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+                long methodHandle = LibGraal.translate(runtime, method);
+                long isolateThread = LibGraal.getIsolateThread();
+
+                StackTraceBuffer stackTraceBuffer = libgraal.getStackTraceBuffer();
+
+                long stackTraceBufferAddress = stackTraceBuffer.getAddress();
+                long installedCodeHandle = compileMethodInLibgraal(isolateThread,
+                                methodHandle,
+                                useProfilingInfo,
+                                installAsDefault,
+                                libgraal.options.getAddress(),
+                                libgraal.options.size,
+                                libgraal.options.hash,
+                                stackTraceBufferAddress,
+                                stackTraceBuffer.size);
+
+                installedCode = LibGraal.unhand(runtime, HotSpotInstalledCode.class, installedCodeHandle);
+                if (installedCode == null) {
+                    int length = UNSAFE.getInt(stackTraceBufferAddress);
+                    byte[] data = new byte[length];
+                    UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length);
+                    String stackTrace = new String(data).trim();
+                    println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
+                    println(stackTrace);
+                }
+
+            } else {
+                int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
+                HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
+                CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault);
+                task.runCompilation(compilerOptions);
+                installedCode = task.getInstalledCode();
+            }
 
             // Invalidate the generated code so the code cache doesn't fill up
-            HotSpotInstalledCode installedCode = task.getInstalledCode();
             if (installedCode != null) {
                 installedCode.invalidate();
             }
@@ -799,13 +1030,12 @@
     }
 
     static class Options {
-        // @formatter:off
         public static final OptionKey<Boolean> Help = new OptionKey<>(false);
         public static final OptionKey<String> Classpath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH);
         public static final OptionKey<Boolean> Verbose = new OptionKey<>(true);
         /**
-         * Ignore Graal classes by default to avoid problems associated with compiling
-         * snippets and method substitutions.
+         * Ignore Graal classes by default to avoid problems associated with compiling snippets and
+         * method substitutions.
          */
         public static final OptionKey<String> LimitModules = new OptionKey<>("~jdk.internal.vm.compiler");
         public static final OptionKey<Integer> Iterations = new OptionKey<>(1);
@@ -813,10 +1043,12 @@
         public static final OptionKey<String> ExcludeMethodFilter = new OptionKey<>(null);
         public static final OptionKey<Integer> StartAt = new OptionKey<>(1);
         public static final OptionKey<Integer> StopAt = new OptionKey<>(Integer.MAX_VALUE);
+        public static final OptionKey<Integer> MaxClasses = new OptionKey<>(Integer.MAX_VALUE);
         public static final OptionKey<String> Config = new OptionKey<>(null);
         public static final OptionKey<Boolean> MultiThreaded = new OptionKey<>(false);
         public static final OptionKey<Integer> Threads = new OptionKey<>(0);
 
+        // @formatter:off
         static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class,
                            "Help", "List options and their help messages and then exit.",
                       "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.",
@@ -826,21 +1058,24 @@
                      "Iterations", "The number of iterations to perform.",
                    "MethodFilter", "Only compile methods matching this filter.",
             "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.",
-                        "StartAt", "First class to consider for compilation.",
-                         "StopAt", "Last class to consider for compilation.",
-                         "Config", "Option value overrides to use during compile the world. For example, " +
-                                   "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " +
-                                   "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.",
+                        "StartAt", "First class to consider for compilation (default = 1).",
+                         "StopAt", "Last class to consider for compilation (default = <number of classes>).",
+                     "MaxClasses", "Maximum number of classes to process (default = <number of classes>). " +
+                                   "Ignored if less than (StopAt - StartAt + 1).",
+                         "Config", "Option values to use during compile the world compilations. For example, " +
+                                   "to disable partial escape analysis and print compilations specify " +
+                                   "'PartialEscapeAnalysis=false PrintCompilation=true'. " +
+                                   "Unless explicitly enabled with 'Inline=true' here, inlining is disabled.",
                   "MultiThreaded", "Run using multiple threads for compilation.",
                         "Threads", "Number of threads to use for multithreaded execution. Defaults to Runtime.getRuntime().availableProcessors().");
         // @formatter:on
     }
 
-    public static OptionValues loadOptions(OptionValues initialValues) {
+    public static OptionValues loadHarnessOptions() {
         EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
         List<OptionDescriptors> loader = singletonList(DESCRIPTORS);
         OptionsParser.parseOptions(extractEntries(System.getProperties(), "CompileTheWorld.", true), values, loader);
-        OptionValues options = new OptionValues(initialValues, values);
+        OptionValues options = new OptionValues(values);
         if (Options.Help.getValue(options)) {
             options.printHelp(loader, System.out, "CompileTheWorld.");
             System.exit(0);
@@ -853,14 +1088,14 @@
         HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) jvmciRuntime.getCompiler();
         HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
         HotSpotCodeCacheProvider codeCache = graalRuntime.getHostProviders().getCodeCache();
-        OptionValues options = loadOptions(graalRuntime.getOptions());
+        OptionValues harnessOptions = loadHarnessOptions();
 
-        int iterations = Options.Iterations.getValue(options);
+        int iterations = Options.Iterations.getValue(harnessOptions);
         for (int i = 0; i < iterations; i++) {
             codeCache.resetCompilationStatistics();
             TTY.println("CompileTheWorld : iteration " + i);
 
-            CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, options);
+            CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, harnessOptions, graalRuntime.getOptions());
             ctw.compile();
         }
         // This is required as non-daemon threads can be started by class initializers
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Fri May 03 14:59:32 2019 -0400
@@ -27,11 +27,10 @@
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 
-import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
+import org.graalvm.compiler.core.phases.HighTier;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
-import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
@@ -50,8 +49,25 @@
         HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
         System.setProperty("CompileTheWorld.LimitModules", "java.base");
         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();
+        OptionValues harnessOptions = new OptionValues(OptionValues.newOptionMap());
+        int startAt = 1;
+        int stopAt = 5;
+        int maxClasses = Integer.MAX_VALUE;
+        String methodFilters = null;
+        String excludeMethodFilters = null;
+        boolean verbose = false;
+        CompileTheWorld ctw = new CompileTheWorld(runtime,
+                        (HotSpotGraalCompiler) runtime.getCompiler(),
+                        CompileTheWorld.SUN_BOOT_CLASS_PATH,
+                        startAt,
+                        stopAt,
+                        maxClasses,
+                        methodFilters,
+                        excludeMethodFilters,
+                        verbose,
+                        harnessOptions,
+                        new OptionValues(initialOptions, HighTier.Options.Inline, false));
+        ctw.compile();
         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	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Fri May 03 14:59:32 2019 -0400
@@ -79,7 +79,7 @@
         long jvmciEnv = 0L;
         HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv);
         HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
-        CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, debug.getOptions());
+        CompilationTask task = new CompilationTask(runtime, compiler, request, true, true);
         if (method instanceof HotSpotResolvedJavaMethod) {
             HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
             GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotBase64Test.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Base64;
+
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HotSpotBase64Test extends HotSpotGraalCompilerTest {
+
+    // Checkstyle: stop
+    private static final String lipsum = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata ";
+    // Checkstyle: resume
+
+    @Before
+    public void sanity() {
+        HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class);
+        assumeTrue("Enable test case when the hotspot intrinsic is available", rt.getVMConfig().useBase64Intrinsics());
+    }
+
+    @Test
+    public void testEncode() {
+        test(getResolvedJavaMethod(Base64.Encoder.class, "encode", byte[].class), Base64.getEncoder(), lipsum.getBytes());
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java	Fri May 03 14:59:32 2019 -0400
@@ -137,8 +137,8 @@
             HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
             int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
             HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv);
-            CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions());
-            task.runCompilation();
+            CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false);
+            task.runCompilation(getInitialOptions());
         }
     }
 
@@ -156,8 +156,8 @@
                 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv);
                 HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
                 OptionValues options = getInitialOptions();
-                CompilationTask task = new CompilationTask(runtime, compiler, request, true, false, options);
-                task.runCompilation();
+                CompilationTask task = new CompilationTask(runtime, compiler, request, true, false);
+                task.runCompilation(options);
             }
         }
     }
@@ -180,10 +180,10 @@
     public void run() {
         compileAndTime("simple");
         compileAndTime("complex");
-        OptionValues options = CompileTheWorld.loadOptions(getInitialOptions());
-        if (CompileTheWorld.Options.Classpath.getValue(options) != CompileTheWorld.SUN_BOOT_CLASS_PATH) {
+        OptionValues harnessOptions = CompileTheWorld.loadHarnessOptions();
+        if (CompileTheWorld.Options.Classpath.getValue(harnessOptions) != CompileTheWorld.SUN_BOOT_CLASS_PATH) {
             HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
-            CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), options);
+            CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), harnessOptions, getInitialOptions());
             try {
                 ctw.compile();
             } catch (Throwable e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * 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.test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
+import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class ObjectHashCodeInliningTest extends GraalCompilerTest {
+
+    public static int getHash(Object obj) {
+        return obj.hashCode();
+    }
+
+    @Test
+    public void testInstallCodeInvalidation() {
+        for (int i = 0; i < 100000; i++) {
+            getHash(i % 1000 == 0 ? new Object() : "");
+        }
+
+        ResolvedJavaMethod method = getResolvedJavaMethod("getHash");
+        StructuredGraph graph = parseForCompile(method);
+        for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.TYPE)) {
+            if ("Object.hashCode".equals(callTargetNode.targetName())) {
+                Assume.assumeTrue(callTargetNode.getProfile() != null);
+            }
+        }
+        compile(method, graph);
+    }
+
+    private static boolean containsForeignCallToIdentityHashCode(StructuredGraph graph) {
+        for (ForeignCallNode foreignCallNode : graph.getNodes().filter(ForeignCallNode.class)) {
+            if ("identity_hashcode".equals(foreignCallNode.getDescriptor().getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean containsReadStringHash(StructuredGraph graph) {
+        for (ReadNode readNode : graph.getNodes().filter(ReadNode.class)) {
+            if ("String.hash".equals(readNode.getLocationIdentity().toString())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean checkHighTierGraph(StructuredGraph graph) {
+        return containsForeignCallToIdentityHashCode(graph) && containsReadStringHash(graph);
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java	Fri May 03 14:59:32 2019 -0400
@@ -178,6 +178,10 @@
                                 StackTraceElement[] stackTraceNow = t.getStackTrace();
                                 TTY.printf("Printing stack trace for current compilation of %s lasting more than %d seconds:%n%s",
                                                 fmt(request1.getMethod()), EPOCH, fmt(stackTraceNow));
+
+                                // Fortify: Null Dereference false positive
+                                assert stacksAtTimeout != null;
+
                                 if (Arrays.equals(stacksAtTimeout.get(t), stackTraceNow)) {
                                     TTY.printf("\t** Identical stack trace %d seconds ago, implying a hung compilation **%n",
                                                     EPOCH);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Fri May 03 14:59:32 2019 -0400
@@ -40,7 +40,6 @@
 import org.graalvm.compiler.core.CompilationPrinter;
 import org.graalvm.compiler.core.CompilationWrapper;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
-import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
@@ -93,7 +92,6 @@
 
     private final boolean useProfilingInfo;
     private final boolean shouldRetainLocalVariables;
-    private final OptionValues options;
 
     final class HotSpotCompilationWrapper extends CompilationWrapper<HotSpotCompilationRequestResult> {
         private final EventProvider.CompilationEvent compilationEvent;
@@ -150,9 +148,8 @@
                 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()) {
+                        // Get more info for permanent bailouts during bootstrap.
+                        if (compiler.getGraalRuntime().isBootstrapping()) {
                             return Diagnose;
                         }
 
@@ -165,9 +162,8 @@
 
             // 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()) {
+                // Automatically exit on failure during bootstrap.
+                if (compiler.getGraalRuntime().isBootstrapping()) {
                     return ExitVM;
                 }
             }
@@ -180,14 +176,14 @@
             HotSpotResolvedJavaMethod method = getMethod();
             int entryBCI = getEntryBCI();
             final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
-            CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
+            CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR);
 
-            final CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI);
+            final CompilationPrinter printer = CompilationPrinter.begin(debug.getOptions(), compilationId, method, entryBCI);
 
             try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
                 // Begin the compilation event.
                 compilationEvent.begin();
-                result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, options, debug);
+                result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, debug);
             } catch (Throwable e) {
                 throw debug.handle(e);
             } finally {
@@ -211,20 +207,21 @@
 
     }
 
-    public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault,
-                    OptionValues options) {
-        this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault, options);
+    public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) {
+        this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault);
     }
 
     public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean shouldRetainLocalVariables,
-                    boolean installAsDefault, OptionValues options) {
+                    boolean installAsDefault) {
         this.jvmciRuntime = jvmciRuntime;
         this.compiler = compiler;
         this.compilationId = new HotSpotCompilationIdentifier(request);
         this.useProfilingInfo = useProfilingInfo;
         this.shouldRetainLocalVariables = shouldRetainLocalVariables;
         this.installAsDefault = installAsDefault;
+    }
 
+    public OptionValues filterOptions(OptionValues options) {
         /*
          * Disable inlining if HotSpot has it disabled unless it's been explicitly set in Graal.
          */
@@ -243,7 +240,7 @@
                 newOptions = new OptionValues(options, m);
             }
         }
-        this.options = newOptions;
+        return newOptions;
     }
 
     public HotSpotResolvedJavaMethod getMethod() {
@@ -309,7 +306,8 @@
      */
     public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation");
 
-    public HotSpotCompilationRequestResult runCompilation() {
+    public HotSpotCompilationRequestResult runCompilation(OptionValues initialOptions) {
+        OptionValues options = filterOptions(initialOptions);
         SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
         try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) {
             return runCompilation(debug);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -219,6 +219,8 @@
                 factory = candidates.get(0);
             }
         }
+        assert factory != null;
+
         ShowConfigurationLevel level = Options.ShowConfiguration.getValue(options);
         if (level != ShowConfigurationLevel.none) {
             switch (level) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri May 03 14:59:32 2019 -0400
@@ -102,6 +102,7 @@
     private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class);
     private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class);
     private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false);
+    private final boolean useBase64Intrinsics = getFlag("UseBASE64Intrinsics", Boolean.class, false);
     private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false);
     private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false);
     private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false);
@@ -132,6 +133,10 @@
         return useGHASHIntrinsics && ghashProcessBlocks != 0;
     }
 
+    public boolean useBase64Intrinsics() {
+        return useBase64Intrinsics && base64EncodeBlock != 0;
+    }
+
     public boolean useMontgomeryMultiplyIntrinsic() {
         return useMontgomeryMultiplyIntrinsic && montgomeryMultiply != 0;
     }
@@ -647,6 +652,7 @@
 
     public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L);
     public final long ghashProcessBlocks = getFieldValue("StubRoutines::_ghash_processBlocks", Long.class, "address", 0L);
+    public final long base64EncodeBlock = getFieldValue("StubRoutines::_base64_encodeBlock", Long.class, "address", 0L);
     public final long crc32cTableTddr = getFieldValue("StubRoutines::_crc32c_table_addr", Long.class, "address", 0L);
     public final long updateBytesCRC32C = getFieldValue("StubRoutines::_updateBytesCRC32C", Long.class, "address", 0L);
     public final long updateBytesAdler32 = getFieldValue("StubRoutines::_updateBytesAdler32", Long.class, "address", 0L);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Fri May 03 14:59:32 2019 -0400
@@ -306,6 +306,11 @@
     public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class);
 
     /**
+     * Descriptor for {@code StubRoutines::_base64_encodeBlock}.
+     */
+    public static final ForeignCallDescriptor BASE64_ENCODE_BLOCK = new ForeignCallDescriptor("base64EncodeBlock", void.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class);
+
+    /**
      * Descriptor for {@code StubRoutines::_counterMode_AESCrypt}.
      */
     public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -280,14 +280,14 @@
                         }
                     }
                 }
-                assert !siteListIterator.hasNext() || site.pcOffset >= source.getStartOffset();
+                assert !siteListIterator.hasNext() || (site != null && site.pcOffset >= source.getStartOffset());
                 if (site != null && source.getStartOffset() <= site.pcOffset && site.pcOffset <= source.getEndOffset()) {
                     // Conflicting source mapping, skip it.
                     continue;
                 } else {
                     // Since the sites are sorted there can not be any more sites in this interval.
                 }
-                assert !siteListIterator.hasNext() || site.pcOffset > source.getEndOffset();
+                assert !siteListIterator.hasNext() || (site != null && site.pcOffset > source.getEndOffset());
                 // Good source mapping. Create an infopoint and add it to the list.
                 NodeSourcePosition sourcePosition = source.getSourcePosition();
                 assert sourcePosition.verify();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java	Fri May 03 14:59:32 2019 -0400
@@ -53,11 +53,14 @@
      */
     enum Transition {
         /**
-         * A call to a leaf function that is guaranteed to not use floating point registers and will
-         * never have its caller stack inspected by the VM. That is, {@code JavaFrameAnchor}
-         * management around the call can be omitted.
+         * A call to a leaf function that is guaranteed to not use floating point registers.
+         * Consequently, floating point registers cleanup will be waived. On AMD64, this means the
+         * compiler will no longer emit vzeroupper instruction around the foreign call, which it
+         * normally does for unknown foreign calls to avoid potential SSE-AVX transition penalty.
+         * Besides, this foreign call will never have its caller stack inspected by the VM. That is,
+         * {@code JavaFrameAnchor} management around the call can be omitted.
          */
-        LEAF_NOFP,
+        LEAF_NO_VZERO,
 
         /**
          * A call to a leaf function that might use floating point registers but will never have its
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -283,7 +283,7 @@
 
     @Override
     public boolean mayContainFP() {
-        return transition != Transition.LEAF_NOFP;
+        return transition != Transition.LEAF_NO_VZERO;
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 package org.graalvm.compiler.hotspot;
 
 import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions;
-import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
@@ -59,6 +58,7 @@
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.phases.tiers.Suites;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
+import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
 
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.code.CompilationRequestResult;
@@ -109,7 +109,7 @@
     }
 
     @SuppressWarnings("try")
-    CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues options) {
+    CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) {
         if (graalRuntime.isShutdown()) {
             return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
         }
@@ -117,7 +117,7 @@
         ResolvedJavaMethod method = request.getMethod();
 
         if (graalRuntime.isBootstrapping()) {
-            if (DebugOptions.BootstrapInitializeOnly.getValue(options)) {
+            if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) {
                 return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true);
             }
             if (bootstrapWatchDog != null) {
@@ -128,13 +128,14 @@
             }
         }
         HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request;
+        CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault);
+        OptionValues options = task.filterOptions(initialOptions);
         try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options);
                         BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request);
                         CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) {
             if (compilationCounters != null) {
                 compilationCounters.countCompilation(method);
             }
-            CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault, options);
             CompilationRequestResult r = null;
             try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM);
                             Activation a = debug.activate()) {
@@ -187,7 +188,7 @@
 
     public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo,
                     boolean shouldRetainLocalVariables, OptionValues options) {
-
+        assert options == graph.getOptions();
         HotSpotBackend backend = graalRuntime.getHostBackend();
         HotSpotProviders providers = backend.getProviders();
         final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
@@ -218,15 +219,11 @@
         return result;
     }
 
-    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
-        return compile(method, entryBCI, useProfilingInfo, false, compilationId, options, debug);
-    }
-
-    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId, OptionValues options,
+    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId,
                     DebugContext debug) {
-        StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
+        StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, debug.getOptions(), debug);
         CompilationResult result = new CompilationResult(compilationId);
-        return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, options);
+        return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, debug.getOptions());
     }
 
     protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,9 @@
 
 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
-import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets;
+import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs;
+import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
+import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION;
 
 import java.util.Set;
 
@@ -43,6 +45,7 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.options.OptionValues;
@@ -59,12 +62,12 @@
  * them.
  */
 public class HotSpotReplacementsImpl extends ReplacementsImpl {
-    public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
-        super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
+    public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
+        super(new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
     }
 
-    protected HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) {
-        super(replacements.options, new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection,
+    HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) {
+        super(new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection,
                         replacements.getDefaultReplacementBytecodeProvider(), replacements.target);
     }
 
@@ -73,14 +76,15 @@
         return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method);
     }
 
-    public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) {
+    @Override
+    public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) {
         if (!IS_IN_NATIVE_IMAGE) {
-            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) {
                 synchronized (HotSpotReplacementsImpl.class) {
                     if (snippetEncoder == null) {
                         snippetEncoder = new SymbolicSnippetEncoder(this);
                     }
-                    snippetEncoder.registerMethodSubstitution(method, original);
+                    snippetEncoder.registerMethodSubstitution(plugin, original, context, options);
                 }
             }
         }
@@ -88,12 +92,18 @@
 
     @Override
     public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
-        if (IS_IN_NATIVE_IMAGE) {
+        boolean useEncodedGraphs = UseEncodedGraphs.getValue(debug.getOptions());
+        if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
             HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements();
             InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method);
             if (plugin instanceof MethodSubstitutionPlugin) {
                 MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin;
-                return replacements.getMethodSubstitution(msp, method);
+                if (useEncodedGraphs) {
+                    replacements.registerMethodSubstitution(msp, method, ROOT_COMPILATION, debug.getOptions());
+                }
+                StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, StructuredGraph.AllowAssumptions.YES, debug.getOptions());
+                methodSubstitution.resetDebug(debug);
+                return methodSubstitution;
             }
             return null;
         }
@@ -101,6 +111,26 @@
     }
 
     @Override
+    public StructuredGraph getSubstitution(ResolvedJavaMethod targetMethod, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) {
+        boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
+        if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
+            InvocationPlugin plugin = getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
+            if (plugin instanceof MethodSubstitutionPlugin && (!plugin.inlineOnly() || invokeBci >= 0)) {
+                MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin;
+                if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) {
+                    registerMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, options);
+                }
+                // This assumes the normal path creates the graph using
+                // GraphBuilderConfiguration.getSnippetDefault with omits exception edges
+                StructuredGraph subst = getMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.NO, options);
+                return subst;
+            }
+        }
+
+        return super.getSubstitution(targetMethod, invokeBci, trackNodeSourcePosition, replaceePosition, options);
+    }
+
+    @Override
     public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) {
         if (b.parsingIntrinsic() && snippetEncoder != null) {
             if (getIntrinsifyingPlugin(method) != null) {
@@ -118,16 +148,16 @@
     private boolean snippetRegistrationClosed;
 
     @Override
-    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
         if (!IS_IN_NATIVE_IMAGE) {
             assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)");
             assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)");
-            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) {
                 synchronized (HotSpotReplacementsImpl.class) {
                     if (snippetEncoder == null) {
                         snippetEncoder = new SymbolicSnippetEncoder(this);
                     }
-                    snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition);
+                    snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition, options);
                 }
             }
         }
@@ -138,7 +168,7 @@
         snippetRegistrationClosed = true;
     }
 
-    static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() {
+    private static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() {
         return encodedSnippets;
     }
 
@@ -153,57 +183,66 @@
         HotSpotReplacementsImpl.encodedSnippets = encodedSnippets;
     }
 
-    public boolean encode() {
+    public boolean encode(OptionValues options) {
         SymbolicSnippetEncoder encoder = HotSpotReplacementsImpl.snippetEncoder;
         if (encoder != null) {
-            return encoder.encode();
+            return encoder.encode(options);
         }
         return false;
     }
 
     private static volatile SymbolicSnippetEncoder.EncodedSnippets encodedSnippets;
 
-    @NativeImageReinitialize static SymbolicSnippetEncoder snippetEncoder;
+    @NativeImageReinitialize private static SymbolicSnippetEncoder snippetEncoder;
 
     @Override
-    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        StructuredGraph graph = getEncodedSnippet(method, args);
+    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition,
+                    OptionValues options) {
+        StructuredGraph graph = getEncodedSnippet(method, args, StructuredGraph.AllowAssumptions.NO, options);
         if (graph != null) {
             return graph;
         }
 
         assert !IS_IN_NATIVE_IMAGE : "should be using encoded snippets";
-        return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition);
+        return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options);
     }
 
-    public StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args) {
-        if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+    private StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+        boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
+        if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
             synchronized (HotSpotReplacementsImpl.class) {
-                if (!IS_IN_NATIVE_IMAGE && UseEncodedSnippets.getValue(options)) {
-                    snippetEncoder.encode();
+                if (!IS_IN_NATIVE_IMAGE) {
+                    snippetEncoder.encode(options);
                 }
 
                 if (getEncodedSnippets() == null) {
                     throw GraalError.shouldNotReachHere("encoded snippets not found");
                 }
-                StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args);
+                StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options);
                 if (graph == null) {
                     throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
                 }
                 return graph;
             }
-        } else if (registeredSnippets != null) {
-            assert registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)");
+        } else {
+            assert registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)");
         }
         return null;
     }
 
-    public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original) {
-        if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+    @Override
+    public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
+                    StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+        boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
+        if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
+            if (!IS_IN_NATIVE_IMAGE) {
+                snippetEncoder.encode(options);
+            }
+
             if (getEncodedSnippets() == null) {
                 throw GraalError.shouldNotReachHere("encoded snippets not found");
             }
-            return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this);
+            return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, options);
         }
         return null;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java	Fri May 03 14:59:32 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
@@ -24,6 +24,10 @@
 
 package org.graalvm.compiler.hotspot;
 
+import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
+
+import org.graalvm.compiler.debug.GraalError;
+
 import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 
@@ -56,11 +60,17 @@
     @Override
     void onCompilerConfigurationFactorySelection(HotSpotJVMCIRuntime runtime, CompilerConfigurationFactory factory) {
         compilerConfigurationModule = factory.getClass().getModule();
+        runtime.excludeFromJVMCICompilation(jvmciModule, graalModule, compilerConfigurationModule);
     }
 
     @Override
     boolean apply(Class<?> declaringClass) {
-        Module module = declaringClass.getModule();
-        return jvmciModule == module || graalModule == module || compilerConfigurationModule == module;
+        throw GraalError.shouldNotReachHere();
     }
+
+    @Override
+    HotSpotJVMCICompilerFactory.CompilationLevelAdjustment getCompilationLevelAdjustment() {
+        return None;
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java	Fri May 03 14:59:32 2019 -0400
@@ -27,8 +27,9 @@
 import static jdk.vm.ci.runtime.JVMCI.getRuntime;
 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo;
-import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets;
+import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -48,6 +49,7 @@
 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
 import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampPair;
@@ -86,7 +88,6 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
 import org.graalvm.compiler.nodes.java.AccessFieldNode;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
-import org.graalvm.compiler.nodes.spi.DelegatingReplacements;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
@@ -98,12 +99,12 @@
 import org.graalvm.compiler.replacements.SnippetCounter;
 import org.graalvm.compiler.replacements.SnippetIntegerHistogram;
 
-import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotSignature;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
@@ -123,13 +124,13 @@
  * method references into a symbolic form that can be resolved at graph decode time using
  * {@link SymbolicJVMCIReference}.
  */
-public class SymbolicSnippetEncoder extends DelegatingReplacements {
+public class SymbolicSnippetEncoder {
 
     /**
      * This is a customized HotSpotReplacementsImpl intended only for parsing snippets and method
      * substitutions for graph encoding.
      */
-    private final HotSpotSnippetReplacementsImpl replacements;
+    private final HotSpotSnippetReplacementsImpl snippetReplacements;
 
     /**
      * The set of all snippet methods that have been encoded.
@@ -142,11 +143,13 @@
      */
     private final Map<String, String> originalMethods = new ConcurrentHashMap<>();
 
+    private final HotSpotReplacementsImpl originalReplacements;
+
     /**
      * The current count of graphs encoded. Used to detect when new graphs have been enqueued for
      * encoding.
      */
-    int encodedGraphs = 0;
+    private int encodedGraphs = 0;
 
     /**
      * All the graphs parsed so far.
@@ -175,13 +178,13 @@
                 return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
             }
 
-            if (getIntrinsifyingPlugin(method) != null) {
+            if (snippetReplacements.getIntrinsifyingPlugin(method) != null) {
                 delayedInvocationPluginMethods.add(method);
                 return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
             }
 
             // Force inlining when parsing replacements
-            return createIntrinsicInlineInfo(method, null, getDefaultReplacementBytecodeProvider());
+            return createIntrinsicInlineInfo(method, snippetReplacements.getDefaultReplacementBytecodeProvider());
         }
 
         @Override
@@ -219,12 +222,12 @@
                 return true;
             }
             if (field.getType().getName().equals(snippetCounterName)) {
-                b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess()));
+                b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReplacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess()));
                 return true;
             }
 
             if (field.getType().getName().equals(snippetIntegerHistogramName)) {
-                b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess()));
+                b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReplacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess()));
                 return true;
             }
             return false;
@@ -240,8 +243,7 @@
     }
 
     SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) {
-        super(replacements);
-
+        this.originalReplacements = replacements;
         GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins();
         SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins());
         GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins);
@@ -249,22 +251,20 @@
         copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin());
         copy.appendNodePlugin(new SnippetCounterPlugin());
         HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection()));
-        this.replacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy));
-        this.replacements.setGraphBuilderPlugins(copy);
-    }
-
-    @Override
-    public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() {
-        return replacements.getGraphBuilderPlugins();
+        this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy));
+        this.snippetReplacements.setGraphBuilderPlugins(copy);
     }
 
     /**
      * Compiles the snippet and stores the graph.
      */
-    public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) {
+    synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) {
+        ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess());
         assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName();
-        buildGraph(method, original, null, false, false);
+        StructuredGraph subst = buildGraph(method, original, null, true, false, context, options);
         snippetMethods.add(method);
+        originalMethods.put(methodKey(method), methodKey(original));
+        preparedSnippetGraphs.put(plugin.toString() + context, subst);
     }
 
     static class EncodedSnippets {
@@ -282,54 +282,26 @@
             this.originalMethods = originalMethods;
         }
 
-        public StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements) {
-            Integer startOffset = snippetStartOffsets.get(plugin.toString());
+        StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements, IntrinsicContext.CompilationContext context,
+                        StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+            Integer startOffset = snippetStartOffsets.get(plugin.toString() + context);
             if (startOffset == null) {
-                throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin);
+                throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + context);
             }
 
-            return decodeGraph(original, null, startOffset, replacements);
+            ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass());
+            return decodeGraph(original, accessingClass, startOffset, replacements, context, allowAssumptions, options);
         }
 
         @SuppressWarnings("try")
-        private StructuredGraph decodeGraph(ResolvedJavaMethod method, Object[] args, int startOffset, ReplacementsImpl replacements) {
-            OptionValues options = replacements.getOptions();
-            SnippetReflectionProvider snippetReflection = replacements.snippetReflection;
-            ParameterPlugin parameterPlugin = null;
+        private StructuredGraph decodeGraph(ResolvedJavaMethod method, ResolvedJavaType accessingClass, int startOffset, ReplacementsImpl replacements,
+                        IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
             Providers providers = replacements.getProviders();
-            if (args != null) {
-                parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), snippetReflection);
-            }
-
-            EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(),
-                            originalMethods.get(methodKey(method)));
-            try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) {
-                StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(true).build();
-                PEGraphDecoder graphDecoder = new PEGraphDecoder(
-                                providers.getCodeCache().getTarget().arch,
-                                result,
-                                providers,
-                                null, // loopExplosionPlugin
-                                replacements.getGraphBuilderPlugins().getInvocationPlugins(),
-                                new InlineInvokePlugin[0],
-                                parameterPlugin,
-                                null, // nodePlugins
-                                null, // callInlinedMethod
-                                null // sourceLanguagePositionProvider
-                ) {
-                    @Override
-                    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod,
-                                    ResolvedJavaMethod originalMethod,
-                                    BytecodeProvider intrinsicBytecodeProvider,
-                                    boolean isSubstitution,
-                                    boolean trackNodeSourcePosition) {
-                        if (lookupMethod.equals(method)) {
-                            return encodedGraph;
-                        } else {
-                            throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)"));
-                        }
-                    }
-                };
+            EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses,
+                            methodKey(method), accessingClass, method.getDeclaringClass());
+            try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
+                StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).setIsSubstitution(true).build();
+                PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph);
 
                 graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition());
 
@@ -338,7 +310,7 @@
             }
         }
 
-        StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args) {
+        StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
             Integer startOffset = null;
             if (snippetStartOffsets != null) {
                 startOffset = snippetStartOffsets.get(methodKey(method));
@@ -351,22 +323,57 @@
                 }
             }
 
-            SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(),
-                            originalMethods.get(methodKey(method)));
-            return decodeSnippetGraph(encodedGraph, method, replacements, args, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch);
+            SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses,
+                            originalMethods.get(methodKey(method)), method.getDeclaringClass());
+            return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options);
         }
 
     }
 
-    private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition) {
+    private static class SubstitutionGraphDecoder extends PEGraphDecoder {
+        private final ResolvedJavaMethod method;
+        private final EncodedGraph encodedGraph;
+        private IntrinsicContext intrinsic;
+
+        SubstitutionGraphDecoder(Providers providers, StructuredGraph result, ReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method,
+                        IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph) {
+            super(providers.getCodeCache().getTarget().arch, result, providers, null,
+                            replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin,
+                            null, null, null);
+            this.method = method;
+            this.encodedGraph = encodedGraph;
+            intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false);
+        }
+
+        @Override
+        protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod,
+                        MethodSubstitutionPlugin plugin,
+                        BytecodeProvider intrinsicBytecodeProvider,
+                        boolean isSubstitution,
+                        boolean trackNodeSourcePosition) {
+            if (lookupMethod.equals(method)) {
+                return encodedGraph;
+            } else {
+                throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)"));
+            }
+        }
+
+        @Override
+        protected IntrinsicContext getIntrinsic() {
+            return intrinsic;
+        }
+    }
+
+    private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition,
+                    IntrinsicContext.CompilationContext context, OptionValues options) {
         assert method.hasBytecodes() : "Snippet must not be abstract or native";
         Object[] args = null;
         if (receiver != null) {
             args = new Object[method.getSignature().getParameterCount(true)];
             args[0] = receiver;
         }
-        try (DebugContext debug = openDebugContext("Snippet_", method)) {
-            StructuredGraph graph = replacements.makeGraph(debug, replacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null);
+        try (DebugContext debug = openDebugContext("Snippet_", method, options)) {
+            StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, context);
 
             // Check if all methods which should be inlined are really inlined.
             for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) {
@@ -382,48 +389,24 @@
     }
 
     @SuppressWarnings("try")
-    static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, Architecture architecture) {
+    private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args,
+                    StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
         Providers providers = replacements.getProviders();
         ParameterPlugin parameterPlugin = null;
         if (args != null) {
             parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection);
         }
 
-        try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) {
+        try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
             // @formatter:off
-            StructuredGraph result = new StructuredGraph.Builder(replacements.getOptions(), debug)
-                            .method(method)
-                            .trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition())
-                            .setIsSubstitution(true)
-                            .build();
+            StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions)
+                    .method(method)
+                    .trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition())
+                    .setIsSubstitution(true)
+                    .build();
             // @formatter:on
             try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) {
-                PEGraphDecoder graphDecoder = new PEGraphDecoder(
-                                architecture,
-                                result,
-                                providers,
-                                null,
-                                replacements.getGraphBuilderPlugins().getInvocationPlugins(),
-                                new InlineInvokePlugin[0],
-                                parameterPlugin,
-                                null,
-                                null,
-                                null) {
-                    @Override
-                    protected EncodedGraph lookupEncodedGraph(
-                                    ResolvedJavaMethod lookupMethod,
-                                    ResolvedJavaMethod originalMethod,
-                                    BytecodeProvider intrinsicBytecodeProvider,
-                                    boolean isSubstitution,
-                                    boolean track) {
-                        if (lookupMethod.equals(method)) {
-                            assert !track || encodedGraph.trackNodeSourcePosition();
-                            return encodedGraph;
-                        } else {
-                            throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)"));
-                        }
-                    }
-                };
+                PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph);
 
                 graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition());
                 debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding");
@@ -437,14 +420,12 @@
     }
 
     @SuppressWarnings("try")
-    private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph structuredGraph) {
+    private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph graph) {
         // Verify the encoding and decoding process
-        EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(structuredGraph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch);
+        EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch);
 
-        Architecture arch = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch;
-
-        try (DebugContext debug = replacements.openDebugContext("VerifySnippetEncodeDecode_", method)) {
-            HotSpotProviders originalProvider = (HotSpotProviders) replacements.getProviders();
+        try (DebugContext debug = snippetReplacements.openDebugContext("VerifySnippetEncodeDecode_", method, graph.getOptions())) {
+            HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders();
 
             SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection();
             SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider(
@@ -452,29 +433,29 @@
             HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection,
                             originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(),
                             originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins());
-            HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(getOptions(), newProviders, snippetReflection,
-                            originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(),
-                            originalProvider.getCodeCache().getTarget());
+            HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection,
+                            originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget());
             filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins());
-            try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", structuredGraph)) {
+            try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) {
                 for (int i = 0; i < encodedGraph.getNumObjects(); i++) {
                     filterSnippetObject(encodedGraph.getObject(i));
                 }
                 StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original,
                                 trackNodeSourcePosition, null);
                 SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), original != null ? methodKey(original) : null);
-                StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, method, replacements, null, arch);
+                StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null,
+                                StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions());
                 String snippetString = getCanonicalGraphString(snippet, true, false);
                 String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false);
                 if (snippetString.equals(decodedSnippetString)) {
                     debug.log("Snippet decode for %s produces exactly same graph", method);
-                    debug.dump(DebugContext.INFO_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method);
+                    debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method);
                 } else {
                     debug.log("Snippet decode for %s produces different graph", method);
                     debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString));
-                    debug.dump(DebugContext.INFO_LEVEL, snippet, "Snippet graph for %s", method);
-                    debug.dump(DebugContext.INFO_LEVEL, structuredGraph, "Encoded snippet graph for %s", method);
-                    debug.dump(DebugContext.INFO_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method);
+                    debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method);
+                    debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method);
+                    debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method);
                 }
             } catch (Throwable t) {
                 throw debug.handle(t);
@@ -487,10 +468,10 @@
      * If there are new graphs waiting to be encoded, reencode all the graphs and return the result.
      */
     @SuppressWarnings("try")
-    synchronized EncodedSnippets maybeEncodeSnippets() {
+    private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) {
         Map<String, StructuredGraph> graphs = this.preparedSnippetGraphs;
         if (encodedGraphs != graphs.size()) {
-            DebugContext debug = openDebugContext("SnippetEncoder", null);
+            DebugContext debug = openDebugContext("SnippetEncoder", null, options);
             try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) {
                 encodedGraphs = graphs.size();
                 for (StructuredGraph graph : graphs.values()) {
@@ -504,23 +485,23 @@
         return null;
     }
 
-    @Override
-    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
-        if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(getOptions())) {
+    synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
+        if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) {
             assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
             String key = methodKey(method);
             if (!preparedSnippetGraphs.containsKey(key)) {
                 if (original != null) {
                     originalMethods.put(key, methodKey(original));
                 }
-                StructuredGraph snippet = buildGraph(method, original, receiver, true, trackNodeSourcePosition);
+                StructuredGraph snippet = buildGraph(method, original, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options);
                 snippetMethods.add(method);
                 preparedSnippetGraphs.put(key, snippet);
             }
         }
+
     }
 
-    EncodedSnippets encodeSnippets(DebugContext debug) {
+    private synchronized EncodedSnippets encodeSnippets(DebugContext debug) {
         GraphEncoder encoder = new GraphEncoder(HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch, debug);
         for (StructuredGraph graph : preparedSnippetGraphs.values()) {
             encoder.prepare(graph);
@@ -552,8 +533,8 @@
      * Encode any outstanding graphs and return true if any work was done.
      */
     @SuppressWarnings("try")
-    public boolean encode() {
-        EncodedSnippets encodedSnippets = maybeEncodeSnippets();
+    public boolean encode(OptionValues options) {
+        EncodedSnippets encodedSnippets = maybeEncodeSnippets(options);
         if (encodedSnippets != null) {
             HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets);
             return true;
@@ -561,38 +542,65 @@
         return false;
     }
 
-    private DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
-        return replacements.openDebugContext(idPrefix, method);
+    private DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) {
+        return snippetReplacements.openDebugContext(idPrefix, method, options);
     }
 
     static class SymbolicEncodedGraph extends EncodedGraph {
 
-        private final ResolvedJavaType accessingClass;
+        private final ResolvedJavaType[] accessingClasses;
         private final String originalMethod;
 
-        SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, ResolvedJavaType accessingClass, String originalMethod) {
+        SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, String originalMethod, ResolvedJavaType... accessingClasses) {
             super(encoding, startOffset, objects, types, null, null, null, false, false);
-            this.accessingClass = accessingClass;
+            this.accessingClasses = accessingClasses;
             this.originalMethod = originalMethod;
         }
 
         SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod) {
-            this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(), declaringClass, originalMethod);
+            this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(),
+                            originalMethod, declaringClass);
         }
 
         @Override
         public Object getObject(int i) {
             Object o = objects[i];
+            Object replacement = null;
             if (o instanceof SymbolicJVMCIReference) {
-                objects[i] = o = ((SymbolicJVMCIReference<?>) o).resolve(accessingClass);
+                for (ResolvedJavaType type : accessingClasses) {
+                    try {
+                        replacement = ((SymbolicJVMCIReference<?>) o).resolve(type);
+                        break;
+                    } catch (NoClassDefFoundError | AssertionError e) {
+                    }
+                }
             } else if (o instanceof UnresolvedJavaType) {
-                objects[i] = o = ((UnresolvedJavaType) o).resolve(accessingClass);
+                for (ResolvedJavaType type : accessingClasses) {
+                    try {
+                        replacement = ((UnresolvedJavaType) o).resolve(type);
+                        break;
+                    } catch (NoClassDefFoundError | AssertionError e) {
+                    }
+                }
             } else if (o instanceof UnresolvedJavaMethod) {
                 throw new InternalError(o.toString());
             } else if (o instanceof UnresolvedJavaField) {
-                objects[i] = o = ((UnresolvedJavaField) o).resolve(accessingClass);
+                for (ResolvedJavaType type : accessingClasses) {
+                    try {
+                        replacement = ((UnresolvedJavaField) o).resolve(type);
+                        break;
+                    } catch (NoClassDefFoundError | AssertionError e) {
+                    }
+                }
             } else if (o instanceof GraalCapability) {
-                objects[i] = o = ((GraalCapability) o).resolve(((GraalJVMCICompiler) getRuntime().getCompiler()).getGraalRuntime());
+                replacement = ((GraalCapability) o).resolve(((GraalJVMCICompiler) getRuntime().getCompiler()).getGraalRuntime());
+            } else {
+                return o;
+            }
+            if (replacement != null) {
+                objects[i] = o = replacement;
+            } else {
+                throw new GraalError("Can't resolve " + o);
             }
             return o;
         }
@@ -632,7 +640,7 @@
         final String methodName;
         final String signature;
 
-        SymbolicResolvedJavaMethod(HotSpotResolvedJavaMethod method) {
+        SymbolicResolvedJavaMethod(ResolvedJavaMethod method) {
             this.type = UnresolvedJavaType.create(method.getDeclaringClass().getName());
             this.methodName = method.getName();
             this.signature = method.getSignature().toMethodDescriptor();
@@ -650,6 +658,9 @@
         @Override
         public ResolvedJavaMethod resolve(ResolvedJavaType accessingClass) {
             ResolvedJavaType resolvedType = type.resolve(accessingClass);
+            if (resolvedType == null) {
+                throw new InternalError("Could not resolve " + this + " in context of " + accessingClass.toJavaName());
+            }
             for (ResolvedJavaMethod method : methodName.equals("<init>") ? resolvedType.getDeclaredConstructors() : resolvedType.getDeclaredMethods()) {
                 if (method.getName().equals(methodName) && method.getSignature().toMethodDescriptor().equals(signature)) {
                     return method;
@@ -665,7 +676,7 @@
         final UnresolvedJavaType signature;
         private final boolean isStatic;
 
-        SymbolicResolvedJavaField(HotSpotResolvedJavaField field) {
+        SymbolicResolvedJavaField(ResolvedJavaField field) {
             this.declaringType = UnresolvedJavaType.create(field.getDeclaringClass().getName());
             this.name = field.getName();
             this.signature = UnresolvedJavaType.create(field.getType().getName());
@@ -697,6 +708,19 @@
         }
     }
 
+    static class SymbolicResolvedJavaMethodBytecode implements SymbolicJVMCIReference<ResolvedJavaMethodBytecode> {
+        SymbolicResolvedJavaMethod method;
+
+        SymbolicResolvedJavaMethodBytecode(ResolvedJavaMethodBytecode bytecode) {
+            method = new SymbolicResolvedJavaMethod(bytecode.getMethod());
+        }
+
+        @Override
+        public ResolvedJavaMethodBytecode resolve(ResolvedJavaType accessingClass) {
+            return new ResolvedJavaMethodBytecode(method.resolve(accessingClass));
+        }
+    }
+
     static class SymbolicStampPair implements SymbolicJVMCIReference<StampPair> {
         Object trustedStamp;
         Object uncheckdStamp;
@@ -820,13 +844,13 @@
      * Objects embedded in encoded graphs might need to converted into a symbolic form so convert
      * the object or pass it through.
      */
-    static Object filterSnippetObject(Object o) {
+    private static Object filterSnippetObject(Object o) {
         if (o instanceof HotSpotResolvedJavaMethod) {
             return new SymbolicResolvedJavaMethod((HotSpotResolvedJavaMethod) o);
         } else if (o instanceof HotSpotResolvedJavaField) {
             return new SymbolicResolvedJavaField((HotSpotResolvedJavaField) o);
         } else if (o instanceof HotSpotResolvedJavaType) {
-            return UnresolvedJavaType.create(((HotSpotResolvedJavaType) o).getName());
+            return UnresolvedJavaType.create(((ResolvedJavaType) o).getName());
         } else if (o instanceof NodeSourcePosition) {
             // Filter these out for now. These can't easily be handled because these positions
             // description snippet methods which might not be available in the runtime.
@@ -843,11 +867,15 @@
             if (((StampPair) o).getTrustedStamp() instanceof AbstractObjectStamp) {
                 return new SymbolicStampPair((StampPair) o);
             }
+        } else if (o instanceof ResolvedJavaMethodBytecode) {
+            return new SymbolicResolvedJavaMethodBytecode((ResolvedJavaMethodBytecode) o);
+        } else if (o instanceof HotSpotSignature) {
+            throw new GraalError(o.toString());
         }
         return o;
     }
 
-    static String compareGraphStrings(StructuredGraph expectedGraph, String expectedString, StructuredGraph actualGraph, String actualString) {
+    private static String compareGraphStrings(StructuredGraph expectedGraph, String expectedString, StructuredGraph actualGraph, String actualString) {
         if (!expectedString.equals(actualString)) {
             String[] expectedLines = expectedString.split("\n");
             String[] actualLines = actualString.split("\n");
@@ -883,7 +911,7 @@
         }
     }
 
-    static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) {
+    private static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) {
         SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST);
         schedule.apply(graph);
         StructuredGraph.ScheduleResult scheduleResult = graph.getLastSchedule();
@@ -968,8 +996,8 @@
             super(replacements, providers);
         }
 
-        HotSpotSnippetReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
-            super(options, providers, snippetReflection, bytecodeProvider, target);
+        HotSpotSnippetReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
+            super(providers, snippetReflection, bytecodeProvider, target);
         }
 
         @Override
@@ -1009,14 +1037,25 @@
 
         @Override
         public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) {
+            // Fold is always deferred but NodeIntrinsics may have to wait if all their arguments
+            // aren't constant yet.
             return plugin.getSource().equals(Fold.class) || plugin.getSource().equals(Node.NodeIntrinsic.class);
         }
 
         @Override
+        protected boolean canInlinePartialIntrinsicExit() {
+            return false;
+        }
+
+        @Override
         protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
             if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
                 return false;
             }
+            if (targetMethod.getAnnotation(Fold.class) != null) {
+                // Always defer Fold until decode time but NodeIntrinsics may fold if they are able.
+                return false;
+            }
             return super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -26,6 +26,7 @@
 
 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
 import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs;
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs;
 import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
@@ -161,7 +162,7 @@
 import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
 import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
 import org.graalvm.compiler.replacements.arraycopy.ArrayCopySnippets;
-import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithSlowPathNode;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopyWithDelayedLoweringNode;
 import org.graalvm.compiler.replacements.nodes.AssertionNode;
 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 import jdk.internal.vm.compiler.word.LocationIdentity;
@@ -227,13 +228,17 @@
         stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target);
         hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
         resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
-        if (!JavaVersionUtil.Java8OrEarlier) {
+        if (!JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)) {
             profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
         }
         objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
         foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
     }
 
+    public ArrayCopySnippets.Templates getArraycopySnippets() {
+        return arraycopySnippets;
+    }
+
     public MonitorSnippets.Templates getMonitorSnippets() {
         return monitorSnippets;
     }
@@ -332,8 +337,8 @@
                 }
             } else if (n instanceof ArrayCopyNode) {
                 arraycopySnippets.lower((ArrayCopyNode) n, tool);
-            } else if (n instanceof ArrayCopyWithSlowPathNode) {
-                arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool);
+            } else if (n instanceof ArrayCopyWithDelayedLoweringNode) {
+                arraycopySnippets.lower((ArrayCopyWithDelayedLoweringNode) n, tool);
             } else if (n instanceof G1PreWriteBarrier) {
                 writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
             } else if (n instanceof G1PostWriteBarrier) {
@@ -468,11 +473,15 @@
         if (invoke.callTarget() instanceof MethodCallTargetNode) {
             MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
             NodeInputList<ValueNode> parameters = callTarget.arguments();
-            ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
-            if (!callTarget.isStatic() && receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) {
-                ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool);
-                parameters.set(0, nonNullReceiver);
-                receiver = nonNullReceiver;
+            ValueNode receiver = parameters.isEmpty() ? null : parameters.get(0);
+
+            if (!callTarget.isStatic()) {
+                assert receiver != null : "non-static call must have a receiver";
+                if (receiver.stamp(NodeView.DEFAULT) instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) {
+                    ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool);
+                    parameters.set(0, nonNullReceiver);
+                    receiver = nonNullReceiver;
+                }
             }
             JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java	Fri May 03 14:59:32 2019 -0400
@@ -24,13 +24,11 @@
 
 package org.graalvm.compiler.hotspot.meta;
 
-import java.lang.reflect.Method;
 import java.util.function.Supplier;
 
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
 import org.graalvm.compiler.nodes.ConstantNode;
@@ -40,6 +38,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 
+import jdk.vm.ci.hotspot.HotSpotConstantPool;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -85,44 +84,17 @@
         return false;
     }
 
-    private static final Class<? extends ConstantPool> hscp;
-    private static final Method loadReferencedTypeIIZMH;
-
-    static {
-        Method m = null;
-        Class<? extends ConstantPool> c = null;
-        try {
-            c = Class.forName("jdk.vm.ci.hotspot.HotSpotConstantPool").asSubclass(ConstantPool.class);
-            m = c.getDeclaredMethod("loadReferencedType", int.class, int.class, boolean.class);
-        } catch (Exception e) {
-            throw GraalError.shouldNotReachHere(e);
-        }
-        loadReferencedTypeIIZMH = m;
-        hscp = c;
-    }
-
-    private static boolean isHotSpotConstantPool(ConstantPool cp) {
+    @Override
+    public boolean supportsLazyInitialization(ConstantPool cp) {
         // jdk.vm.ci.hotspot.HotSpotConstantPool is final, so we can
         // directly compare Classes.
-        return cp.getClass() == hscp;
-    }
-
-    @Override
-    public boolean supportsLazyInitialization(ConstantPool cp) {
-        if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) {
-            return true;
-        }
-        return false;
+        return (cp instanceof HotSpotConstantPool);
     }
 
     @Override
     public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int cpi, int opcode) {
-        if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) {
-            try {
-                loadReferencedTypeIIZMH.invoke(cp, cpi, opcode, false);
-            } catch (Throwable t) {
-                throw GraalError.shouldNotReachHere(t);
-            }
+        if (cp instanceof HotSpotConstantPool) {
+            ((HotSpotConstantPool) cp).loadReferencedType(cpi, opcode, false);
         } else {
             cp.loadReferencedType(cpi, opcode);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -35,6 +35,7 @@
 import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
@@ -207,11 +208,19 @@
     public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
         assert foreignCalls != null : descriptor;
         HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor);
+        if (callTarget == null) {
+            throw GraalError.shouldNotReachHere("missing implementation for runtime call: " + descriptor);
+        }
         callTarget.finalizeAddress(runtime.getHostBackend());
         return callTarget;
     }
 
     @Override
+    public boolean isAvailable(ForeignCallDescriptor descriptor) {
+        return foreignCalls.containsKey(descriptor);
+    }
+
+    @Override
     public boolean isReexecutable(ForeignCallDescriptor descriptor) {
         assert foreignCalls.containsKey(descriptor) : "unknown foreign call: " + descriptor;
         return foreignCalls.get(descriptor).isReexecutable();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Fri May 03 14:59:32 2019 -0400
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot.meta;
 
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
+import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS;
 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION;
@@ -123,9 +124,11 @@
      * @param constantReflection
      * @param snippetReflection
      * @param foreignCalls
+     * @param options
      */
     public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess,
-                    ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ReplacementsImpl replacements) {
+                    ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ReplacementsImpl replacements,
+                    OptionValues options) {
         InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration);
 
         Plugins plugins = new Plugins(invocationPlugins);
@@ -135,7 +138,6 @@
 
         plugins.appendTypePlugin(nodePlugin);
         plugins.appendNodePlugin(nodePlugin);
-        OptionValues options = replacements.getOptions();
         if (!GeneratePIC.getValue(options)) {
             plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true));
         }
@@ -172,6 +174,7 @@
                 registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
                 registerGHASHPlugins(invocationPlugins, config, metaAccess, foreignCalls);
                 registerCounterModePlugins(invocationPlugins, config, replacementBytecodeProvider);
+                registerBase64Plugins(invocationPlugins, config, metaAccess, foreignCalls);
                 registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider);
                 StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true, false);
                 registerArrayPlugins(invocationPlugins, replacementBytecodeProvider);
@@ -563,6 +566,38 @@
         }
     }
 
+    private static void registerBase64Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) {
+        if (config.useBase64Intrinsics()) {
+            Registration r = new Registration(plugins, "java.util.Base64$Encoder");
+            r.register7("encodeBlock",
+                            Receiver.class,
+                            byte[].class,
+                            int.class,
+                            int.class,
+                            byte[].class,
+                            int.class,
+                            boolean.class,
+                            new InvocationPlugin() {
+                                @Override
+                                public boolean apply(GraphBuilderContext b,
+                                                ResolvedJavaMethod targetMethod,
+                                                Receiver receiver,
+                                                ValueNode src,
+                                                ValueNode sp,
+                                                ValueNode sl,
+                                                ValueNode dst,
+                                                ValueNode dp,
+                                                ValueNode isURL) {
+                                    int byteArrayBaseOffset = metaAccess.getArrayBaseOffset(JavaKind.Byte);
+                                    ComputeObjectAddressNode srcAddress = b.add(new ComputeObjectAddressNode(src, ConstantNode.forInt(byteArrayBaseOffset)));
+                                    ComputeObjectAddressNode dstAddress = b.add(new ComputeObjectAddressNode(dst, ConstantNode.forInt(byteArrayBaseOffset)));
+                                    b.add(new ForeignCallNode(foreignCalls, BASE64_ENCODE_BLOCK, srcAddress, sp, sl, dstAddress, dp, isURL));
+                                    return true;
+                                }
+                            });
+        }
+    }
+
     private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
         if (config.useCRC32Intrinsics) {
             Registration r = new Registration(plugins, CRC32.class, bytecodeProvider);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -29,6 +29,7 @@
 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM;
 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT;
+import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.COUNTERMODE_IMPL_CRYPT;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK;
@@ -72,7 +73,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
-import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
+import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.STACK_INSPECTABLE_LEAF;
 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER;
@@ -217,7 +218,7 @@
         String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + (uninit ? "Uninit" : "") + "Arraycopy" + (killAny ? "KillAny" : "");
         ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class);
         LocationIdentity killed = killAny ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(kind);
-        registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+        registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed);
         return desc;
     }
 
@@ -232,7 +233,7 @@
         // return: 0 = success, n = number of copied elements xor'd with -1.
         ForeignCallDescriptor desc = new ForeignCallDescriptor(name, int.class, Word.class, Word.class, Word.class, Word.class, Word.class);
         LocationIdentity killed = NamedLocationIdentity.any();
-        registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+        registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed);
         checkcastArraycopyDescriptors[uninit ? 1 : 0] = desc;
     }
 
@@ -272,25 +273,25 @@
 
     public void initialize(HotSpotProviders providers, OptionValues options) {
         GraalHotSpotVMConfig c = runtime.getVMConfig();
-        registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
 
         if (c.enableStackReservedZoneAddress != 0) {
             assert c.throwDelayedStackOverflowErrorEntry != 0 : "both must exist";
-            registerForeignCall(ENABLE_STACK_RESERVED_ZONE, c.enableStackReservedZoneAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-            registerForeignCall(THROW_DELAYED_STACKOVERFLOW_ERROR, c.throwDelayedStackOverflowErrorEntry, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+            registerForeignCall(ENABLE_STACK_RESERVED_ZONE, c.enableStackReservedZoneAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+            registerForeignCall(THROW_DELAYED_STACKOVERFLOW_ERROR, c.throwDelayedStackOverflowErrorEntry, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
         }
 
-        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
 
         registerMathStubs(c, providers, options);
 
         registerForeignCall(ARITHMETIC_FREM, c.fremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_DREM, c.dremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
+        registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
 
         registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
         registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
@@ -318,7 +319,7 @@
 
         link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER)));
         link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any())));
-        link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS)));
+        link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS)));
 
         EnumMap<BytecodeExceptionKind, ForeignCallDescriptor> exceptionRuntimeCalls = DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls;
         link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), SAFEPOINT, REEXECUTABLE, any())));
@@ -338,14 +339,14 @@
         linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS);
-        linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS);
+        linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
 
         if (GeneratePIC.getValue(options)) {
-            registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+            registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
             CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore());
             linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
             linkForeignCall(options, providers, RESOLVE_DYNAMIC_INVOKE, cr.resolveDynamicInvoke, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
@@ -375,11 +376,11 @@
         registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
         registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
 
-        registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
-        registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
+        registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
+        registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
 
         if (c.useMultiplyToLenIntrinsic()) {
-            registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+            registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
         }
 
@@ -398,19 +399,22 @@
         if (c.useGHASHIntrinsics()) {
             registerForeignCall(GHASH_PROCESS_BLOCKS, c.ghashProcessBlocks, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
         }
+        if (c.useBase64Intrinsics()) {
+            registerForeignCall(BASE64_ENCODE_BLOCK, c.base64EncodeBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
+        }
         if (c.useMulAddIntrinsic()) {
-            registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+            registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
         }
         if (c.useMontgomeryMultiplyIntrinsic()) {
-            registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+            registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
         }
         if (c.useMontgomerySquareIntrinsic()) {
-            registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
+            registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
         }
         if (c.useSquareToLenIntrinsic()) {
-            registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
+            registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
         }
 
         if (c.useAESIntrinsics) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -65,8 +65,9 @@
     }
 
     @Override
-    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-        final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) {
+        OptionValues options = calleeInfo.graph().getOptions();
+        final boolean isTracing = GraalOptions.TraceInlining.getValue(options);
         final InlineInfo info = invocation.callee();
 
         for (int i = 0; i < info.numberOfMethods(); ++i) {
@@ -79,7 +80,6 @@
         final double probability = invocation.probability();
         final double relevance = invocation.relevance();
 
-        OptionValues options = info.graph().getOptions();
         if (InlineEverything.getValue(options)) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
             return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Fri May 03 14:59:32 2019 -0400
@@ -160,7 +160,7 @@
                 return field.getOffset();
             }
         }
-        throw new GraalError("missing field " + fieldName);
+        throw new GraalError("missing field " + fieldName + " in type " + type);
     }
 
     public static HotSpotJVMCIRuntime runtime() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Fri May 03 14:59:32 2019 -0400
@@ -831,7 +831,8 @@
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
 
-                    StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null, invoke.graph().trackNodeSourcePosition(), invoke.getNodeSourcePosition());
+                    StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null, null, invoke.graph().trackNodeSourcePosition(), invoke.getNodeSourcePosition(),
+                                    invoke.getOptions());
                     InliningUtil.inline(invoke, inlineeGraph, false, null);
 
                     List<ReturnNode> rets = graph.getNodes(ReturnNode.TYPE).snapshot();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Fri May 03 14:59:32 2019 -0400
@@ -89,7 +89,7 @@
                     StructuredGraph snippetGraph = null;
                     DebugContext debug = getDebug();
                     try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) {
-                        snippetGraph = replacements.getSnippet(snippetMethod, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition());
+                        snippetGraph = replacements.getSnippet(snippetMethod, null, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition(), debug.getOptions());
                     } catch (Throwable e) {
                         throw debug.handle(e);
                     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java	Fri May 03 14:59:32 2019 -0400
@@ -84,7 +84,7 @@
     }
 
     protected void registerSnippet() {
-        providers.getReplacements().registerSnippet(method, null, null, false);
+        providers.getReplacements().registerSnippet(method, null, null, false, options);
     }
 
     @Override
@@ -115,7 +115,7 @@
     }
 
     protected StructuredGraph buildInitialGraph(DebugContext debug, CompilationIdentifier compilationId, Object[] args) {
-        return providers.getReplacements().getSnippet(method, args, false, null).copyWithIdentifier(compilationId, debug);
+        return providers.getReplacements().getSnippet(method, null, args, false, null, options).copyWithIdentifier(compilationId, debug);
     }
 
     protected boolean checkConstArg(int index, String expectedName) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Fri May 03 14:59:32 2019 -0400
@@ -183,7 +183,7 @@
             Description description = new Description(linkage, "Stub_" + nextStubId.incrementAndGet());
             return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())));
         }
-        return DebugContext.DISABLED;
+        return DebugContext.disabled(options);
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java	Fri May 03 14:59:32 2019 -0400
@@ -900,8 +900,7 @@
         assert next == newBlocks.length - 1;
 
         // Add unwind block.
-        int deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
-        ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(deoptBci);
+        ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(BytecodeFrame.AFTER_EXCEPTION_BCI);
         unwindBlock.setId(newBlocks.length - 1);
         newBlocks[newBlocks.length - 1] = unwindBlock;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
 import static java.lang.String.format;
 import static java.lang.reflect.Modifier.STATIC;
 import static java.lang.reflect.Modifier.SYNCHRONIZED;
+import static jdk.vm.ci.code.BytecodeFrame.UNKNOWN_BCI;
 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
 import static jdk.vm.ci.meta.DeoptimizationAction.None;
@@ -256,7 +257,7 @@
 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
 import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
@@ -271,6 +272,7 @@
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
 import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.bytecode.Bytecode;
@@ -383,6 +385,7 @@
 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
 import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode;
@@ -488,10 +491,11 @@
     protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions");
 
     /**
-     * A scoped object for tasks to be performed after parsing an intrinsic such as processing
+     * A scoped object for tasks to be performed after inlining during parsing such as processing
      * {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states.
      */
-    static class IntrinsicScope implements AutoCloseable {
+    static class InliningScope implements AutoCloseable {
+        final ResolvedJavaMethod callee;
         FrameState stateBefore;
         final Mark mark;
         final BytecodeParser parser;
@@ -502,44 +506,41 @@
          *
          * @param parser the parsing context of the intrinsic
          */
-        IntrinsicScope(BytecodeParser parser) {
+        InliningScope(BytecodeParser parser) {
             this.parser = parser;
             assert parser.parent == null;
             assert parser.bci() == 0;
             mark = null;
+            callee = null;
         }
 
         /**
-         * Creates a scope for parsing an intrinsic during graph builder inlining.
+         * Creates a scope for graph builder inlining.
          *
          * @param parser the parsing context of the (non-intrinsic) method calling the intrinsic
          * @param args the arguments to the call
          */
-        IntrinsicScope(BytecodeParser parser, JavaKind[] argSlotKinds, ValueNode[] args) {
+        InliningScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) {
+            this.callee = callee;
             assert !parser.parsingIntrinsic();
             this.parser = parser;
             mark = parser.getGraph().getMark();
+            JavaKind[] argSlotKinds = callee.getSignature().toParameterKinds(!callee.isStatic());
             stateBefore = parser.frameState.create(parser.bci(), parser.getNonIntrinsicAncestor(), false, argSlotKinds, args);
         }
 
         @Override
         public void close() {
-            IntrinsicContext intrinsic = parser.intrinsicContext;
-            if (intrinsic != null && intrinsic.isPostParseInlined()) {
-                return;
-            }
-
-            processPlaceholderFrameStates(intrinsic);
+            processPlaceholderFrameStates(false);
         }
 
         /**
          * Fixes up the {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frame states
          * added to the graph while parsing/inlining the intrinsic for which this object exists.
          */
-        private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
+        protected void processPlaceholderFrameStates(boolean isCompilationRoot) {
             StructuredGraph graph = parser.getGraph();
             graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method);
-            boolean sawInvalidFrameState = false;
             for (Node node : graph.getNewNodes(mark)) {
                 if (node instanceof FrameState) {
                     FrameState frameState = (FrameState) node;
@@ -547,7 +548,7 @@
                         if (frameState.bci == BytecodeFrame.AFTER_BCI) {
                             if (parser.getInvokeReturnType() == null) {
                                 // A frame state in a root compiled intrinsic.
-                                assert intrinsic.isCompilationRoot();
+                                assert isCompilationRoot;
                                 FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
                                 frameState.replaceAndDelete(newFrameState);
                             } else {
@@ -557,7 +558,7 @@
                                 if (frameState.stackSize() != 0) {
                                     ValueNode returnVal = frameState.stackAt(0);
                                     if (!ReturnToCallerData.containsReturnValue(returnDataList, returnVal)) {
-                                        throw new GraalError("AFTER_BCI frame state within an intrinsic has a non-return value on the stack: %s", returnVal);
+                                        throw new GraalError("AFTER_BCI frame state within a sub-parse has a non-return value on the stack: %s", returnVal);
                                     }
 
                                     // Swap the top-of-stack value with the return value
@@ -569,15 +570,7 @@
                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
                                     frameStateBuilder.push(returnKind, tos);
                                 } else if (returnKind != JavaKind.Void) {
-                                    // If the intrinsic returns a non-void value, then any frame
-                                    // state with an empty stack is invalid as it cannot
-                                    // be used to deoptimize to just after the call returns.
-                                    // These invalid frame states are expected to be removed
-                                    // by later compilation stages.
-                                    FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
-                                    newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
-                                    frameState.replaceAndDelete(newFrameState);
-                                    sawInvalidFrameState = true;
+                                    handleReturnMismatch(graph, frameState);
                                 } else {
                                     // An intrinsic for a void method.
                                     FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null);
@@ -592,7 +585,7 @@
                             if (stateBefore != frameState) {
                                 frameState.replaceAndDelete(stateBefore);
                             }
-                        } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+                        } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !callee.isSynchronized())) {
                             // This is a frame state for the entry point to an exception
                             // dispatcher in an intrinsic. For example, the invoke denoting
                             // a partial intrinsic exit will have an edge to such a
@@ -603,41 +596,102 @@
                             // namely the exception object.
                             assert frameState.rethrowException();
                             ValueNode exceptionValue = frameState.stackAt(0);
-                            ExceptionObjectNode exceptionObject = (ExceptionObjectNode) GraphUtil.unproxify(exceptionValue);
                             FrameStateBuilder dispatchState = parser.frameState.copy();
                             dispatchState.clearStack();
                             dispatchState.push(JavaKind.Object, exceptionValue);
                             dispatchState.setRethrowException(true);
-                            FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject);
-                            frameState.replaceAndDelete(newFrameState);
-                            newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
+                            for (Node usage : frameState.usages()) {
+                                FrameState newFrameState = dispatchState.create(parser.bci(), (StateSplit) usage);
+                                frameState.replaceAndDelete(newFrameState);
+                                newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
+                            }
+                        } else if (frameState.bci == BytecodeFrame.UNWIND_BCI) {
+                            if (graph.getGuardsStage().allowsFloatingGuards()) {
+                                throw GraalError.shouldNotReachHere("Cannot handle this UNWIND_BCI");
+                            }
+                            // hope that by construction, there are no fixed guard after this unwind
+                            // and before an other state split
                         } else {
-                            assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
+                            assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI : frameState.bci;
                         }
                     }
                 }
             }
+            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
+        }
+
+        @SuppressWarnings("unused")
+        protected void handleReturnMismatch(StructuredGraph g, FrameState fs) {
+            throw GraalError.shouldNotReachHere("Unexpected return kind mismatch in " + parser.method + " at FS " + fs);
+        }
+    }
+
+    static class IntrinsicScope extends InliningScope {
+        boolean sawInvalidFrameState;
+
+        IntrinsicScope(BytecodeParser parser) {
+            super(parser);
+        }
+
+        IntrinsicScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) {
+            super(parser, callee, args);
+        }
+
+        @Override
+        public void close() {
+            IntrinsicContext intrinsic = parser.intrinsicContext;
+            boolean isRootCompilation;
+            if (intrinsic != null) {
+                if (intrinsic.isPostParseInlined()) {
+                    return;
+                }
+                isRootCompilation = intrinsic.isCompilationRoot();
+            } else {
+                isRootCompilation = false;
+            }
+            processPlaceholderFrameStates(isRootCompilation);
             if (sawInvalidFrameState) {
                 JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
                 FrameStateBuilder frameStateBuilder = parser.frameState;
                 ValueNode returnValue = frameStateBuilder.pop(returnKind);
+                StructuredGraph graph = parser.lastInstr.graph();
                 StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
                 parser.lastInstr.setNext(proxy);
                 frameStateBuilder.push(returnKind, proxy);
                 proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
                 parser.lastInstr = proxy;
             }
-            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
+        }
+
+        @Override
+        protected void handleReturnMismatch(StructuredGraph g, FrameState fs) {
+            // If the intrinsic returns a non-void value, then any frame
+            // state with an empty stack is invalid as it cannot
+            // be used to deoptimize to just after the call returns.
+            // These invalid frame states are expected to be removed
+            // by later compilation stages.
+            FrameState newFrameState = g.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
+            newFrameState.setNodeSourcePosition(fs.getNodeSourcePosition());
+            fs.replaceAndDelete(newFrameState);
+            sawInvalidFrameState = true;
         }
     }
 
     private static class Target {
-        FixedNode fixed;
-        FrameStateBuilder state;
-
-        Target(FixedNode fixed, FrameStateBuilder state) {
-            this.fixed = fixed;
+        final FixedNode entry;
+        final FixedNode originalEntry;
+        final FrameStateBuilder state;
+
+        Target(FixedNode entry, FrameStateBuilder state) {
+            this.entry = entry;
             this.state = state;
+            this.originalEntry = null;
+        }
+
+        Target(FixedNode entry, FrameStateBuilder state, FixedNode originalEntry) {
+            this.entry = entry;
+            this.state = state;
+            this.originalEntry = originalEntry;
         }
     }
 
@@ -1748,7 +1802,7 @@
                 // edge. Finally, we know that this intrinsic is parsed for late inlining,
                 // so the bci must be set to unknown, so that the inliner patches it later.
                 assert intrinsicContext.isPostParseInlined();
-                invokeBci = BytecodeFrame.UNKNOWN_BCI;
+                invokeBci = UNKNOWN_BCI;
                 profile = null;
                 edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
             }
@@ -2064,7 +2118,14 @@
 
             AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
             AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
-            append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
+            // In the adjustment above, we filter out receiver types that select the intrinsic as
+            // virtual call target. This means the recorded types in the adjusted profile will
+            // definitely not call into the intrinsic. Note that the following branch probability is
+            // still not precise -- the previously-not-recorded receiver types in the original
+            // profile might or might not call into the intrinsic. Yet we accumulate them into the
+            // probability of the intrinsic branch, assuming that the not-recorded types will only
+            // be a small fraction.
+            append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, profile != null ? profile.getNotRecordedProbability() : LIKELY_PROBABILITY));
             lastInstr = intrinsicBranch;
             return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
         } else {
@@ -2223,7 +2284,7 @@
         for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
             InlineInfo inlineInfo = plugin.shouldInlineInvoke(this, targetMethod, args);
             if (inlineInfo != null) {
-                if (inlineInfo.getMethodToInline() != null) {
+                if (inlineInfo.allowsInlining()) {
                     if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) {
                         return SUCCESSFULLY_INLINED;
                     }
@@ -2277,6 +2338,134 @@
         return false;
     }
 
+    /**
+     * Inline a method substitution graph. This is necessary for libgraal as substitutions only
+     * exist as encoded graphs and can't be parsed directly into the caller.
+     */
+    @Override
+    @SuppressWarnings("try")
+    public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] args) {
+        if (receiver != null) {
+            receiver.get();
+        }
+
+        InvokeWithExceptionNode withException = null;
+        FixedWithNextNode replacee = lastInstr;
+        try (DebugContext.Scope a = debug.scope("instantiate", substituteGraph)) {
+            // Inline the snippet nodes, replacing parameters with the given args in the process
+            StartNode entryPointNode = substituteGraph.start();
+            FixedNode firstCFGNode = entryPointNode.next();
+            StructuredGraph replaceeGraph = replacee.graph();
+            Mark mark = replaceeGraph.getMark();
+            try (InliningScope inlineScope = new IntrinsicScope(this, targetMethod, args)) {
+
+                EconomicMap<Node, Node> replacementsMap = EconomicMap.create(Equivalence.IDENTITY);
+                for (ParameterNode param : substituteGraph.getNodes().filter(ParameterNode.class)) {
+                    replacementsMap.put(param, args[param.index()]);
+                }
+                replacementsMap.put(entryPointNode, AbstractBeginNode.prevBegin(replacee));
+
+                debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "Before inlining method substitution %s", substituteGraph.method());
+                UnmodifiableEconomicMap<Node, Node> duplicates = inlineMethodSubstitution(replaceeGraph, substituteGraph, replacementsMap);
+
+                FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
+                replacee.setNext(firstCFGNodeDuplicate);
+                debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining method substitution %s", substituteGraph.method());
+
+                // Handle partial intrinsic exits
+                for (Node node : graph.getNewNodes(mark)) {
+                    if (node instanceof Invoke) {
+                        Invoke invoke = (Invoke) node;
+                        if (invoke.bci() == BytecodeFrame.UNKNOWN_BCI) {
+                            invoke.replaceBci(bci());
+                        }
+                        if (node instanceof InvokeWithExceptionNode) {
+                            // The graphs for MethodSubsitutions are produced assuming that
+                            // exceptions
+                            // must be dispatched. If the calling context doesn't want exception
+                            // then
+                            // convert back into a normal InvokeNode.
+                            assert withException == null : "only one invoke expected";
+                            withException = (InvokeWithExceptionNode) node;
+                            BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
+                            if (intrinsicCallSiteParser != null && intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null) == ExceptionEdgeAction.OMIT) {
+                                InvokeNode newInvoke = graph.add(new InvokeNode(withException));
+                                newInvoke.setStateDuring(withException.stateDuring());
+                                newInvoke.setStateAfter(withException.stateAfter());
+                                withException.killExceptionEdge();
+                                AbstractBeginNode next = withException.killKillingBegin();
+                                FixedWithNextNode pred = (FixedWithNextNode) withException.predecessor();
+                                pred.setNext(newInvoke);
+                                withException.setNext(null);
+                                newInvoke.setNext(next);
+                                withException.replaceAndDelete(newInvoke);
+                            } else {
+                                // Disconnnect exception edge
+                                withException.killExceptionEdge();
+                            }
+                        }
+                    } else if (node instanceof ForeignCallNode) {
+                        ForeignCallNode call = (ForeignCallNode) node;
+                        if (call.getBci() == BytecodeFrame.UNKNOWN_BCI) {
+                            call.setBci(bci());
+                            if (call.stateAfter() != null && call.stateAfter().bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+                                call.setStateAfter(inlineScope.stateBefore);
+                            }
+                        }
+                    }
+                }
+
+                ArrayList<ReturnToCallerData> calleeReturnDataList = new ArrayList<>();
+                for (ReturnNode n : substituteGraph.getNodes().filter(ReturnNode.class)) {
+                    ReturnNode returnNode = (ReturnNode) duplicates.get(n);
+                    FixedWithNextNode predecessor = (FixedWithNextNode) returnNode.predecessor();
+                    calleeReturnDataList.add(new ReturnToCallerData(returnNode.result(), predecessor));
+                    predecessor.setNext(null);
+                    returnNode.safeDelete();
+                }
+
+                // Merge multiple returns
+                processCalleeReturn(targetMethod, inlineScope, calleeReturnDataList);
+
+                // Exiting this scope causes processing of the placeholder frame states.
+            }
+
+            if (withException != null && withException.isAlive()) {
+                // Connect exception edge into main graph
+                AbstractBeginNode exceptionEdge = handleException(null, bci(), false);
+                withException.setExceptionEdge(exceptionEdge);
+            }
+
+            debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
+            return true;
+        } catch (Throwable t) {
+            throw debug.handle(t);
+        }
+    }
+
+    private static UnmodifiableEconomicMap<Node, Node> inlineMethodSubstitution(StructuredGraph replaceeGraph, StructuredGraph snippet,
+                    EconomicMap<Node, Node> replacementsMap) {
+        try (InliningLog.UpdateScope scope = replaceeGraph.getInliningLog().openUpdateScope((oldNode, newNode) -> {
+            InliningLog log = replaceeGraph.getInliningLog();
+            if (oldNode == null) {
+                log.trackNewCallsite(newNode);
+            }
+        })) {
+            StartNode entryPointNode = snippet.start();
+            ArrayList<Node> nodes = new ArrayList<>(snippet.getNodeCount());
+            for (Node node : snippet.getNodes()) {
+                if (node != entryPointNode && node != entryPointNode.stateAfter()) {
+                    nodes.add(node);
+                }
+            }
+            UnmodifiableEconomicMap<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacementsMap);
+            if (scope != null) {
+                replaceeGraph.getInliningLog().addLog(duplicates, snippet.getInliningLog());
+            }
+            return duplicates;
+        }
+    }
+
     @Override
     public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) {
         if (receiver != null) {
@@ -2441,7 +2630,8 @@
         FixedWithNextNode calleeBeforeUnwindNode = null;
         ValueNode calleeUnwindValue = null;
 
-        try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) {
+        try (InliningScope s = parsingIntrinsic() ? null : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args)
+                        : new InliningScope(this, targetMethod, args))) {
             BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
             FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables());
             if (!targetMethod.isStatic()) {
@@ -2450,35 +2640,9 @@
             startFrameState.initializeFromArgumentsArray(args);
             parser.build(this.lastInstr, startFrameState);
 
-            if (parser.returnDataList == null) {
-                /* Callee does not return. */
-                lastInstr = null;
-            } else {
-                ValueNode calleeReturnValue;
-                MergeNode returnMergeNode = null;
-                if (s != null) {
-                    s.returnDataList = parser.returnDataList;
-                }
-                if (parser.returnDataList.size() == 1) {
-                    /* Callee has a single return, we can continue parsing at that point. */
-                    ReturnToCallerData singleReturnData = parser.returnDataList.get(0);
-                    lastInstr = singleReturnData.beforeReturnNode;
-                    calleeReturnValue = singleReturnData.returnValue;
-                } else {
-                    assert parser.returnDataList.size() > 1;
-                    /* Callee has multiple returns, we need to insert a control flow merge. */
-                    returnMergeNode = graph.add(new MergeNode());
-                    calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue);
-                }
-
-                if (calleeReturnValue != null) {
-                    frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
-                }
-                if (returnMergeNode != null) {
-                    returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
-                    lastInstr = finishInstruction(returnMergeNode, frameState);
-                }
-            }
+            List<ReturnToCallerData> calleeReturnDataList = parser.returnDataList;
+
+            processCalleeReturn(targetMethod, s, calleeReturnDataList);
             /*
              * Propagate any side effects into the caller when parsing intrinsics.
              */
@@ -2509,6 +2673,40 @@
         }
     }
 
+    private ValueNode processCalleeReturn(ResolvedJavaMethod targetMethod, InliningScope inliningScope, List<ReturnToCallerData> calleeReturnDataList) {
+        if (calleeReturnDataList == null) {
+            /* Callee does not return. */
+            lastInstr = null;
+        } else {
+            ValueNode calleeReturnValue;
+            MergeNode returnMergeNode = null;
+            if (inliningScope != null) {
+                inliningScope.returnDataList = calleeReturnDataList;
+            }
+            if (calleeReturnDataList.size() == 1) {
+                /* Callee has a single return, we can continue parsing at that point. */
+                ReturnToCallerData singleReturnData = calleeReturnDataList.get(0);
+                lastInstr = singleReturnData.beforeReturnNode;
+                calleeReturnValue = singleReturnData.returnValue;
+            } else {
+                assert calleeReturnDataList.size() > 1;
+                /* Callee has multiple returns, we need to insert a control flow merge. */
+                returnMergeNode = graph.add(new MergeNode());
+                calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, calleeReturnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue);
+            }
+
+            if (calleeReturnValue != null) {
+                frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
+            }
+            if (returnMergeNode != null) {
+                returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
+                lastInstr = finishInstruction(returnMergeNode, frameState);
+            }
+            return calleeReturnValue;
+        }
+        return null;
+    }
+
     public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
         return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile);
     }
@@ -2566,7 +2764,7 @@
                         /*
                          * This must be the return value from within a partial intrinsification.
                          */
-                        assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
+                        assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci) || intrinsicContext.isDeferredInvoke(stateSplit);
                     }
                 } else {
                     assert stateAfter == null;
@@ -2628,6 +2826,9 @@
             append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null));
         }
         synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind);
+        if (method.isSynchronized()) {
+            finishPrepare(lastInstr, BytecodeFrame.AFTER_BCI, frameState);
+        }
     }
 
     protected MonitorEnterNode createMonitorEnterNode(ValueNode x, MonitorIdNode monitorId) {
@@ -2641,7 +2842,7 @@
         monitorEnter.setStateAfter(createFrameState(bci, monitorEnter));
     }
 
-    protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) {
+    protected void genMonitorExit(ValueNode x, ValueNode escapedValue, int bci) {
         if (frameState.lockDepth(false) == 0) {
             throw bailout("unbalanced monitors: too many exits");
         }
@@ -2650,7 +2851,7 @@
         if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
             throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)));
         }
-        MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue));
+        MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedValue));
         monitorExit.setStateAfter(createFrameState(bci, monitorExit));
     }
 
@@ -2760,7 +2961,7 @@
         }
     }
 
-    private Target checkLoopExit(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) {
+    private Target checkLoopExit(Target target, BciBlock targetBlock) {
         if (currentBlock != null) {
             long exits = currentBlock.loops & ~targetBlock.loops;
             if (exits != 0) {
@@ -2790,7 +2991,7 @@
                 if (targetBlock instanceof ExceptionDispatchBlock) {
                     bci = ((ExceptionDispatchBlock) targetBlock).deoptBci;
                 }
-                FrameStateBuilder newState = state.copy();
+                FrameStateBuilder newState = target.state.copy();
                 for (BciBlock loop : exitLoops) {
                     LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop);
                     LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin));
@@ -2807,11 +3008,49 @@
                     loopExit.setStateAfter(newState.create(bci, loopExit));
                 }
 
-                lastLoopExit.setNext(target);
-                return new Target(firstLoopExit, newState);
+                // Fortify: Suppress Null Dereference false positive
+                assert lastLoopExit != null;
+
+                if (target.originalEntry == null) {
+                    lastLoopExit.setNext(target.entry);
+                    return new Target(firstLoopExit, newState, target.entry);
+                } else {
+                    target.originalEntry.replaceAtPredecessor(firstLoopExit);
+                    lastLoopExit.setNext(target.originalEntry);
+                    return new Target(target.entry, newState, target.originalEntry);
+                }
             }
         }
-        return new Target(target, state);
+        return target;
+    }
+
+    private Target checkUnwind(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) {
+        if (targetBlock != blockMap.getUnwindBlock()) {
+            return new Target(target, state);
+        }
+        FrameStateBuilder newState = state;
+        newState = newState.copy();
+        newState.setRethrowException(false);
+        if (!method.isSynchronized()) {
+            return new Target(target, newState);
+        }
+        FixedWithNextNode originalLast = lastInstr;
+        FrameStateBuilder originalState = frameState;
+        BeginNode holder = new BeginNode();
+        lastInstr = graph.add(holder);
+        frameState = newState;
+        assert frameState.stackSize() == 1;
+        ValueNode exception = frameState.peekObject();
+        synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, exception, JavaKind.Void);
+        lastInstr.setNext(target);
+
+        lastInstr = originalLast;
+        frameState = originalState;
+
+        FixedNode result = holder.next();
+        holder.setNext(null);
+        holder.safeDelete();
+        return new Target(result, newState, target);
     }
 
     private FrameStateBuilder getEntryState(BciBlock block) {
@@ -2856,29 +3095,23 @@
                  * placeholder that later can be replaced with a MergeNode when we see this block
                  * again.
                  */
-                FixedNode targetNode;
                 if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0) {
                     setFirstInstruction(block, lastInstr);
                     lastInstr = null;
                 } else {
                     setFirstInstruction(block, graph.add(new BeginNode()));
                 }
-                targetNode = getFirstInstruction(block);
-                Target target = checkLoopExit(targetNode, block, state);
-                FixedNode result = target.fixed;
+                Target target = checkUnwind(getFirstInstruction(block), block, state);
+                target = checkLoopExit(target, block);
+                FixedNode result = target.entry;
                 FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
                 setEntryState(block, currentEntryState);
                 currentEntryState.clearNonLiveLocals(block, liveness, true);
 
-                debug.log("createTarget %s: first visit, result: %s", block, targetNode);
+                debug.log("createTarget %s: first visit, result: %s", block, result);
                 return result;
             }
 
-            // We already saw this block before, so we have to merge states.
-            if (!getEntryState(block).isCompatibleWith(state)) {
-                throw bailout(String.format("stacks do not match on merge from %d into %s; bytecodes would not verify:%nexpect: %s%nactual: %s", bci(), block, getEntryState(block), state));
-            }
-
             if (getFirstInstruction(block) instanceof LoopBeginNode) {
                 assert (block.isLoopHeader() && currentBlock.getId() >= block.getId()) : "must be backward branch";
                 /*
@@ -2887,8 +3120,8 @@
                  */
                 LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
                 LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
-                Target target = checkLoopExit(loopEnd, block, state);
-                FixedNode result = target.fixed;
+                Target target = checkLoopExit(new Target(loopEnd, state), block);
+                FixedNode result = target.entry;
                 getEntryState(block).merge(loopBegin, target.state);
 
                 debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
@@ -2927,8 +3160,8 @@
 
             // The EndNode for the newly merged edge.
             EndNode newEnd = graph.add(new EndNode());
-            Target target = checkLoopExit(newEnd, block, state);
-            FixedNode result = target.fixed;
+            Target target = checkLoopExit(checkUnwind(newEnd, block, state), block);
+            FixedNode result = target.entry;
             getEntryState(block).merge(mergeNode, target.state);
             mergeNode.addForwardEnd(newEnd);
 
@@ -2993,13 +3226,15 @@
     }
 
     private void handleUnwindBlock(ExceptionDispatchBlock block) {
+        if (frameState.lockDepth(false) != 0) {
+            throw bailout("unbalanced monitors: too few exits exiting frame");
+        }
+        assert !frameState.rethrowException();
+        finishPrepare(lastInstr, block.deoptBci, frameState);
         if (parent == null) {
-            finishPrepare(lastInstr, block.deoptBci, frameState);
-            frameState.setRethrowException(false);
             createUnwind();
         } else {
-            ValueNode exception = frameState.pop(JavaKind.Object);
-            this.unwindValue = exception;
+            this.unwindValue = frameState.pop(JavaKind.Object);
             this.beforeUnwindNode = this.lastInstr;
         }
     }
@@ -3018,7 +3253,6 @@
     @SuppressWarnings("try")
     private void createUnwind() {
         assert frameState.stackSize() == 1 : frameState;
-        synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null);
         try (DebugCloseable context = openNodeContext(frameState, BytecodeFrame.UNWIND_BCI)) {
             ValueNode exception = frameState.pop(JavaKind.Object);
             append(new UnwindNode(exception));
@@ -3029,12 +3263,13 @@
     private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) {
         try (DebugCloseable context = openNodeContext(frameState, bci)) {
             if (method.isSynchronized()) {
-                if (currentReturnValue != null) {
+                if (currentReturnValueKind != JavaKind.Void) {
+                    // we are making a state that should look like the state after the return:
+                    // push the return value on the stack
                     frameState.push(currentReturnValueKind, currentReturnValue);
                 }
                 genMonitorExit(methodSynchronizedObject, currentReturnValue, bci);
                 assert !frameState.rethrowException();
-                finishPrepare(lastInstr, bci, frameState);
             }
             if (frameState.lockDepth(false) != 0) {
                 throw bailout("unbalanced monitors: too few exits exiting frame");
@@ -4557,7 +4792,7 @@
          */
         if (resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
             if (parsingIntrinsic()) {
-                throw new GraalError("Cannot use an assertion within the context of an intrinsic.");
+                throw new GraalError("Cannot use an assertion within the context of an intrinsic: " + resolvedField);
             } else if (graphBuilderConfig.omitAssertions()) {
                 frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
                 return;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -48,6 +48,7 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
 import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -390,6 +391,10 @@
         assert code.equals(other.code) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
         assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds";
 
+        if (rethrowException != other.rethrowException) {
+            return false;
+        }
+
         if (stackSize() != other.stackSize()) {
             return false;
         }
@@ -413,7 +418,7 @@
     }
 
     public void merge(AbstractMergeNode block, FrameStateBuilder other) {
-        assert isCompatibleWith(other);
+        GraalError.guarantee(isCompatibleWith(other), "stacks do not match on merge; bytecodes would not verify:%nexpect: %s%nactual: %s", block, other);
 
         for (int i = 0; i < localsSize(); i++) {
             locals[i] = merge(locals[i], other.locals[i], block);
@@ -803,6 +808,12 @@
         return result;
     }
 
+    public ValueNode peekObject() {
+        ValueNode x = xpeek();
+        assert verifyKind(JavaKind.Object, x);
+        return x;
+    }
+
     /**
      * Pop the specified number of slots off of this stack and return them as an array of
      * instructions.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_currentTimeMillis02.java	Fri May 03 14:59:32 2019 -0400
@@ -24,34 +24,28 @@
 
 package org.graalvm.compiler.jtt.jdk;
 
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.jtt.JTTTest;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
-
-/*
+/**
+ * Checks that the time between 2 successive calls to {@link System#currentTimeMillis()} is less
+ * than 100 milliseconds at least once in 5_000_000 attempts.
  */
 public class System_currentTimeMillis02 extends JTTTest {
 
-    static void m(long[] times) {
-        times[1] = System.currentTimeMillis() - times[0];
-    }
-
     public static boolean test() {
-        long[] times = new long[2];  // { start, delta }
-        times[0] = System.currentTimeMillis();
-        times[1] = 0;
-        // force compilation:
-        for (int i = 0; i < 5000; i++) {
-            m(times);
+        for (int i = 0; i < 5_000_000; i++) {
+            long elapsed = System.currentTimeMillis() - System.currentTimeMillis();
+            if (elapsed < 100) {
+                return true;
+            }
         }
-        times[0] = System.currentTimeMillis();
-        times[1] = 0;
-        for (int i = 0; times[1] == 0 && i < 5000000; i++) {
-            m(times);
-            // do nothing.
+        if (!GraalDirectives.inCompiledCode()) {
+            // We don't care about the result for the interpreter, C1 or C2
+            return true;
         }
-        // better get at least 100 millisecond resolution.
-        return times[1] >= 1 && times[1] < 100;
+        return false;
     }
 
     @Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/System_nanoTime02.java	Fri May 03 14:59:32 2019 -0400
@@ -24,38 +24,32 @@
 
 package org.graalvm.compiler.jtt.jdk;
 
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.jtt.JTTTest;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
-
-/*
+/**
+ * Checks that the time between 2 successive calls to {@link System#nanoTime()} is less than 30
+ * microseconds at least once in 5_000_000 attempts.
  */
 public class System_nanoTime02 extends JTTTest {
 
     public static boolean test() {
-        long minDelta = Long.MAX_VALUE;
-
-        // the first call to System.nanoTime might take a long time due to call resolution
-        for (int c = 0; c < 10; c++) {
-            long start = System.nanoTime();
-            long delta = 0;
-            int i;
-            for (i = 0; delta == 0 && i < 50000; i++) {
-                delta = System.nanoTime() - start;
-                // do nothing.
-            }
-            if (delta < minDelta) {
-                minDelta = delta;
+        for (int i = 0; i < 5_000_000; i++) {
+            long delta = System.nanoTime() - System.nanoTime();
+            if (delta < 30_000) {
+                return true;
             }
         }
-
-        // better get at least 30 microsecond resolution.
-        return minDelta > 1 && minDelta < 30000;
+        if (!GraalDirectives.inCompiledCode()) {
+            // We don't care about the result for the interpreter, C1 or C2
+            return true;
+        }
+        return false;
     }
 
     @Test
     public void run0() throws Throwable {
         runTest("test");
     }
-
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log10.java	Fri May 03 14:59:32 2019 -0400
@@ -182,7 +182,7 @@
         // Test for gross inaccuracy by comparing to log; should be
         // within a few ulps of log(x)/log(10)
         Random rand = new java.util.Random(0L);
-        for (int i = 0; i < 10000; i++) {
+        for (int i = 0; i < 500; i++) {
             double input = Double.longBitsToDouble(rand.nextLong());
             if (!Double.isFinite(input)) {
                 continue; // avoid testing NaN and infinite values
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java	Fri May 03 14:59:32 2019 -0400
@@ -31,7 +31,7 @@
 
 public abstract class UnaryMath extends JTTTest {
 
-    private static final long STEP = Long.MAX_VALUE / 1_000_000;
+    private static final long STEP = Long.MAX_VALUE / 100_000;
 
     /**
      * Tests a unary {@link Math} method on a wide range of values.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Fri May 03 14:59:32 2019 -0400
@@ -44,6 +44,7 @@
     protected Object object = new Object();
     protected volatile boolean drained = false;
     protected volatile boolean someBoolean = true;
+    protected volatile int someInt = 3;
 
     public boolean test() {
         boolean b = true;
@@ -63,4 +64,49 @@
         runTest("test");
     }
 
+    public synchronized boolean test1() {
+        boolean b = true;
+        while (!drained) {
+            synchronized (object) {
+                boolean c = b = someBoolean;
+                if (c || drained) {
+                    break;
+                }
+            }
+        }
+        return b;
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test1");
+    }
+
+    public synchronized boolean test2() {
+        boolean b = true;
+        while (!drained) {
+            synchronized (object) {
+                boolean c = b = someBoolean;
+                if (c || drained) {
+                    break;
+                }
+                if (someInt > 0) {
+                    throw new RuntimeException();
+                }
+            }
+            if (someInt < -10) {
+                throw new IndexOutOfBoundsException();
+            }
+        }
+        if (someInt < -5) {
+            throw new IllegalArgumentException();
+        }
+        return b;
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test2");
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedParserInlineTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,95 @@
+/*
+ * 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.jtt.threads;
+
+import org.graalvm.compiler.jtt.JTTTest;
+import org.junit.Test;
+
+public final class SynchronizedParserInlineTest extends JTTTest {
+
+    private static SynchronizedParserInlineTest object = new SynchronizedParserInlineTest();
+
+    public static Integer test(boolean b) {
+        foo(object);
+        return b ? 42 : 1337;
+    }
+
+    @BytecodeParserForceInline
+    public static synchronized void foo(SynchronizedParserInlineTest o) {
+        o.notifyAll();
+    }
+
+    @Test
+    public void run0() {
+        runTest("test", false);
+    }
+
+    public static Integer test1(int b) {
+        return foo1(b);
+    }
+
+    @BytecodeParserForceInline
+    public static synchronized int foo1(int b) {
+        if (b < 0) {
+            return 7777;
+        } else if (b > 100) {
+            throw new RuntimeException();
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Test
+    public void run1() {
+        runTest("test1", -1);
+        runTest("test1", 1);
+        runTest("test1", 101);
+    }
+
+    public static Integer test2(int b) {
+        return foo2(b);
+    }
+
+    @BytecodeParserForceInline
+    public static int foo2(int b) {
+        if (b < 0) {
+            return 7777;
+        } else if (b > 100) {
+            throw new RuntimeException();
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Test
+    public void run2() {
+        runTest("test2", -1);
+        runTest("test2", 1);
+        runTest("test2", 101);
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java	Fri May 03 14:59:32 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
@@ -24,17 +24,22 @@
 
 package org.graalvm.compiler.lir.aarch64;
 
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
 
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 
+import jdk.vm.ci.aarch64.AArch64Kind;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
 
 /**
  * Bit manipulation ops for ARMv8 ISA.
@@ -45,6 +50,7 @@
         BSR,
         BSWP,
         CLZ,
+        POPCNT,
     }
 
     private static final LIRInstructionClass<AArch64BitManipulationOp> TYPE = LIRInstructionClass.create(AArch64BitManipulationOp.class);
@@ -53,11 +59,14 @@
     @Def protected AllocatableValue result;
     @Use({REG}) protected AllocatableValue input;
 
-    public AArch64BitManipulationOp(BitManipulationOpCode opcode, AllocatableValue result, AllocatableValue input) {
+    @Temp({REG, ILLEGAL}) protected Value temp;
+
+    public AArch64BitManipulationOp(LIRGeneratorTool tool, BitManipulationOpCode opcode, AllocatableValue result, AllocatableValue input) {
         super(TYPE);
         this.opcode = opcode;
         this.result = result;
         this.input = input;
+        this.temp = BitManipulationOpCode.POPCNT == opcode ? tool.newVariable(LIRKind.value(AArch64Kind.V64_BYTE)) : Value.ILLEGAL;
     }
 
     @Override
@@ -83,6 +92,11 @@
             case BSWP:
                 masm.rev(size, dst, src);
                 break;
+            case POPCNT:
+                assert !Value.ILLEGAL.equals(temp) : "Auxiliary register not allocated.";
+                Register vreg = asRegister(temp);
+                masm.popcnt(size, dst, src, vreg);
+                break;
             default:
                 throw GraalError.shouldNotReachHere();
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java	Fri May 03 14:59:32 2019 -0400
@@ -175,7 +175,10 @@
             boolean isFarBranch;
 
             if (label.isBound()) {
-                isFarBranch = NumUtil.isSignedNbit(18, masm.position() - label.position());
+                // The label.position() is a byte based index. The TBZ instruction has 14 bits for
+                // the offset and AArch64 instruction is 4 bytes aligned. So TBZ can encode 16 bits
+                // signed offset.
+                isFarBranch = !NumUtil.isSignedNbit(16, masm.position() - label.position());
             } else {
                 // Max range of tbz is +-2^13 instructions. We estimate that each LIR instruction
                 // emits 2 AArch64 instructions on average. Thus we test for maximum 2^12 LIR
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Fri May 03 14:59:32 2019 -0400
@@ -497,7 +497,12 @@
                         masm.fmov(32, dst, scratch);
                     }
                 } else {
-                    masm.fldr(32, dst, (AArch64Address) crb.asFloatConstRef(input));
+                    try (ScratchRegister scr = masm.getScratchRegister()) {
+                        Register scratch = scr.getRegister();
+                        crb.asFloatConstRef(input);
+                        masm.addressOf(scratch);
+                        masm.fldr(32, dst, AArch64Address.createBaseRegisterOnlyAddress(scratch));
+                    }
                 }
                 break;
             case Double:
@@ -510,7 +515,12 @@
                         masm.fmov(64, dst, scratch);
                     }
                 } else {
-                    masm.fldr(64, dst, (AArch64Address) crb.asDoubleConstRef(input));
+                    try (ScratchRegister scr = masm.getScratchRegister()) {
+                        Register scratch = scr.getRegister();
+                        crb.asDoubleConstRef(input);
+                        masm.addressOf(scratch);
+                        masm.fldr(64, dst, AArch64Address.createBaseRegisterOnlyAddress(scratch));
+                    }
                 }
                 break;
             case Object:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Fri May 03 14:59:32 2019 -0400
@@ -299,7 +299,7 @@
                     int imm32 = label.position() - jumpTablePos;
                     masm.emitInt(imm32);
                 } else {
-                    label.addPatchAt(masm.position());
+                    label.addPatchAt(masm.position(), masm);
 
                     masm.emitByte(0); // pseudo-opcode for jump table entry
                     masm.emitShort(offsetToJumpTableBase);
@@ -393,7 +393,7 @@
                     masm.emitInt(imm32);
                 } else {
                     int offsetToJumpTableBase = masm.position() - jumpTablePos;
-                    label.addPatchAt(masm.position());
+                    label.addPatchAt(masm.position(), masm);
                     masm.emitByte(0); // pseudo-opcode for jump table entry
                     masm.emitShort(offsetToJumpTableBase);
                     masm.emitByte(0); // padding to make jump table entry 4 bytes wide
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java	Fri May 03 14:59:32 2019 -0400
@@ -878,6 +878,9 @@
                 break;
             }
 
+            // Fortify: Suppress Null Dereference false positive
+            assert reg != null;
+
             boolean needSplit = blockPos[reg.number] <= intervalTo;
 
             int splitPos = blockPos[reg.number];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -598,8 +598,8 @@
                         if (label != null) {
                             labelBindLirPositions.put(label, instructionPosition);
                         }
-                        lirPositions.put(op, instructionPosition);
                     }
+                    lirPositions.put(op, instructionPosition);
                     instructionPosition++;
                 }
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java	Fri May 03 14:59:32 2019 -0400
@@ -278,7 +278,8 @@
             }
 
             if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().getRelativeFrequency()) {
-                try (DebugContext.Scope s = debug.scope("CLOmodify", constTree); Indent i = debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) {
+                try (DebugContext.Scope s = debug.scope("CLOmodify", constTree);
+                                Indent i = debug.isLogEnabled() ? debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString()) : null) {
                     // mark original load for removal
                     deleteInstruction(tree);
                     constantsOptimized.increment(debug);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Fri May 03 14:59:32 2019 -0400
@@ -394,9 +394,14 @@
                         invariantValue = switchNode.value();
                         controls = new ArrayList<>();
                         controls.add(switchNode);
-                    } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) {
-                        // Only collect switches which test the same values in the same order
-                        controls.add(switchNode);
+                    } else if (switchNode.value() == invariantValue) {
+                        // Fortify: Suppress Null Dereference false positive
+                        assert firstSwitch != null;
+
+                        if (firstSwitch.structureEquals(switchNode)) {
+                            // Only collect switches which test the same values in the same order
+                            controls.add(switchNode);
+                        }
                     }
                 }
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Fri May 03 14:59:32 2019 -0400
@@ -164,7 +164,7 @@
 
     @Override
     public String toString() {
-        return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + loop().getDepth() + ") " + loopBegin();
+        return (countedLoopChecked && isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + loop().getDepth() + ") " + loopBegin();
     }
 
     private class InvariantPredicate implements NodePredicate {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CallTargetNode.java	Fri May 03 14:59:32 2019 -0400
@@ -137,4 +137,8 @@
     public void setInvokeKind(InvokeKind kind) {
         this.invokeKind = kind;
     }
+
+    public Invoke invoke() {
+        return (Invoke) this.usages().first();
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingNode.java	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,12 @@
 
 /**
  * Interface implemented by nodes which may need {@linkplain FrameState deoptimization information}.
+ * <p>
+ * Sub-interfaces are used to specify exactly when the deoptimization can take place:
+ * {@linkplain DeoptBefore before}, {@linkplain DeoptAfter after}, and/or {@linkplain DeoptDuring
+ * during}. <br>
+ * Note that these sub-interfaces are not mutually exclusive so that nodes that may deoptimize at
+ * multiple times can be modeled.
  */
 public interface DeoptimizingNode extends NodeWithState {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Fri May 03 14:59:32 2019 -0400
@@ -878,33 +878,37 @@
                 registerNode(outerScope, proxyOrderId, phiInput, true, false);
                 replacement = phiInput;
 
-            } else if (!merge.isPhiAtMerge(existing)) {
-                /* Now we have two different values, so we need to create a phi node. */
-                PhiNode phi;
-                if (proxy instanceof ValueProxyNode) {
-                    phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge));
-                } else if (proxy instanceof GuardProxyNode) {
-                    phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+            } else {
+                // Fortify: Suppress Null Dereference false positive
+                assert merge != null;
+
+                if (!merge.isPhiAtMerge(existing)) {
+                    /* Now we have two different values, so we need to create a phi node. */
+                    PhiNode phi;
+                    if (proxy instanceof ValueProxyNode) {
+                        phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge));
+                    } else if (proxy instanceof GuardProxyNode) {
+                        phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+                    } else {
+                        throw GraalError.shouldNotReachHere();
+                    }
+                    /* Add the inputs from all previous exits. */
+                    for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
+                        phi.addInput(existing);
+                    }
+                    /* Add the input from this exit. */
+                    phi.addInput(phiInput);
+                    registerNode(outerScope, proxyOrderId, phi, true, false);
+                    replacement = phi;
+                    phiCreated = true;
+
                 } else {
-                    throw GraalError.shouldNotReachHere();
-                }
-                /* Add the inputs from all previous exits. */
-                for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
-                    phi.addInput(existing);
+                    /* Phi node has been created before, so just add the new input. */
+                    PhiNode phi = (PhiNode) existing;
+                    phi.addInput(phiInput);
+                    replacement = phi;
                 }
-                /* Add the input from this exit. */
-                phi.addInput(phiInput);
-                registerNode(outerScope, proxyOrderId, phi, true, false);
-                replacement = phi;
-                phiCreated = true;
-
-            } else {
-                /* Phi node has been created before, so just add the new input. */
-                PhiNode phi = (PhiNode) existing;
-                phi.addInput(phiInput);
-                replacement = phi;
             }
-
             proxy.replaceAtUsagesAndDelete(replacement);
         }
 
@@ -1814,6 +1818,7 @@
             }
         }
         assert loopVariableIndex != -1;
+        assert explosionHeadValue != null;
 
         ValuePhiNode loopVariablePhi;
         SortedMap<Integer, AbstractBeginNode> dispatchTable = new TreeMap<>();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Fri May 03 14:59:32 2019 -0400
@@ -768,6 +768,9 @@
                     removeThroughFalseBranch(tool, merge);
                     return true;
                 } else if (distinct == 1) {
+                    // Fortify: Suppress Null Dereference false positive
+                    assert singlePhi != null;
+
                     ValueNode trueValue = singlePhi.valueAt(trueEnd);
                     ValueNode falseValue = singlePhi.valueAt(falseEnd);
                     ValueNode conditional = canonicalizeConditionalCascade(tool, trueValue, falseValue);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java	Fri May 03 14:59:32 2019 -0400
@@ -118,4 +118,6 @@
     default InvokeKind getInvokeKind() {
         return callTarget().invokeKind();
     }
+
+    void replaceBci(int newBci);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java	Fri May 03 14:59:32 2019 -0400
@@ -55,6 +55,7 @@
 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
+import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.JavaKind;
 
 /**
@@ -76,7 +77,7 @@
     @OptionalInput ValueNode classInit;
     @Input(Extension) CallTargetNode callTarget;
     @OptionalInput(State) FrameState stateDuring;
-    protected final int bci;
+    protected int bci;
     protected boolean polymorphic;
     protected boolean useForInlining;
     protected final LocationIdentity identity;
@@ -102,15 +103,19 @@
         this.identity = identity;
     }
 
-    public InvokeNode replaceWithNewBci(int newBci) {
-        InvokeNode newInvoke = graph().add(new InvokeNode(callTarget, newBci, stamp, identity));
-        newInvoke.setUseForInlining(useForInlining);
-        newInvoke.setPolymorphic(polymorphic);
-        newInvoke.setStateAfter(stateAfter);
-        newInvoke.setStateDuring(stateDuring);
-        newInvoke.setClassInit(classInit);
-        graph().replaceFixedWithFixed(this, newInvoke);
-        return newInvoke;
+    public InvokeNode(InvokeWithExceptionNode invoke) {
+        super(TYPE, invoke.stamp);
+        this.callTarget = invoke.callTarget;
+        this.bci = invoke.bci;
+        this.polymorphic = invoke.polymorphic;
+        this.useForInlining = invoke.useForInlining;
+        this.identity = invoke.getLocationIdentity();
+    }
+
+    @Override
+    public void replaceBci(int newBci) {
+        assert BytecodeFrame.isPlaceholderBci(bci) && !BytecodeFrame.isPlaceholderBci(newBci) : "can only replace placeholder with better bci";
+        bci = newBci;
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java	Fri May 03 14:59:32 2019 -0400
@@ -24,7 +24,16 @@
 
 package org.graalvm.compiler.nodes;
 
+import static org.graalvm.compiler.nodeinfo.InputType.Extension;
+import static org.graalvm.compiler.nodeinfo.InputType.Memory;
+import static org.graalvm.compiler.nodeinfo.InputType.State;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
+
+import java.util.Map;
+
 import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -38,13 +47,7 @@
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
-import java.util.Map;
-
-import static org.graalvm.compiler.nodeinfo.InputType.Extension;
-import static org.graalvm.compiler.nodeinfo.InputType.Memory;
-import static org.graalvm.compiler.nodeinfo.InputType.State;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
+import jdk.vm.ci.code.BytecodeFrame;
 
 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}", allowedUsageTypes = {Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
 public final class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable, UncheckedInterfaceProvider {
@@ -58,7 +61,7 @@
     @Input(Extension) CallTargetNode callTarget;
     @OptionalInput(State) FrameState stateDuring;
     @OptionalInput(State) FrameState stateAfter;
-    protected final int bci;
+    protected int bci;
     protected boolean polymorphic;
     protected boolean useForInlining;
     protected double exceptionProbability;
@@ -207,20 +210,25 @@
         GraphUtil.killCFG(edge);
     }
 
-    public void replaceWithNewBci(int newBci) {
-        AbstractBeginNode nextNode = next();
-        AbstractBeginNode exceptionObject = exceptionEdge;
-        setExceptionEdge(null);
-        setNext(null);
-        InvokeWithExceptionNode repl = graph().add(new InvokeWithExceptionNode(callTarget(), exceptionObject, newBci));
-        repl.setStateAfter(stateAfter);
-        this.setStateAfter(null);
-        this.replaceAtPredecessor(repl);
-        repl.setNext(nextNode);
-        boolean removed = this.callTarget().removeUsage(this);
-        assert removed;
-        this.replaceAtUsages(repl);
-        this.markDeleted();
+    @SuppressWarnings("try")
+    public AbstractBeginNode killKillingBegin() {
+        AbstractBeginNode begin = next();
+        if (begin instanceof KillingBeginNode) {
+            try (DebugCloseable position = begin.withNodeSourcePosition()) {
+                AbstractBeginNode newBegin = new BeginNode();
+                graph().addAfterFixed(begin, graph().add(newBegin));
+                begin.replaceAtUsages(newBegin);
+                graph().removeFixed(begin);
+                return newBegin;
+            }
+        }
+        return begin;
+    }
+
+    @Override
+    public void replaceBci(int newBci) {
+        assert BytecodeFrame.isPlaceholderBci(bci) && !BytecodeFrame.isPlaceholderBci(newBci) : "can only replace placeholder with better bci";
+        bci = newBci;
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Fri May 03 14:59:32 2019 -0400
@@ -966,7 +966,7 @@
      */
     public List<ResolvedJavaMethod> getMethods() {
         if (methods != null) {
-            assert checkFrameStatesAgainstInlinedMethods();
+            assert isSubstitution || checkFrameStatesAgainstInlinedMethods();
             return Collections.unmodifiableList(methods);
         }
         return Collections.emptyList();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java	Fri May 03 14:59:32 2019 -0400
@@ -289,11 +289,17 @@
             }
             if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
                 if (left == null) {
+                    // Fortify: Suppress Null Dereference false positive
+                    assert leftCst != null;
+
                     left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
                 } else if (xResidue != 0) {
                     left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue), view);
                 }
                 if (right == null) {
+                    // Fortify: Suppress Null Dereference false positive
+                    assert rightCst != null;
+
                     right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
                 } else if (yResidue != 0) {
                     right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue), view);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java	Fri May 03 14:59:32 2019 -0400
@@ -41,6 +41,7 @@
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
+import org.graalvm.compiler.nodes.type.NarrowOopStamp;
 import org.graalvm.compiler.nodes.type.StampTool;
 
 import jdk.vm.ci.meta.JavaConstant;
@@ -67,6 +68,7 @@
 
     public IsNullNode(ValueNode object) {
         this(object, JavaConstant.NULL_POINTER);
+        assertNonNarrow(object);
     }
 
     public JavaConstant nullConstant() {
@@ -74,9 +76,19 @@
     }
 
     public static LogicNode create(ValueNode forValue) {
+        assertNonNarrow(forValue);
         return canonicalized(null, forValue, JavaConstant.NULL_POINTER);
     }
 
+    public static LogicNode create(ValueNode forValue, JavaConstant nullConstant) {
+        assert nullConstant.isNull() : "Null constant is not null: " + nullConstant;
+        return canonicalized(null, forValue, nullConstant);
+    }
+
+    private static void assertNonNarrow(ValueNode object) {
+        assert !(object.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) : "Value to compare against null is a NarrowOop" + object;
+    }
+
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         // Nothing to do.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java	Fri May 03 14:59:32 2019 -0400
@@ -138,14 +138,22 @@
         } else if (forX.stamp(view).alwaysDistinct(forY.stamp(view))) {
             return LogicConstantNode.contradiction();
         } else if (((AbstractPointerStamp) forX.stamp(view)).alwaysNull()) {
-            return IsNullNode.create(forY);
+            return nullSynonym(forY, forX);
         } else if (((AbstractPointerStamp) forY.stamp(view)).alwaysNull()) {
-            return IsNullNode.create(forX);
+            return nullSynonym(forX, forY);
         } else {
             return null;
         }
     }
 
+    private static LogicNode nullSynonym(ValueNode nonNullValue, ValueNode nullValue) {
+        if (nullValue.isConstant()) {
+            return IsNullNode.create(nonNullValue, nullValue.asJavaConstant());
+        } else {
+            return IsNullNode.create(nonNullValue);
+        }
+    }
+
     @Override
     public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) {
         if (!negated) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java	Fri May 03 14:59:32 2019 -0400
@@ -317,6 +317,9 @@
                     dominator = ((dominator == null) ? pred : commonDominatorRaw(dominator, pred));
                 }
             }
+            // Fortify: Suppress Null Dereference false positive (every block apart from the first
+            // is guaranteed to have a predecessor)
+            assert dominator != null;
 
             // Set dominator.
             block.setDominator(dominator);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Fri May 03 14:59:32 2019 -0400
@@ -79,6 +79,13 @@
 
     public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls,
                     ForeignCallDescriptor descriptor, ValueNode... arguments) {
+        if (!foreignCalls.isAvailable(descriptor)) {
+            // When using encoded snippets a graph main contain a reference to a foreign call that's
+            // not actually available in the current configuration. It's assumed that further
+            // simplification of the graph will eliminate this call completely.
+            return false;
+        }
+
         ForeignCallNode node = new ForeignCallNode(foreignCalls, descriptor, arguments);
         node.setStamp(returnStamp);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java	Fri May 03 14:59:32 2019 -0400
@@ -39,9 +39,9 @@
 
     @OptionalInput(Guard) protected GuardingNode guard;
 
-    public GuardedUnsafeLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity, GuardingNode guard) {
+    public GuardedUnsafeLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity, ValueNode guard) {
         super(TYPE, object, offset, accessKind, locationIdentity);
-        this.guard = guard;
+        this.guard = (GuardingNode) guard;
     }
 
     @Override
@@ -54,4 +54,7 @@
         updateUsagesInterface(this.guard, guard);
         this.guard = guard;
     }
+
+    @NodeIntrinsic
+    public static native Object guardedLoad(Object object, long offset, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity, GuardingNode guard);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java	Fri May 03 14:59:32 2019 -0400
@@ -45,6 +45,8 @@
  */
 public abstract class GeneratedInvocationPlugin implements InvocationPlugin {
 
+    private ResolvedJavaMethod executeMethod;
+
     /**
      * Gets the class of the annotation for which this plugin was generated.
      */
@@ -69,23 +71,37 @@
             return true;
         }
 
-        if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
+        if (IS_IN_NATIVE_IMAGE) {
             // The reflection here is problematic for SVM.
             return true;
         }
 
-        MetaAccessProvider metaAccess = b.getMetaAccess();
-        ResolvedJavaMethod executeMethod = metaAccess.lookupJavaMethod(getExecuteMethod());
-        ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass());
-        ResolvedJavaMethod thisExecuteMethod = thisClass.resolveConcreteMethod(executeMethod, thisClass);
+        if (b.getMethod().equals(foldAnnotatedMethod)) {
+            return false;
+        }
+
+        ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b);
         if (b.getMethod().equals(thisExecuteMethod)) {
             // The "execute" method of this plugin is itself being compiled. In (only) this context,
             // the injected argument of the call to the @Fold annotated method will be non-null.
+            if (IS_BUILDING_NATIVE_IMAGE) {
+                return false;
+            }
             return true;
         }
         throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg);
     }
 
+    private ResolvedJavaMethod getExecutedMethod(GraphBuilderContext b) {
+        if (executeMethod == null) {
+            MetaAccessProvider metaAccess = b.getMetaAccess();
+            ResolvedJavaMethod baseMethod = metaAccess.lookupJavaMethod(getExecuteMethod());
+            ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass());
+            executeMethod = thisClass.resolveConcreteMethod(baseMethod, thisClass);
+        }
+        return executeMethod;
+    }
+
     private static Method getExecuteMethod() {
         try {
             return GeneratedInvocationPlugin.class.getMethod("execute", GraphBuilderContext.class, ResolvedJavaMethod.class, InvocationPlugin.Receiver.class, ValueNode[].class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java	Fri May 03 14:59:32 2019 -0400
@@ -47,6 +47,7 @@
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.StateSplit;
+import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.calc.IsNullNode;
 import org.graalvm.compiler.nodes.calc.NarrowNode;
@@ -165,6 +166,19 @@
     boolean intrinsify(BytecodeProvider bytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver);
 
     /**
+     * Intrinsifies an invocation of a given method by inlining the graph of a given substitution
+     * method.
+     *
+     * @param targetMethod the method being intrinsified
+     * @param substituteGraph the intrinsic implementation
+     * @param receiver the receiver, or null for static methods
+     * @param argsIncludingReceiver the arguments with which to inline the invocation
+     *
+     * @return whether the intrinsification was successful
+     */
+    boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver);
+
+    /**
      * Creates a snap shot of the current frame state with the BCI of the instruction after the one
      * currently being parsed and assigns it to a given {@linkplain StateSplit#hasSideEffect() side
      * effect} node.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java	Fri May 03 14:59:32 2019 -0400
@@ -47,35 +47,43 @@
          * Denotes a call site that must not be inlined and should be implemented by a node that
          * does not speculate on the call not raising an exception.
          */
-        public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo(null, null, null);
+        public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo();
 
         /**
          * Denotes a call site must not be inlined and can be implemented by a node that speculates
          * the call will not throw an exception.
          */
-        public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(null, null, null);
+        public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo();
 
         /**
          * Denotes a call site must not be inlined and the execution should be transferred to
          * interpreter in case of an exception.
          */
-        public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo(null, null, null);
+        public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo();
 
         private final ResolvedJavaMethod methodToInline;
-        private final ResolvedJavaMethod originalMethod;
+        private final MethodSubstitutionPlugin plugin;
         private final BytecodeProvider intrinsicBytecodeProvider;
 
         public static InlineInfo createStandardInlineInfo(ResolvedJavaMethod methodToInline) {
             return new InlineInfo(methodToInline, null, null);
         }
 
-        public static InlineInfo createIntrinsicInlineInfo(ResolvedJavaMethod methodToInline, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider) {
-            return new InlineInfo(methodToInline, originalMethod, intrinsicBytecodeProvider);
+        public static InlineInfo createIntrinsicInlineInfo(ResolvedJavaMethod methodToInline, BytecodeProvider intrinsicBytecodeProvider) {
+            return new InlineInfo(methodToInline, null, intrinsicBytecodeProvider);
+        }
+
+        public static InlineInfo createMethodSubstitutionInlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin) {
+            return new InlineInfo(methodToInline, plugin, plugin.getBytecodeProvider());
         }
 
-        private InlineInfo(ResolvedJavaMethod methodToInline, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider) {
+        private InlineInfo() {
+            this(null, null, null);
+        }
+
+        private InlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider) {
             this.methodToInline = methodToInline;
-            this.originalMethod = originalMethod;
+            this.plugin = plugin;
             this.intrinsicBytecodeProvider = intrinsicBytecodeProvider;
         }
 
@@ -91,14 +99,6 @@
         }
 
         /**
-         * Returns the original method if this is an inline of an intrinsic, or {@code null} if the
-         * call site must not be inlined.
-         */
-        public ResolvedJavaMethod getOriginalMethod() {
-            return originalMethod;
-        }
-
-        /**
          * Gets the provider of bytecode to be parsed for {@link #getMethodToInline()} if is is an
          * intrinsic for the original method (i.e., the {@code method} passed to
          * {@link InlineInvokePlugin#shouldInlineInvoke}). A {@code null} return value indicates
@@ -107,6 +107,14 @@
         public BytecodeProvider getIntrinsicBytecodeProvider() {
             return intrinsicBytecodeProvider;
         }
+
+        public boolean isSubstitution() {
+            return plugin != null;
+        }
+
+        public MethodSubstitutionPlugin getPlugin() {
+            return plugin;
+        }
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java	Fri May 03 14:59:32 2019 -0400
@@ -191,6 +191,11 @@
         void addSideEffect(StateSplit sideEffect);
     }
 
+    @SuppressWarnings("unused")
+    public boolean isDeferredInvoke(StateSplit stateSplit) {
+        return false;
+    }
+
     public FrameState createFrameState(StructuredGraph graph, SideEffectsState sideEffects, StateSplit forStateSplit, NodeSourcePosition sourcePosition) {
         assert forStateSplit != graph.start();
         if (forStateSplit.hasSideEffect()) {
@@ -205,12 +210,16 @@
                     lastSideEffect.setStateAfter(invalid);
                 }
             }
-            sideEffects.addSideEffect(forStateSplit);
             FrameState frameState;
-            if (forStateSplit instanceof ExceptionObjectNode) {
-                frameState = graph.add(new FrameState(AFTER_EXCEPTION_BCI, (ExceptionObjectNode) forStateSplit));
+            if (isDeferredInvoke(forStateSplit)) {
+                frameState = graph.add(new FrameState(INVALID_FRAMESTATE_BCI));
             } else {
-                frameState = graph.add(new FrameState(AFTER_BCI));
+                sideEffects.addSideEffect(forStateSplit);
+                if (forStateSplit instanceof ExceptionObjectNode) {
+                    frameState = graph.add(new FrameState(AFTER_EXCEPTION_BCI, (ExceptionObjectNode) forStateSplit));
+                } else {
+                    frameState = graph.add(new FrameState(AFTER_BCI));
+                }
             }
             if (graph.trackNodeSourcePosition()) {
                 frameState.setNodeSourcePosition(sourcePosition);
@@ -243,6 +252,7 @@
 
     @Override
     public String toString() {
-        return "Intrinsic{original: " + originalMethod.format("%H.%n(%p)") + ", intrinsic: " + intrinsicMethod.format("%H.%n(%p)") + ", context: " + compilationContext + "}";
+        return "Intrinsic{original: " + originalMethod.format("%H.%n(%p)") + ", intrinsic: " + (intrinsicMethod != null ? intrinsicMethod.format("%H.%n(%p)") : "null") + ", context: " +
+                        compilationContext + "}";
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java	Fri May 03 14:59:32 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
@@ -197,6 +197,11 @@
                 return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]);
             } else if (argsIncludingReceiver.length == 5) {
                 return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]);
+            } else if (argsIncludingReceiver.length == 6) {
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4], argsIncludingReceiver[5]);
+            } else if (argsIncludingReceiver.length == 7) {
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4], argsIncludingReceiver[5],
+                                argsIncludingReceiver[6]);
             } else {
                 return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver);
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Fri May 03 14:59:32 2019 -0400
@@ -1023,18 +1023,10 @@
         if (parent != null) {
             InvocationPlugin plugin = parent.lookupInvocation(method);
             if (plugin != null) {
-                if (IS_IN_NATIVE_IMAGE && plugin instanceof MethodSubstitutionPlugin) {
-                    // Disable method substitutions until GR-13607
-                    return null;
-                }
                 return plugin;
             }
         }
         InvocationPlugin invocationPlugin = get(method);
-        if (IS_IN_NATIVE_IMAGE && invocationPlugin instanceof MethodSubstitutionPlugin) {
-            // Disable method substitutions until GR-13607
-            return null;
-        }
         return invocationPlugin;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java	Fri May 03 14:59:32 2019 -0400
@@ -25,6 +25,8 @@
 package org.graalvm.compiler.nodes.graphbuilderconf;
 
 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs;
+import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.resolveType;
 
 import java.lang.reflect.Method;
@@ -35,6 +37,7 @@
 
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
 
 import jdk.vm.ci.meta.MetaAccessProvider;
@@ -116,9 +119,16 @@
     }
 
     /**
+     * Gets the class in which the substitute method is declared.
+     */
+    public Class<?> getDeclaringClass() {
+        return declaringClass;
+    }
+
+    /**
      * Gets the reflection API version of the substitution method.
      */
-    Method getJavaSubstitute() throws GraalError {
+    public Method getJavaSubstitute() throws GraalError {
         Method substituteMethod = lookupSubstitute();
         int modifiers = substituteMethod.getModifiers();
         if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
@@ -178,12 +188,18 @@
 
     @Override
     public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) {
-        if (IS_IN_NATIVE_IMAGE) {
-            // these are currently unimplemented
-            return false;
+        if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) {
+            if (!IS_IN_NATIVE_IMAGE && UseEncodedGraphs.getValue(b.getOptions())) {
+                b.getReplacements().registerMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, b.getOptions());
+            }
+            StructuredGraph subst = b.getReplacements().getMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()), b.getOptions());
+            if (subst == null) {
+                throw new GraalError("No graphs found for substitution %s", this);
+            }
+            return b.intrinsify(targetMethod, subst, receiver, argsIncludingReceiver);
         }
-        ResolvedJavaMethod subst = getSubstitute(b.getMetaAccess());
-        return b.intrinsify(bytecodeProvider, targetMethod, subst, receiver, argsIncludingReceiver);
+        ResolvedJavaMethod substitute = getSubstitute(b.getMetaAccess());
+        return b.intrinsify(bytecodeProvider, targetMethod, substitute, receiver, argsIncludingReceiver);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java	Fri May 03 14:59:32 2019 -0400
@@ -95,10 +95,6 @@
         return targetMethod().getSignature().getReturnKind();
     }
 
-    public Invoke invoke() {
-        return (Invoke) this.usages().first();
-    }
-
     @Override
     public boolean verify() {
         assert getUsageCount() <= 1 : "call target may only be used by a single invoke";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java	Fri May 03 14:59:32 2019 -0400
@@ -56,15 +56,15 @@
      */
     @OptionalInput ValueNode escapedReturnValue;
 
-    public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) {
+    public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedValue) {
         super(TYPE, object, monitorId);
-        this.escapedReturnValue = escapedReturnValue;
+        this.escapedReturnValue = escapedValue;
     }
 
     /**
      * Return value is cleared when a synchronized method graph is inlined.
      */
-    public void clearEscapedReturnValue() {
+    public void clearEscapedValue() {
         updateUsages(escapedReturnValue, null);
         this.escapedReturnValue = null;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/TypeSwitchNode.java	Fri May 03 14:59:32 2019 -0400
@@ -188,11 +188,10 @@
                         }
                     }
 
+                    ArrayList<AbstractBeginNode> oldSuccessors = new ArrayList<>();
                     for (int i = 0; i < blockSuccessorCount(); i++) {
                         AbstractBeginNode successor = blockSuccessor(i);
-                        if (!newSuccessors.contains(successor)) {
-                            tool.deleteBranch(successor);
-                        }
+                        oldSuccessors.add(successor);
                         setBlockSuccessor(i, null);
                     }
 
@@ -200,6 +199,13 @@
                     TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors, tool.getConstantReflection()));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
+
+                    for (int i = 0; i < oldSuccessors.size(); i++) {
+                        AbstractBeginNode successor = oldSuccessors.get(i);
+                        if (!newSuccessors.contains(successor)) {
+                            GraphUtil.killCFG(successor);
+                        }
+                    }
                 }
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,6 @@
 package org.graalvm.compiler.nodes.spi;
 
 import org.graalvm.compiler.api.replacements.SnippetTemplateCache;
-import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.DebugContext;
@@ -33,6 +32,8 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -48,8 +49,8 @@
     }
 
     @Override
-    public OptionValues getOptions() {
-        return delegate.getOptions();
+    public CoreProviders getProviders() {
+        return delegate.getProviders();
     }
 
     @Override
@@ -63,28 +64,30 @@
     }
 
     @Override
-    public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        return delegate.getSnippet(method, args, trackNodeSourcePosition, replaceePosition);
+    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition,
+                    OptionValues options) {
+        return delegate.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options);
     }
 
     @Override
-    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        return delegate.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition);
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
+        delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition, options);
     }
 
     @Override
-    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
-        delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition);
+    public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
+                    StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+        return delegate.getMethodSubstitution(plugin, original, context, allowAssumptions, options);
     }
 
     @Override
-    public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        return delegate.getSubstitution(method, invokeBci, trackNodeSourcePosition, replaceePosition);
+    public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) {
+        delegate.registerMethodSubstitution(plugin, original, context, options);
     }
 
     @Override
-    public Bytecode getSubstitutionBytecode(ResolvedJavaMethod method) {
-        return delegate.getSubstitutionBytecode(method);
+    public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) {
+        return delegate.getSubstitution(method, invokeBci, trackNodeSourcePosition, replaceePosition, options);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,6 @@
 
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.SnippetTemplateCache;
-import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.DebugContext;
@@ -34,7 +33,9 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -44,7 +45,7 @@
  */
 public interface Replacements {
 
-    OptionValues getOptions();
+    CoreProviders getProviders();
 
     /**
      * Gets the object managing the various graph builder plugins used by this object when parsing
@@ -60,30 +61,41 @@
     /**
      * Gets the snippet graph derived from a given method.
      *
-     * @param args arguments to the snippet if available, otherwise {@code null}
-     * @param trackNodeSourcePosition
-     * @return the snippet graph, if any, that is derived from {@code method}
-     */
-    default StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        return getSnippet(method, null, args, trackNodeSourcePosition, replaceePosition);
-    }
-
-    /**
-     * Gets the snippet graph derived from a given method.
-     *
      * @param recursiveEntry if the snippet contains a call to this method, it's considered as
      *            recursive call and won't be processed for {@linkplain MethodSubstitution
      *            substitutions}.
      * @param args arguments to the snippet if available, otherwise {@code null}
      * @param trackNodeSourcePosition
+     * @param options
      * @return the snippet graph, if any, that is derived from {@code method}
      */
-    StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition);
+    StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition,
+                    OptionValues options);
 
     /**
      * Registers a method as snippet.
      */
-    void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition);
+    void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options);
+
+    /**
+     * Gets a graph that is a substitution for a given {@link MethodSubstitutionPlugin plugin} in
+     * the {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext
+     * context}.
+     *
+     * @param plugin the plugin being substituted
+     * @param original the method being substituted
+     * @param context the kind of inlining to be performed for the substitution
+     * @param allowAssumptions
+     * @param options
+     * @return the method substitution graph, if any, that is derived from {@code method}
+     */
+    StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
+                    StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options);
+
+    /**
+     * Registers a plugin as a substitution.
+     */
+    void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options);
 
     /**
      * Gets a graph that is a substitution for a given method.
@@ -91,17 +103,10 @@
      * @param invokeBci the call site BCI if this request is made for inlining a substitute
      *            otherwise {@code -1}
      * @param trackNodeSourcePosition
+     * @param options
      * @return the graph, if any, that is a substitution for {@code method}
      */
-    StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition);
-
-    /**
-     * Gets the substitute bytecode for a given method.
-     *
-     * @return the bytecode to substitute for {@code method} or {@code null} if there is no
-     *         substitute bytecode for {@code method}
-     */
-    Bytecode getSubstitutionBytecode(ResolvedJavaMethod method);
+    StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options);
 
     /**
      * Gets a graph produced from the intrinsic for a given method that can be compiled and
@@ -116,7 +121,7 @@
 
     /**
      * Determines if there may be a
-     * {@linkplain #getSubstitution(ResolvedJavaMethod, int, boolean, NodeSourcePosition)
+     * {@linkplain #getSubstitution(ResolvedJavaMethod, int, boolean, NodeSourcePosition, OptionValues)
      * substitution graph} for a given method.
      *
      * A call to {@link #getSubstitution} may still return {@code null} for {@code method} and
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Fri May 03 14:59:32 2019 -0400
@@ -243,10 +243,12 @@
             EconomicSet<Node> unsafeNodes = null;
             Graph.NodeEventScope nodeEventScope = null;
             OptionValues options = node.getOptions();
-            if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) {
+            boolean verifyGraalGraphEdges = Graph.Options.VerifyGraalGraphEdges.getValue(options);
+            boolean verifyKillCFGUnusedNodes = GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options);
+            if (verifyGraalGraphEdges) {
                 unsafeNodes = collectUnsafeNodes(node.graph());
             }
-            if (GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options)) {
+            if (verifyKillCFGUnusedNodes) {
                 EconomicSet<Node> collectedUnusedNodes = unusedNodes = EconomicSet.create(Equivalence.IDENTITY);
                 nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
                     @Override
@@ -260,12 +262,12 @@
             debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "Before killCFG %s", node);
             killCFGInner(node);
             debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "After killCFG %s", node);
-            if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) {
+            if (verifyGraalGraphEdges) {
                 EconomicSet<Node> newUnsafeNodes = collectUnsafeNodes(node.graph());
                 newUnsafeNodes.removeAll(unsafeNodes);
                 assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes;
             }
-            if (GraphUtil.Options.VerifyKillCFGUnusedNodes.getValue(options)) {
+            if (verifyKillCFGUnusedNodes) {
                 nodeEventScope.close();
                 Iterator<Node> iterator = unusedNodes.iterator();
                 while (iterator.hasNext()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Fri May 03 14:59:32 2019 -0400
@@ -511,6 +511,8 @@
                                 allow = true;
                             }
                         } else {
+                            // Fortify: Suppress Null Dereference false positive
+                            assert bestPossibleStamp != null;
                             allow = (bestPossibleStamp.asConstant() != null);
                         }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.phases.common;
 
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -34,7 +35,6 @@
 import org.graalvm.compiler.nodes.AbstractMergeNode;
 import org.graalvm.compiler.nodes.DynamicDeoptimizeNode;
 import org.graalvm.compiler.nodes.EndNode;
-import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.LoopBeginNode;
 import org.graalvm.compiler.nodes.LoopExitNode;
@@ -59,54 +59,53 @@
     protected void run(StructuredGraph graph, MidTierContext context) {
         ControlFlowGraph cfg = null;
         for (FrameState fs : graph.getNodes(FrameState.TYPE)) {
-            FixedNode target = null;
-            PhiNode reasonActionPhi = null;
-            PhiNode speculationPhi = null;
-            List<AbstractDeoptimizeNode> obsoletes = null;
-            for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) {
-                if (target == null) {
-                    target = deopt;
-                } else {
-                    if (cfg == null) {
-                        cfg = ControlFlowGraph.compute(graph, true, true, false, false);
-                    }
-                    AbstractMergeNode merge;
-                    if (target instanceof AbstractDeoptimizeNode) {
-                        merge = graph.add(new MergeNode());
-                        EndNode firstEnd = graph.add(new EndNode());
-                        ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess());
-                        ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess());
-                        reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge));
-                        speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge));
-                        merge.addForwardEnd(firstEnd);
-                        reasonActionPhi.addInput(actionAndReason);
-                        speculationPhi.addInput(speculation);
-                        target.replaceAtPredecessor(firstEnd);
+            Iterator<AbstractDeoptimizeNode> iterator = fs.usages().filter(AbstractDeoptimizeNode.class).iterator();
+            if (!iterator.hasNext()) {
+                // No deopt
+                continue;
+            }
+            AbstractDeoptimizeNode first = iterator.next();
+            if (!iterator.hasNext()) {
+                // Only 1 deopt
+                continue;
+            }
+            // There is more than one deopt, create a merge
+            if (cfg == null) {
+                cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+            }
+            AbstractMergeNode merge = graph.add(new MergeNode());
+            EndNode firstEnd = graph.add(new EndNode());
+            ValueNode actionAndReason = first.getActionAndReason(context.getMetaAccess());
+            ValueNode speculation = first.getSpeculation(context.getMetaAccess());
+            PhiNode reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge));
+            PhiNode speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge));
+            merge.addForwardEnd(firstEnd);
+            reasonActionPhi.addInput(actionAndReason);
+            speculationPhi.addInput(speculation);
+            first.replaceAtPredecessor(firstEnd);
+            exitLoops(first, firstEnd, cfg);
+            DynamicDeoptimizeNode dynamicDeopt;
+            try (DebugCloseable position = first.withNodeSourcePosition()) {
+                dynamicDeopt = new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi);
+                merge.setNext(graph.add(dynamicDeopt));
+            }
+            List<AbstractDeoptimizeNode> obsoletes = new LinkedList<>();
+            obsoletes.add(first);
 
-                        exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
-                        try (DebugCloseable position = target.withNodeSourcePosition()) {
-                            merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi)));
-                        }
-                        obsoletes = new LinkedList<>();
-                        obsoletes.add((AbstractDeoptimizeNode) target);
-                        target = merge;
-                    } else {
-                        merge = (AbstractMergeNode) target;
-                    }
-                    EndNode newEnd = graph.add(new EndNode());
-                    merge.addForwardEnd(newEnd);
-                    reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
-                    speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
-                    deopt.replaceAtPredecessor(newEnd);
-                    exitLoops(deopt, newEnd, cfg);
-                    obsoletes.add(deopt);
-                }
-            }
-            if (obsoletes != null) {
-                ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs);
-                for (AbstractDeoptimizeNode obsolete : obsoletes) {
-                    obsolete.safeDelete();
-                }
+            do {
+                AbstractDeoptimizeNode deopt = iterator.next();
+                EndNode newEnd = graph.add(new EndNode());
+                merge.addForwardEnd(newEnd);
+                reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
+                speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
+                deopt.replaceAtPredecessor(newEnd);
+                exitLoops(deopt, newEnd, cfg);
+                obsoletes.add(deopt);
+            } while (iterator.hasNext());
+
+            dynamicDeopt.setStateBefore(fs);
+            for (AbstractDeoptimizeNode obsolete : obsoletes) {
+                obsolete.safeDelete();
             }
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java	Fri May 03 14:59:32 2019 -0400
@@ -254,6 +254,8 @@
             for (MemoryMap state : states) {
                 MemoryNode last = state.getLastLocationAccess(key);
                 if (isPhi) {
+                    // Fortify: Suppress Null Deference false positive (`isPhi == true` implies
+                    // `merged != null`)
                     ((MemoryPhiNode) merged).addInput(ValueNodeUtil.asNode(last));
                 } else {
                     if (merged == last) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java	Fri May 03 14:59:32 2019 -0400
@@ -137,7 +137,8 @@
             int index = 0;
             for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
                 ValueNode thisReason = reasons != null ? reasons.get(index) : reason;
-                ValueNode thisSpeculation = speculations != null ? speculations.get(index++) : speculation;
+                ValueNode thisSpeculation = speculations != null ? speculations.get(index) : speculation;
+                index++;
                 if (!thisReason.isConstant() || !thisSpeculation.isConstant()) {
                     continue;
                 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Fri May 03 14:59:32 2019 -0400
@@ -72,7 +72,6 @@
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.InvokeNode;
 import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
-import org.graalvm.compiler.nodes.KillingBeginNode;
 import org.graalvm.compiler.nodes.LogicNode;
 import org.graalvm.compiler.nodes.MergeNode;
 import org.graalvm.compiler.nodes.NodeView;
@@ -93,7 +92,6 @@
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.java.MonitorExitNode;
 import org.graalvm.compiler.nodes.java.MonitorIdNode;
-import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
@@ -466,11 +464,7 @@
             // A partial intrinsic exit must be replaced with a call to
             // the intrinsified method.
             Invoke dup = (Invoke) duplicates.get(exit.asNode());
-            if (dup instanceof InvokeNode) {
-                ((InvokeNode) dup).replaceWithNewBci(invoke.bci());
-            } else {
-                ((InvokeWithExceptionNode) dup).replaceWithNewBci(invoke.bci());
-            }
+            dup.replaceBci(invoke.bci());
         }
         if (unwindNode != null) {
             unwindNode = (UnwindNode) duplicates.get(unwindNode);
@@ -544,15 +538,7 @@
             }
 
             // get rid of memory kill
-            AbstractBeginNode begin = invokeWithException.next();
-            if (begin instanceof KillingBeginNode) {
-                try (DebugCloseable position = begin.withNodeSourcePosition()) {
-                    AbstractBeginNode newBegin = new BeginNode();
-                    graph.addAfterFixed(begin, graph.add(newBegin));
-                    begin.replaceAtUsages(newBegin);
-                    graph.removeFixed(begin);
-                }
-            }
+            invokeWithException.killKillingBegin();
         } else {
             if (unwindNode != null && unwindNode.isAlive()) {
                 try (DebugCloseable position = unwindNode.withNodeSourcePosition()) {
@@ -836,7 +822,7 @@
 
         // Return value does no longer need to be limited by the monitor exit.
         for (MonitorExitNode n : frameState.usages().filter(MonitorExitNode.class)) {
-            n.clearEscapedReturnValue();
+            n.clearEscapedValue();
         }
 
         frameState.replaceAndDelete(stateAfterReturn);
@@ -1005,14 +991,6 @@
         }
     }
 
-    public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target, int invokeBci) {
-        return replacements.hasSubstitution(target, invokeBci);
-    }
-
-    public static StructuredGraph getIntrinsicGraph(Replacements replacements, ResolvedJavaMethod target, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
-        return replacements.getSubstitution(target, invokeBci, trackNodeSourcePosition, replaceePosition);
-    }
-
     /**
      * This method exclude InstrumentationNode from inlining heuristics.
      */
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java	Fri May 03 14:59:32 2019 -0400
@@ -69,7 +69,7 @@
     private FixedNodeRelativeFrequencyCache probabilites = new FixedNodeRelativeFrequencyCache();
 
     public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer, boolean trackNodeSourcePosition) {
-        StructuredGraph original = InliningUtil.getIntrinsicGraph(context.getReplacements(), method, invoke.bci(), trackNodeSourcePosition, null);
+        StructuredGraph original = context.getReplacements().getSubstitution(method, invoke.bci(), trackNodeSourcePosition, null, invoke.asNode().getOptions());
         if (original == null) {
             original = parseBytecodes(method, context, canonicalizer, invoke.asNode().graph(), trackNodeSourcePosition);
         } else if (original.isFrozen()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/AbstractInliningPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -31,7 +31,6 @@
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.Replacements;
-import org.graalvm.compiler.phases.common.inlining.InliningUtil;
 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
 
@@ -69,7 +68,7 @@
 
     private static boolean onlyIntrinsics(Replacements replacements, InlineInfo info) {
         for (int i = 0; i < info.numberOfMethods(); i++) {
-            if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i), info.invoke().bci())) {
+            if (!replacements.hasSubstitution(info.methodAt(i), info.invoke().bci())) {
                 return false;
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -64,10 +64,10 @@
     }
 
     @Override
-    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-        final boolean isTracing = TraceInlining.getValue(replacements.getOptions());
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) {
+        OptionValues options = calleeInfo.graph().getOptions();
+        final boolean isTracing = TraceInlining.getValue(options);
         final InlineInfo info = invocation.callee();
-        OptionValues options = info.graph().getOptions();
         final double probability = invocation.probability();
         final double relevance = invocation.relevance();
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -31,6 +31,7 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.phases.common.inlining.InliningUtil;
+import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
 
 public class InlineEverythingPolicy implements InliningPolicy {
@@ -44,7 +45,7 @@
     }
 
     @Override
-    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-        return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(replacements.getOptions()), "inline everything");
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) {
+        return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(calleeInfo.graph().getOptions()), "inline everything");
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,7 @@
 import org.graalvm.compiler.nodes.CallTargetNode;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.spi.Replacements;
+import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -38,11 +39,11 @@
 public final class InlineMethodSubstitutionsPolicy extends InlineEverythingPolicy {
 
     @Override
-    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-        final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed) {
+        final boolean isTracing = GraalOptions.TraceInlining.getValue(calleeInfo.graph().getOptions());
         CallTargetNode callTarget = invocation.callee().invoke().callTarget();
         if (callTarget instanceof MethodCallTargetNode) {
-            ResolvedJavaMethod calleeMethod = ((MethodCallTargetNode) callTarget).targetMethod();
+            ResolvedJavaMethod calleeMethod = callTarget.targetMethod();
             if (replacements.hasSubstitution(calleeMethod, invocation.callee().invoke().bci())) {
                 return Decision.YES.withReason(isTracing, "has a method subtitution");
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java	Fri May 03 14:59:32 2019 -0400
@@ -26,6 +26,7 @@
 
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.Replacements;
+import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
 
 public interface InliningPolicy {
@@ -60,5 +61,5 @@
 
     boolean continueInlining(StructuredGraph graph);
 
-    Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
+    Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, InlineInfo calleeInfo, int inliningDepth, boolean fullyProcessed);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java	Fri May 03 14:59:32 2019 -0400
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.CallTargetNode;
+import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.ParameterNode;
@@ -144,7 +145,7 @@
         OptionValues options = rootGraph.getOptions();
         if (method == null) {
             return "the method is not resolved";
-        } else if (method.isNative() && (!Intrinsify.getValue(options) || !InliningUtil.canIntrinsify(context.getReplacements(), method, invokeBci))) {
+        } else if (method.isNative() && (!Intrinsify.getValue(options) || !context.getReplacements().hasSubstitution(method, invokeBci))) {
             return "it is a non-intrinsic native method";
         } else if (method.isAbstract()) {
             return "it is an abstract method";
@@ -191,11 +192,12 @@
         MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
 
-        if (callTarget.invokeKind() == CallTargetNode.InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
+        InvokeKind invokeKind = callTarget.invokeKind();
+        if (invokeKind == CallTargetNode.InvokeKind.Special || invokeKind == CallTargetNode.InvokeKind.Static || targetMethod.canBeStaticallyBound()) {
             return getExactInlineInfo(invoke, targetMethod);
         }
 
-        assert callTarget.invokeKind().isIndirect();
+        assert invokeKind.isIndirect();
 
         ResolvedJavaType holder = targetMethod.getDeclaringClass();
         if (!(callTarget.receiver().stamp(NodeView.DEFAULT) instanceof ObjectStamp)) {
@@ -457,7 +459,7 @@
         assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke());
         counterInliningConsidered.increment(debug);
 
-        InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true);
+        InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, calleeInfo, inliningDepth, true);
         if (decision.shouldInline()) {
             doInline(callerCallsiteHolder, calleeInvocation, decision.getReason());
             return true;
@@ -718,7 +720,8 @@
 
         final MethodInvocation currentInvocation = currentInvocation();
 
-        final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false).shouldInline());
+        final boolean backtrack = (!currentInvocation.isRoot() &&
+                        !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, currentInvocation.callee(), inliningDepth(), false).shouldInline());
         if (backtrack) {
             int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs();
             assert remainingGraphs > 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Fri May 03 14:59:32 2019 -0400
@@ -69,6 +69,7 @@
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.graphio.GraphBlocks;
 import org.graalvm.graphio.GraphElements;
+import org.graalvm.graphio.GraphLocations;
 import org.graalvm.graphio.GraphOutput;
 import org.graalvm.graphio.GraphStructure;
 import org.graalvm.graphio.GraphTypes;
@@ -77,7 +78,6 @@
 import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Signature;
-import org.graalvm.graphio.GraphLocations;
 
 public class BinaryGraphPrinter implements
                 GraphStructure<BinaryGraphPrinter.GraphInfo, Node, NodeClass<?>, Edges>,
@@ -528,7 +528,7 @@
             public URI getURI() {
                 String path = e.getFileName();
                 try {
-                    return path == null ? null : new URI(null, null, path, null);
+                    return new URI(null, null, path == null ? "(Unknown Source)" : path, null);
                 } catch (URISyntaxException ex) {
                     throw new IllegalArgumentException(ex);
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64BitCountNode.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.replacements.aarch64;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.replacements.nodes.BitCountNode;
+
+@NodeInfo(cycles = CYCLES_4, size = SIZE_4)
+public final class AArch64BitCountNode extends BitCountNode {
+
+    public static final NodeClass<AArch64BitCountNode> TYPE = NodeClass.create(AArch64BitCountNode.class);
+
+    public AArch64BitCountNode(ValueNode value) {
+        super(TYPE, value);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java	Fri May 03 14:59:32 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
@@ -64,8 +64,8 @@
         invocationPlugins.defer(new Runnable() {
             @Override
             public void run() {
-                registerIntegerLongPlugins(invocationPlugins, AArch64IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider);
-                registerIntegerLongPlugins(invocationPlugins, AArch64LongSubstitutions.class, JavaKind.Long, bytecodeProvider);
+                registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, bytecodeProvider);
+                registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, bytecodeProvider);
                 if (registerMathPlugins) {
                     registerMathPlugins(invocationPlugins);
                 }
@@ -80,7 +80,7 @@
         });
     }
 
-    private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, JavaKind kind, BytecodeProvider bytecodeProvider) {
+    private static void registerIntegerLongPlugins(InvocationPlugins plugins, JavaKind kind, BytecodeProvider bytecodeProvider) {
         Class<?> declaringClass = kind.toBoxedJavaClass();
         Class<?> type = kind.toJavaClass();
         Registration r = new Registration(plugins, declaringClass, bytecodeProvider);
@@ -108,7 +108,13 @@
                 return true;
             }
         });
-        r.registerMethodSubstitution(substituteDeclaringClass, "bitCount", type);
+        r.register1("bitCount", type, new InvocationPlugin() {
+            @Override
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                b.push(JavaKind.Int, b.append(new AArch64BitCountNode(value).canonical(null)));
+                return true;
+            }
+        });
     }
 
     private static void registerMathPlugins(InvocationPlugins plugins) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerSubstitutions.java	Fri May 03 11:28:14 2019 -0700
+++ /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.
- */
-
-
-package org.graalvm.compiler.replacements.aarch64;
-
-import org.graalvm.compiler.api.replacements.ClassSubstitution;
-import org.graalvm.compiler.api.replacements.MethodSubstitution;
-
-/**
- * AArch64 ISA offers a count leading zeros instruction which can be used to implement
- * numberOfLeadingZeros more efficiently than using BitScanReverse.
- */
-@ClassSubstitution(Integer.class)
-public class AArch64IntegerSubstitutions {
-
-    @MethodSubstitution
-    public static int bitCount(int value) {
-        // Based on Warren, Hacker's Delight, slightly adapted to profit from Aarch64 add + shift
-        // instruction.
-        // Assuming the peephole optimizer optimizes all x - y >>> z into a single instruction
-        // this takes 10 instructions.
-        int x = value;
-        x = x - ((x & 0xaaaaaaaa) >>> 1);
-        x = (x & 0x33333333) + ((x & 0xcccccccc) >>> 2);
-        x = (x + (x >>> 4)) & 0x0f0f0f0f;
-        x = x + (x >>> 8);
-        x = x + (x >>> 16);
-        return x & 0x3f;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64LongSubstitutions.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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.
- */
-
-
-package org.graalvm.compiler.replacements.aarch64;
-
-import org.graalvm.compiler.api.replacements.ClassSubstitution;
-import org.graalvm.compiler.api.replacements.MethodSubstitution;
-
-/**
- * Aarch64 ISA offers a count leading zeros instruction which can be used to implement
- * numberOfLeadingZeros more efficiently than using BitScanReverse.
- */
-@ClassSubstitution(Long.class)
-public class AArch64LongSubstitutions {
-
-    @MethodSubstitution
-    public static int bitCount(long value) {
-        // Based on Warren, Hacker's Delight, slightly adapted to profit from Aarch64 add + shift
-        // instruction.
-        // Assuming the peephole optimizer optimizes all x - y >>> z into a single instruction
-        // this takes 11 instructions.
-        long x = value;
-        x = x - ((x & 0xaaaaaaaaaaaaaaaaL) >>> 1);
-        x = (x & 0x3333333333333333L) + ((x & 0xccccccccccccccccL) >>> 2);
-        x = (x + (x >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
-        x = x + (x >>> 8);
-        x = x + (x >>> 16);
-        x = x + (x >>> 32);
-        return (int) x & 0x7f;
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java	Fri May 03 14:59:32 2019 -0400
@@ -84,7 +84,9 @@
             if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) {
                 constantArgument(processor, out, deps, argCount, param.asType(), argCount);
             } else {
-                out.printf("        assert checkInjectedArgument(b, args[%d], targetMethod);\n", argCount);
+                out.printf("        if (!checkInjectedArgument(b, args[%d], targetMethod)) {\n", argCount);
+                out.printf("            return false;\n");
+                out.printf("        }\n", argCount);
                 out.printf("        %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType()));
             }
             argCount++;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java	Fri May 03 14:59:32 2019 -0400
@@ -116,7 +116,7 @@
         StructuredGraph graph = testGraph(testMethodName);
 
         // Check to see if the resulting graph contains the expected node
-        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
+        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions());
         if (replacement == null && !optional) {
             assertInGraph(graph, intrinsicClass);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Fri May 03 14:59:32 2019 -0400
@@ -430,7 +430,7 @@
         String compiledReturnValue = IN_COMPILED_HANDLER_MARKER;
         forceCompileOverride = true;
         inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
-        inlineInvokeMethodName = "stringizeId";
+        inlineInvokeMethodName = "stringize";
         try {
             testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER);
         } finally {
@@ -681,6 +681,11 @@
                     public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
                         return null;
                     }
+
+                    @Override
+                    public boolean isAvailable(ForeignCallDescriptor descriptor) {
+                        return true;
+                    }
                 };
             }
             if (type == SnippetReflectionProvider.class) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,144 @@
+/*
+ * 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.replacements.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.internal.vm.compiler.collections.MapCursor;
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.target.Backend;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.util.Providers;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Exercise
+ * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext)}
+ * with regular method substitutions and encoded graphs.
+ */
+@RunWith(Parameterized.class)
+public class RootMethodSubstitutionTest extends GraalCompilerTest {
+
+    public RootMethodSubstitutionTest(ResolvedJavaMethod method) {
+        this.method = method;
+    }
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<Object[]> data() {
+        ArrayList<Object[]> ret = new ArrayList<>();
+
+        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
+        Providers providers = backend.getProviders();
+
+        MapCursor<String, List<InvocationPlugins.Binding>> cursor = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().getBindings(true).getEntries();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        while (cursor.advance()) {
+            String className = cursor.getKey();
+            ResolvedJavaType type = null;
+            try {
+                String typeName = className.substring(1, className.length() - 1).replace('/', '.');
+                ClassLoader cl = ClassLoader.getSystemClassLoader();
+                Class<?> clazz = Class.forName(typeName, true, cl);
+                type = metaAccess.lookupJavaType(clazz);
+            } catch (ClassNotFoundException e) {
+                continue;
+            }
+
+            for (InvocationPlugins.Binding binding : cursor.getValue()) {
+                if (binding.plugin instanceof MethodSubstitutionPlugin) {
+                    ResolvedJavaMethod original = null;
+                    for (ResolvedJavaMethod declared : type.getDeclaredMethods()) {
+                        if (declared.getName().equals(binding.name)) {
+                            if (declared.isStatic() == binding.isStatic) {
+                                if (declared.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) {
+                                    original = declared;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    if (!original.isNative()) {
+                        ret.add(new Object[]{original});
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
+    private final ResolvedJavaMethod method;
+
+    private StructuredGraph getIntrinsicGraph(boolean useEncodedGraphs) {
+        OptionValues options = new OptionValues(getDebugContext().getOptions(), GraalOptions.UseEncodedGraphs, useEncodedGraphs);
+        DebugContext debugContext = DebugContext.create(options, getDebugContext().getDescription(), getDebugHandlersFactories());
+        return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext);
+    }
+
+    StructuredGraph expectedGraph;
+    StructuredGraph actualGraph;
+
+    @Override
+    protected boolean checkHighTierGraph(StructuredGraph graph) {
+        // Capture the graphs after high tier
+        if (expectedGraph == null) {
+            expectedGraph = (StructuredGraph) graph.copy(graph.getDebug());
+        } else {
+            assert actualGraph == null;
+            actualGraph = (StructuredGraph) graph.copy(graph.getDebug());
+        }
+        return super.checkHighTierGraph(graph);
+    }
+
+    @Test
+    public void test() {
+        StructuredGraph regularGraph = getIntrinsicGraph(false);
+        assertTrue(regularGraph != null, "must produce a graph");
+        getCode(method, regularGraph);
+
+        StructuredGraph encodedGraph = getIntrinsicGraph(true);
+        assertTrue(encodedGraph != null, "must produce a graph");
+        getCode(method, encodedGraph);
+
+        // Compare the high tier graphs since the final graph might have scheduler
+        // differences because of different usage ordering.
+        assertEquals(expectedGraph, actualGraph, true, false);
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java	Fri May 03 14:59:32 2019 -0400
@@ -39,7 +39,7 @@
     protected SnippetsTest() {
         ReplacementsImpl d = (ReplacementsImpl) getReplacements();
         bytecodeProvider = getSystemClassLoaderBytecodeProvider();
-        installer = new ReplacementsImpl(getInitialOptions(), null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target);
+        installer = new ReplacementsImpl(null, d.getProviders(), d.snippetReflection, bytecodeProvider, d.target);
         installer.setGraphBuilderPlugins(d.getGraphBuilderPlugins());
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java	Fri May 03 14:59:32 2019 -0400
@@ -138,7 +138,7 @@
         StructuredGraph graph = testGraph(testMethodName);
 
         // Check to see if the resulting graph contains the expected node
-        StructuredGraph replacement = getReplacements().getSubstitution(realJavaMethod, -1, false, null);
+        StructuredGraph replacement = getReplacements().getSubstitution(realJavaMethod, -1, false, null, graph.getOptions());
         if (replacement == null && !optional) {
             assertInGraph(graph, intrinsicClass);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Fri May 03 14:59:32 2019 -0400
@@ -83,7 +83,7 @@
         StructuredGraph graph = testGraph(testMethod.getName());
 
         // Check to see if the resulting graph contains the expected node
-        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
+        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions());
         if (replacement == null) {
             assertInGraph(graph, expectedNode);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java	Fri May 03 14:59:32 2019 -0400
@@ -312,7 +312,7 @@
         }
 
         StructuredGraph replacementGraph() {
-            return getReplacements().getSubstitution(javamethod, -1, false, null);
+            return getReplacements().getSubstitution(javamethod, -1, false, null, getInitialOptions());
         }
 
         StructuredGraph testMethodGraph() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfCharTest.java	Fri May 03 14:59:32 2019 -0400
@@ -53,8 +53,8 @@
                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
         String[] targets = new String[]{"foobar", "foo", "bar", "\u03bbfoobar", mediumString, mediumUTF16String, longString, longUTF16String};
         int[] targetChars = new int[]{'f', 'o', 'r', 'x', Character.MIN_SUPPLEMENTARY_CODE_POINT};
-        int[] targetOffsets = new int[18];
-        for (int i = 0; i < 18; i++) {
+        int[] targetOffsets = new int[12];
+        for (int i = 0; i < targetOffsets.length; i++) {
             targetOffsets[i] = i - 1;
         }
         for (String source : targets) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionTestBase.java	Fri May 03 14:59:32 2019 -0400
@@ -28,8 +28,8 @@
 import org.junit.Assert;
 import org.junit.Assume;
 
+import jdk.vm.ci.aarch64.AArch64;
 import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.aarch64.AArch64;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
@@ -71,7 +71,7 @@
         StructuredGraph graph = testGraph(testMethod.getName());
 
         // Check to see if the resulting graph contains the expected node
-        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
+        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions());
         if (replacement == null) {
             assertInGraph(graph, expectedNode);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java	Fri May 03 14:59:32 2019 -0400
@@ -43,7 +43,7 @@
         StructuredGraph graph = testGraph(testMethodName);
 
         // Check to see if the resulting graph contains the expected node
-        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null);
+        StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions());
         if (replacement == null && !optional) {
             assertInGraph(graph, intrinsicClass);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java	Fri May 03 14:59:32 2019 -0400
@@ -26,6 +26,7 @@
 
 import static org.graalvm.compiler.core.GraalCompiler.compileGraph;
 import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeSourcePosition;
+import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs;
 
 import java.util.List;
 
@@ -44,6 +45,7 @@
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -100,6 +102,7 @@
         //   at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest$TestMethod.test(int) [bci: -1]
         //   at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest.methodSubstitution(SubstitutionNodeSourcePositionTest.java:89) [bci: 2]
         // @formatter:on
+        Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions()));
         checkMappings("methodSubstitution", true, TestMethod.class, "test");
     }
 
@@ -119,6 +122,7 @@
         //
         // The precise snippet bytecodes don't matter, just ensure that some actually appear after
         // lowering.
+        Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions()));
         checkMappings("snippetLowering", true, SubstitutionNodeSourcePositionTest.class, "snippetLowering");
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Fri May 03 14:59:32 2019 -0400
@@ -140,6 +140,11 @@
         return false;
     }
 
+    /**
+     * Keep test time down by only sampling a limited number of class files per jar.
+     */
+    private static final int CLASSES_PER_JAR = 250;
+
     @Test
     public void test() {
         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
@@ -156,28 +161,33 @@
             if (shouldProcess(path)) {
                 try {
                     final ZipFile zipFile = new ZipFile(new File(path));
+                    int index = 0;
+                    int step = zipFile.size() > CLASSES_PER_JAR ? zipFile.size() / CLASSES_PER_JAR : 1;
                     for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
                         final ZipEntry zipEntry = entry.nextElement();
-                        String name = zipEntry.getName();
-                        if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) {
-                            String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
-                            if (isInNativeImage(className)) {
-                                /*
-                                 * Native image requires non-graalsdk classes to be present in the
-                                 * classpath.
-                                 */
-                                continue;
-                            }
-                            if (isGSON(className)) {
-                                /* uses old class format */
-                                continue;
-                            }
-                            try {
-                                checkClass(metaAccess, getSnippetReflection(), className);
-                            } catch (ClassNotFoundException e) {
-                                throw new AssertionError(e);
+                        if ((index % step) == 0) {
+                            String name = zipEntry.getName();
+                            if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) {
+                                String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
+                                if (isInNativeImage(className)) {
+                                    /*
+                                     * Native image requires non-graalsdk classes to be present in
+                                     * the classpath.
+                                     */
+                                    continue;
+                                }
+                                if (isGSON(className)) {
+                                    /* uses old class format */
+                                    continue;
+                                }
+                                try {
+                                    checkClass(metaAccess, getSnippetReflection(), className);
+                                } catch (ClassNotFoundException e) {
+                                    throw new AssertionError(e);
+                                }
                             }
                         }
+                        index++;
                     }
                 } catch (IOException ex) {
                     Assert.fail(ex.toString());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,8 @@
 
 package org.graalvm.compiler.replacements;
 
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs;
 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
@@ -41,6 +43,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
@@ -82,45 +85,65 @@
     }
 
     @SuppressWarnings("try")
-    private EncodedGraph createGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) {
-        // @formatter:off
-        StructuredGraph graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions).
-                        useProfilingInfo(false).
-                        trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()).
-                        method(method).
-                        setIsSubstitution(isSubstitution).
-                        cancellable(graph.getCancellable()).
-                        build();
+    private EncodedGraph createGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) {
+        StructuredGraph graphToEncode;
+        if (isSubstitution && (UseEncodedGraphs.getValue(options) || IS_IN_NATIVE_IMAGE)) {
+            // These must go through Replacements to find the graph to use.
+            graphToEncode = providers.getReplacements().getMethodSubstitution(plugin, method, INLINE_AFTER_PARSING, allowAssumptions,
+                            options);
+        } else {
+            graphToEncode = buildGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution);
+        }
+
+        /*
+         * ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that fewer
+         * frame states will be created. This significantly reduces the number of nodes in the
+         * initial graph.
+         */
+        try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) {
+            PhaseContext context = new PhaseContext(providers);
+            new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context);
+        } catch (Throwable t) {
+            throw debug.handle(t);
+        }
+
+        EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graphToEncode, architecture);
+        graphCache.put(method, encodedGraph);
+        return encodedGraph;
+    }
+
+    @SuppressWarnings("try")
+    private StructuredGraph buildGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) {
+        StructuredGraph graphToEncode;// @formatter:off
+        graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions).
+                useProfilingInfo(false).
+                trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()).
+                method(plugin != null ? plugin.getSubstitute(providers.getMetaAccess()) : method).
+                setIsSubstitution(isSubstitution).
+                cancellable(graph.getCancellable()).
+                build();
         // @formatter:on
         try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) {
-            IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(originalMethod, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
+            IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null
+                            ? new IntrinsicContext(method, plugin.getSubstitute(providers.getMetaAccess()), intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
             GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext);
             graphBuilderPhaseInstance.apply(graphToEncode);
 
             PhaseContext context = new PhaseContext(providers);
             new CanonicalizerPhase().apply(graphToEncode, context);
-            /*
-             * ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that
-             * fewer frame states will be created. This significantly reduces the number of nodes in
-             * the initial graph.
-             */
-            new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context);
-
-            EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graphToEncode, architecture);
-            graphCache.put(method, encodedGraph);
-            return encodedGraph;
 
         } catch (Throwable ex) {
             throw debug.handle(ex);
         }
+        return graphToEncode;
     }
 
     @Override
-    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
+    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
                     boolean trackNodeSourcePosition) {
         EncodedGraph result = graphCache.get(method);
         if (result == null && method.hasBytecodes()) {
-            result = createGraph(method, originalMethod, intrinsicBytecodeProvider, isSubstitution);
+            result = createGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution);
         }
         return result;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Fri May 03 14:59:32 2019 -0400
@@ -366,7 +366,7 @@
 
         StructuredGraph calleeGraph;
         if (IS_IN_NATIVE_IMAGE) {
-            calleeGraph = providers.getReplacements().getSnippet(method, null, false, null);
+            calleeGraph = providers.getReplacements().getSnippet(method, null, null, false, null, invoke.getOptions());
         } else {
             calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).setIsSubstitution(
                             true).build();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -281,6 +281,11 @@
     }
 
     @Override
+    public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, Receiver receiver, ValueNode[] argsIncludingReceiver) {
+        throw GraalError.shouldNotReachHere();
+    }
+
+    @Override
     public String toString() {
         return String.format("%s:intrinsic", method.format("%H.%n(%p)"));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Fri May 03 14:59:32 2019 -0400
@@ -95,6 +95,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
 import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
 import org.graalvm.compiler.nodes.java.LoadFieldNode;
@@ -346,7 +347,7 @@
 
         @Override
         public IntrinsicContext getIntrinsic() {
-            return null;
+            return PEGraphDecoder.this.getIntrinsic();
         }
 
         @Override
@@ -375,6 +376,11 @@
         }
 
         @Override
+        public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) {
+            return false;
+        }
+
+        @Override
         public void setStateAfter(StateSplit stateSplit) {
             throw unimplemented();
         }
@@ -422,6 +428,10 @@
         }
     }
 
+    protected IntrinsicContext getIntrinsic() {
+        return null;
+    }
+
     protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext {
         protected FixedWithNextNode lastInstr;
         protected ValueNode pushedNode;
@@ -523,6 +533,11 @@
             appendInvoke(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData, callTarget);
             updateLastInstruction(invoke.asNode());
         }
+
+        @Override
+        public GraphBuilderContext getNonIntrinsicAncestor() {
+            return null;
+        }
     }
 
     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
@@ -829,10 +844,10 @@
         for (InlineInvokePlugin plugin : inlineInvokePlugins) {
             InlineInfo inlineInfo = plugin.shouldInlineInvoke(graphBuilderContext, targetMethod, arguments);
             if (inlineInfo != null) {
-                if (inlineInfo.getMethodToInline() == null) {
+                if (inlineInfo.allowsInlining()) {
+                    return doInline(methodScope, loopScope, invokeData, inlineInfo, arguments);
+                } else {
                     return null;
-                } else {
-                    return doInline(methodScope, loopScope, invokeData, inlineInfo, arguments);
                 }
             }
         }
@@ -844,9 +859,7 @@
             return null;
         }
         ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline();
-        ResolvedJavaMethod originalMethod = inlineInfo.getOriginalMethod();
-        boolean isSubstitution = originalMethod != null && !originalMethod.equals(inlineMethod);
-        EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, originalMethod, inlineInfo.getIntrinsicBytecodeProvider(), isSubstitution, graph.trackNodeSourcePosition());
+        EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getPlugin(), inlineInfo.getIntrinsicBytecodeProvider(), inlineInfo.isSubstitution(), graph.trackNodeSourcePosition());
         if (graphToInline == null) {
             return null;
         }
@@ -1115,7 +1128,7 @@
         }
     }
 
-    protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
+    protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
                     boolean trackNodeSourcePosition);
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -27,9 +27,11 @@
 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
 import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache;
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
+import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo;
+import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createMethodSubstitutionInlineInfo;
 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION;
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
@@ -80,9 +82,6 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.spi.Replacements;
-import org.graalvm.compiler.options.Option;
-import org.graalvm.compiler.options.OptionKey;
-import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -99,15 +98,7 @@
 
 public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
 
-    public static class Options {
-        // @formatter:off
-        @Option(help = "This is a testing option to exercise the SymbolicSnippetEncoder", type = OptionType.Expert)
-        public static final OptionKey<Boolean> UseEncodedSnippets = new OptionKey<>(false);
-        // @formatter:on
-    }
-
-    protected final OptionValues options;
-
+    @Override
     public Providers getProviders() {
         return providers;
     }
@@ -122,11 +113,6 @@
     private GraphBuilderConfiguration.Plugins graphBuilderPlugins;
     private final DebugHandlersFactory debugHandlersFactory;
 
-    @Override
-    public OptionValues getOptions() {
-        return options;
-    }
-
     /**
      * The preprocessed replacement graphs.
      */
@@ -170,11 +156,11 @@
      */
     @Override
     public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
-        Bytecode subst = getSubstitutionBytecode(method);
-        if (subst != null) {
+        MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method);
+        if (msPlugin != null) {
             if (b.parsingIntrinsic() || InlineDuringParsing.getValue(b.getOptions()) || InlineIntrinsicsDuringParsing.getValue(b.getOptions())) {
                 // Forced inlining of intrinsics
-                return createIntrinsicInlineInfo(subst.getMethod(), method, subst.getOrigin());
+                return createMethodSubstitutionInlineInfo(method, msPlugin);
             }
             return null;
         }
@@ -182,7 +168,7 @@
             assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
 
             // Force inlining when parsing replacements
-            return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider);
+            return createIntrinsicInlineInfo(method, defaultBytecodeProvider);
         } else {
             assert IS_BUILDING_NATIVE_IMAGE || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s",
                             NodeIntrinsic.class.getSimpleName(),
@@ -215,9 +201,8 @@
     // it is stable across VM executions (in support of replay compilation).
     private final EconomicMap<String, SnippetTemplateCache> snippetTemplateCache;
 
-    public ReplacementsImpl(OptionValues options, DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider,
+    public ReplacementsImpl(DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider,
                     TargetDescription target) {
-        this.options = options;
         this.providers = providers.copyWith(this);
         this.snippetReflection = snippetReflection;
         this.target = target;
@@ -232,24 +217,28 @@
 
     private static final AtomicInteger nextDebugContextId = new AtomicInteger();
 
-    public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) {
-        DebugContext outer = DebugContext.forCurrentThread();
-        Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet());
-        List<DebugHandlersFactory> factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory);
-        return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories);
+    public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) {
+        if (DebugStubsAndSnippets.getValue(options)) {
+            DebugContext outer = DebugContext.forCurrentThread();
+            Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet());
+            List<DebugHandlersFactory> factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory);
+            return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories);
+        }
+        return DebugContext.disabled(options);
     }
 
     @Override
     @SuppressWarnings("try")
-    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
+    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition,
+                    OptionValues options) {
         assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
         assert method.hasBytecodes() : "Snippet must not be abstract or native";
 
         StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(method) : null;
         if (graph == null || (trackNodeSourcePosition && !graph.trackNodeSourcePosition())) {
-            try (DebugContext debug = openDebugContext("Snippet_", method);
+            try (DebugContext debug = openDebugContext("Snippet_", method, options);
                             DebugCloseable a = SnippetPreparationTime.start(debug)) {
-                StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry, trackNodeSourcePosition, replaceePosition);
+                StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING);
                 DebugContext.counter("SnippetNodeCount[%#s]", method).add(newGraph.getDebug(), newGraph.getNodeCount());
                 if (!UseSnippetGraphCache.getValue(options) || args != null) {
                     return newGraph;
@@ -268,11 +257,23 @@
     }
 
     @Override
-    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
+    public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
         // No initialization needed as snippet graphs are created on demand in getSnippet
     }
 
     @Override
+    public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
+                    StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+        // Method substitutions are parsed by the BytecodeParser.
+        return null;
+    }
+
+    @Override
+    public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) {
+        // No initialization needed as method substitutions are parsed by the BytecodeParser.
+    }
+
+    @Override
     public boolean hasSubstitution(ResolvedJavaMethod method, int invokeBci) {
         InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method);
         return plugin != null && (!plugin.inlineOnly() || invokeBci >= 0);
@@ -283,19 +284,17 @@
         return defaultBytecodeProvider;
     }
 
-    @Override
-    public Bytecode getSubstitutionBytecode(ResolvedJavaMethod method) {
+    protected MethodSubstitutionPlugin getMethodSubstitution(ResolvedJavaMethod method) {
         InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method);
         if (plugin instanceof MethodSubstitutionPlugin) {
             MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin;
-            ResolvedJavaMethod substitute = msPlugin.getSubstitute(providers.getMetaAccess());
-            return msPlugin.getBytecodeProvider().getBytecode(substitute);
+            return msPlugin;
         }
         return null;
     }
 
     @Override
-    public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
+    public StructuredGraph getSubstitution(ResolvedJavaMethod method, int invokeBci, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) {
         StructuredGraph result;
         InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method);
         if (plugin != null && (!plugin.inlineOnly() || invokeBci >= 0)) {
@@ -305,8 +304,8 @@
                 ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess);
                 StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null;
                 if (graph == null || graph.trackNodeSourcePosition() != trackNodeSourcePosition) {
-                    try (DebugContext debug = openDebugContext("Substitution_", method)) {
-                        graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method, trackNodeSourcePosition, replaceePosition);
+                    try (DebugContext debug = openDebugContext("Substitution_", method, options)) {
+                        graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING);
                         if (!UseSnippetGraphCache.getValue(options)) {
                             return graph;
                         }
@@ -319,7 +318,7 @@
                 result = graph;
             } else {
                 Bytecode code = new ResolvedJavaMethodBytecode(method);
-                try (DebugContext debug = openDebugContext("Substitution_", method)) {
+                try (DebugContext debug = openDebugContext("Substitution_", method, options)) {
                     result = new IntrinsicGraphBuilder(options, debug, providers, code, invokeBci).buildGraph(plugin);
                 }
             }
@@ -332,13 +331,13 @@
     @SuppressWarnings("try")
     @Override
     public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
-        Bytecode subst = getSubstitutionBytecode(method);
-        if (subst != null) {
-            ResolvedJavaMethod substMethod = subst.getMethod();
+        MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method);
+        if (msPlugin != null) {
+            ResolvedJavaMethod substMethod = msPlugin.getSubstitute(providers.getMetaAccess());
             assert !substMethod.equals(method);
-            BytecodeProvider bytecodeProvider = subst.getOrigin();
+            BytecodeProvider bytecodeProvider = msPlugin.getBytecodeProvider();
             // @formatter:off
-            StructuredGraph graph = new StructuredGraph.Builder(options, debug, StructuredGraph.AllowAssumptions.YES).
+            StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug, StructuredGraph.AllowAssumptions.YES).
                     method(substMethod).
                     compilationId(compilationId).
                     recordInlinedMethods(bytecodeProvider.shouldRecordMethodDependencies()).
@@ -367,11 +366,32 @@
      * @param args
      * @param original the original method if {@code method} is a {@linkplain MethodSubstitution
      *            substitution} otherwise null
-     * @param trackNodeSourcePosition
+     * @param trackNodeSourcePosition record source information
+     * @param context
+     *            {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext
+     *            compilation context} for the graph
      */
     public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, boolean trackNodeSourcePosition,
-                    NodeSourcePosition replaceePosition) {
-        return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, trackNodeSourcePosition, replaceePosition);
+                    NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) {
+        return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, trackNodeSourcePosition, replaceePosition, context);
+    }
+
+    /**
+     * Creates a preprocessed graph for a snippet or method substitution with a context of .
+     * {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext#INLINE_AFTER_PARSING}
+     * .
+     *
+     *
+     * @param bytecodeProvider how to access the bytecode of {@code method}
+     * @param method the snippet or method substitution for which a graph will be created
+     * @param args
+     * @param original the original method if {@code method} is a {@linkplain MethodSubstitution
+     *            substitution} otherwise null
+     * @param trackNodeSourcePosition record source information
+     */
+    public final StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original,
+                    boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
+        return makeGraph(debug, bytecodeProvider, method, args, original, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING);
     }
 
     /**
@@ -408,10 +428,11 @@
         }
 
         @SuppressWarnings("try")
-        public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
+        public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition,
+                        IntrinsicContext.CompilationContext context) {
             try (DebugContext.Scope s = debug.scope("BuildSnippetGraph", method)) {
                 assert method.hasBytecodes() : method;
-                StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, trackNodeSourcePosition, replaceePosition);
+                StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, trackNodeSourcePosition, replaceePosition, context);
 
                 finalizeGraph(graph);
 
@@ -427,7 +448,7 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            if (!GraalOptions.SnippetCounters.getValue(replacements.options) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) {
+            if (!GraalOptions.SnippetCounters.getValue(graph.getOptions()) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) {
                 int sideEffectCount = 0;
                 assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0;
                 new ConvertDeoptimizeToGuardPhase().apply(graph, null);
@@ -471,16 +492,39 @@
             return false;
         }
 
+        static class EncodedIntrinsicContext extends IntrinsicContext {
+            EncodedIntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext,
+                            boolean allowPartialIntrinsicArgumentMismatch) {
+                super(method, intrinsic, bytecodeProvider, compilationContext, allowPartialIntrinsicArgumentMismatch);
+            }
+
+            @Override
+            public boolean isDeferredInvoke(StateSplit stateSplit) {
+                if (stateSplit instanceof Invoke) {
+                    Invoke invoke = (Invoke) stateSplit;
+                    ResolvedJavaMethod method = invoke.callTarget().targetMethod();
+                    if (method.getAnnotation(Fold.class) != null) {
+                        return true;
+                    }
+                    Node.NodeIntrinsic annotation = method.getAnnotation(Node.NodeIntrinsic.class);
+                    if (annotation != null && !annotation.hasSideEffect()) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+
         /**
          * Builds the initial graph for a replacement.
          */
         @SuppressWarnings("try")
         protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, boolean trackNodeSourcePosition,
-                        NodeSourcePosition replaceePosition) {
+                        NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) {
             // @formatter:off
             // Replacements cannot have optimistic assumptions since they have
             // to be valid for the entire run of the VM.
-            final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug).
+            final StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug).
                             method(methodToParse).
                             trackNodeSourcePosition(trackNodeSourcePosition).
                             callerContext(replaceePosition).
@@ -506,11 +550,11 @@
                 MethodSubstitution methodAnnotation = method.getAnnotation(MethodSubstitution.class);
                 if (methodAnnotation == null && snippetAnnotation == null) {
                     // Post-parse inlined intrinsic
-                    initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING);
+                    initialIntrinsicContext = new EncodedIntrinsicContext(substitutedMethod, method, bytecodeProvider, context, false);
                 } else {
                     // Snippet
                     ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
-                    initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING,
+                    initialIntrinsicContext = new EncodedIntrinsicContext(original, method, bytecodeProvider, context,
                                     snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true);
                 }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Fri May 03 14:59:32 2019 -0400
@@ -675,7 +675,7 @@
             ResolvedJavaMethod javaMethod = findMethod(providers.getMetaAccess(), declaringClass, methodName);
             assert javaMethod != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName;
             assert javaMethod.getAnnotation(Snippet.class) != null : javaMethod + " must be annotated with @" + Snippet.class.getSimpleName();
-            providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options));
+            providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options), options);
             LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations;
             if (GraalOptions.EagerSnippets.getValue(options)) {
                 return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver);
@@ -691,7 +691,7 @@
                 Description description = new Description(args.cacheKey.method, "SnippetTemplate_" + nextSnippetTemplateId.incrementAndGet());
                 return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories);
             }
-            return DebugContext.DISABLED;
+            return DebugContext.disabled(options);
         }
 
         /**
@@ -764,7 +764,8 @@
 
         Object[] constantArgs = getConstantArgs(args);
         boolean shouldTrackNodeSourcePosition1 = trackNodeSourcePosition || (providers.getCodeCache() != null && providers.getCodeCache().shouldDebugNonSafepoints());
-        StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, args.info.original, constantArgs, shouldTrackNodeSourcePosition1, replacee.getNodeSourcePosition());
+        StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, args.info.original, constantArgs, shouldTrackNodeSourcePosition1, replacee.getNodeSourcePosition(),
+                        options);
 
         ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
@@ -965,7 +966,9 @@
                         }
                         retNode.setMemoryMap(null);
                     }
-                    memoryMap.safeDelete();
+                    if (memoryMap != null) {
+                        memoryMap.safeDelete();
+                    }
                 }
                 if (needsAnchor) {
                     snippetCopy.addAfterFixed(snippetCopy.start(), anchor);
@@ -1484,55 +1487,6 @@
 
             rewireFrameStates(replacee, duplicates);
 
-            if (replacee instanceof DeoptimizingNode) {
-                DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
-
-                FrameState stateBefore = null;
-                FrameState stateDuring = null;
-                FrameState stateAfter = null;
-                if (replaceeDeopt.canDeoptimize()) {
-                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
-                        stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
-                    }
-                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
-                        stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
-                    }
-                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
-                        stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
-                    }
-                }
-
-                for (DeoptimizingNode deoptNode : deoptNodes) {
-                    DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode());
-                    if (deoptDup.canDeoptimize()) {
-                        if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
-                            ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
-                        }
-                        if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
-                            DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
-                            if (stateDuring != null) {
-                                deoptDupDuring.setStateDuring(stateDuring);
-                            } else if (stateAfter != null) {
-                                deoptDupDuring.computeStateDuring(stateAfter);
-                            } else if (stateBefore != null) {
-                                assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring;
-                                deoptDupDuring.setStateDuring(stateBefore);
-                            }
-                        }
-                        if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
-                            DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
-                            if (stateAfter != null) {
-                                deoptDupAfter.setStateAfter(stateAfter);
-                            } else {
-                                assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter;
-                                deoptDupAfter.setStateAfter(stateBefore);
-                            }
-
-                        }
-                    }
-                }
-            }
-
             updateStamps(replacee, duplicates);
 
             rewireMemoryGraph(replacee, duplicates);
@@ -1656,7 +1610,8 @@
             FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
             replaceeGraph.addAfterFixed(lastFixedNode, firstCFGNodeDuplicate);
 
-            rewireFrameStates(replacee, duplicates);
+            // floating nodes are not state-splits not need to re-wire frame states
+            assert !(replacee instanceof StateSplit);
             updateStamps(replacee, duplicates);
 
             rewireMemoryGraph(replacee, duplicates);
@@ -1710,7 +1665,8 @@
             }
             UnmodifiableEconomicMap<Node, Node> duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements);
 
-            rewireFrameStates(replacee, duplicates);
+            // floating nodes are not state-splits not need to re-wire frame states
+            assert !(replacee instanceof StateSplit);
             updateStamps(replacee, duplicates);
 
             rewireMemoryGraph(replacee, duplicates);
@@ -1725,12 +1681,64 @@
     }
 
     protected void rewireFrameStates(ValueNode replacee, UnmodifiableEconomicMap<Node, Node> duplicates) {
-        if (replacee instanceof StateSplit) {
+        if (replacee.graph().getGuardsStage().areFrameStatesAtSideEffects() && replacee instanceof StateSplit) {
             for (StateSplit sideEffectNode : sideEffectNodes) {
                 assert ((StateSplit) replacee).hasSideEffect();
                 Node sideEffectDup = duplicates.get(sideEffectNode.asNode());
                 ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter());
             }
+        } else if (replacee.graph().getGuardsStage().areFrameStatesAtDeopts() && replacee instanceof DeoptimizingNode) {
+            DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
+
+            FrameState stateBefore = null;
+            FrameState stateDuring = null;
+            FrameState stateAfter = null;
+            if (replaceeDeopt.canDeoptimize()) {
+                if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
+                    stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
+                }
+                if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
+                    stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
+                }
+                if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
+                    stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
+                }
+            }
+
+            for (DeoptimizingNode deoptNode : deoptNodes) {
+                DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode());
+                if (deoptDup.canDeoptimize()) {
+                    if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
+                        ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
+                    }
+                    if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
+                        // compute a state "during" for a DeoptDuring inside the snippet depending
+                        // on what kind of states we had on the node we are replacing.
+                        // If the original node had a state "during" already, we just use that,
+                        // otherwise we need to find a strategy to compute a state during based on
+                        // some other state (before or after).
+                        DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
+                        if (stateDuring != null) {
+                            deoptDupDuring.setStateDuring(stateDuring);
+                        } else if (stateAfter != null) {
+                            deoptDupDuring.computeStateDuring(stateAfter);
+                        } else if (stateBefore != null) {
+                            assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring;
+                            deoptDupDuring.setStateDuring(stateBefore);
+                        }
+                    }
+                    if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
+                        DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
+                        if (stateAfter != null) {
+                            deoptDupAfter.setStateAfter(stateAfter);
+                        } else {
+                            assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter;
+                            deoptDupAfter.setStateAfter(stateBefore);
+                        }
+
+                    }
+                }
+            }
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java	Fri May 03 14:59:32 2019 -0400
@@ -188,11 +188,11 @@
         return locationIdentity;
     }
 
-    @NodeIntrinsic
+    @NodeIntrinsic(hasSideEffect = true)
     private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind, @ConstantNodeParameter boolean aligned,
                     @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized, @ConstantNodeParameter int heapWordSize);
 
-    @NodeIntrinsic
+    @NodeIntrinsic(hasSideEffect = true)
     private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind,
                     @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter boolean aligned, @ConstantNodeParameter boolean disjoint,
                     @ConstantNodeParameter boolean uninitialized, @ConstantNodeParameter int heapWordSize);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java	Fri May 03 14:59:32 2019 -0400
@@ -49,9 +49,10 @@
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.PiNode;
+import org.graalvm.compiler.nodes.SnippetAnchorNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode;
+import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.extended.RawStoreNode;
 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
@@ -69,7 +70,6 @@
 import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
-import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 import jdk.internal.vm.compiler.word.Pointer;
@@ -108,19 +108,10 @@
 
     protected abstract int heapWordSize();
 
-    @Snippet
-    public void arraycopyZeroLengthSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
-                    @ConstantParameter Counters counters) {
-        Object nonNullSrc = GraalDirectives.guardingNonNull(src);
-        Object nonNullDest = GraalDirectives.guardingNonNull(dest);
-        this.checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
-        checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
-        counters.zeroLengthStaticCounter.inc();
-    }
-
+    @SuppressWarnings("unused")
     @Snippet
     public void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
-                    @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity,
+                    @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity,
                     @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) {
         Object nonNullSrc = GraalDirectives.guardingNonNull(src);
         Object nonNullDest = GraalDirectives.guardingNonNull(dest);
@@ -130,31 +121,37 @@
 
         elementKindCounter.inc();
         elementKindCopiedCounter.add(length);
-        ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind, locationIdentity, heapWordSize());
+
+        ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
     }
 
+    @SuppressWarnings("unused")
     @Snippet
-    public void arraycopyUnrolledSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
-                    @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity, @ConstantParameter int unrolledLength, @ConstantParameter Counters counters) {
+    public void arraycopyExactStubCallSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
+                    @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity locationIdentity,
+                    @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter, @ConstantParameter Counters counters) {
         Object nonNullSrc = GraalDirectives.guardingNonNull(src);
         Object nonNullDest = GraalDirectives.guardingNonNull(dest);
         checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
         incrementLengthCounter(length, counters);
 
-        unrolledArraycopyWork(nonNullSrc, srcPos, nonNullDest, destPos, unrolledLength, elementKind, locationIdentity);
+        elementKindCounter.inc();
+        elementKindCopiedCounter.add(length);
+
+        ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind, locationIdentity, heapWordSize());
     }
 
     @Snippet
-    public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
-                    @ConstantParameter Counters counters, @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) {
+    public void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters,
+                    @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) {
         Object nonNullSrc = GraalDirectives.guardingNonNull(src);
         Object nonNullDest = GraalDirectives.guardingNonNull(dest);
         checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
         incrementLengthCounter(length, counters);
 
-        ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
+        ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
     }
 
     @Snippet
@@ -166,7 +163,7 @@
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
         incrementLengthCounter(length, counters);
 
-        ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
+        ArrayCopyWithDelayedLoweringNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
     }
 
     @Snippet
@@ -179,31 +176,35 @@
         System.arraycopy(src, srcPos, dest, destPos, length);
     }
 
-    private static void unrolledArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, JavaKind elementKind, LocationIdentity arrayLocation) {
+    @SuppressWarnings("unused")
+    @Snippet(allowPartialIntrinsicArgumentMismatch = true)
+    public void exactArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter LocationIdentity arrayLocation,
+                    @ConstantParameter Counters counters) {
         int scale = ReplacementsUtil.arrayIndexScale(INJECTED_META_ACCESS, elementKind);
         int arrayBaseOffset = ReplacementsUtil.getArrayBaseOffset(INJECTED_META_ACCESS, elementKind);
-
         long sourceOffset = arrayBaseOffset + (long) srcPos * scale;
         long destOffset = arrayBaseOffset + (long) destPos * scale;
-        long position = 0;
-        long delta = scale;
-        if (probability(NOT_FREQUENT_PROBABILITY, nonNullSrc == nonNullDest && srcPos < destPos)) {
+
+        GuardingNode anchor = SnippetAnchorNode.anchor();
+        if (probability(NOT_FREQUENT_PROBABILITY, src == dest && srcPos < destPos)) {
             // bad aliased case so we need to copy the array from back to front
-            position = (long) (length - 1) * scale;
-            delta = -delta;
-        }
-
-        // the length was already checked before - we can emit unconditional instructions
-        ExplodeLoopNode.explodeLoop();
-        for (int iteration = 0; iteration < length; iteration++) {
-            Object value = RawLoadNode.load(nonNullSrc, sourceOffset + position, elementKind, arrayLocation);
-            RawStoreNode.storeObject(nonNullDest, destOffset + position, value, elementKind, arrayLocation, false);
-            position += delta;
+            for (int position = length - 1; position >= 0; position--) {
+                Object value = GuardedUnsafeLoadNode.guardedLoad(src, sourceOffset + ((long) position) * scale, elementKind, arrayLocation, anchor);
+                RawStoreNode.storeObject(dest, destOffset + ((long) position) * scale, value, elementKind, arrayLocation, true);
+            }
+        } else {
+            for (int position = 0; position < length; position++) {
+                Object value = GuardedUnsafeLoadNode.guardedLoad(src, sourceOffset + ((long) position) * scale, elementKind, arrayLocation, anchor);
+                RawStoreNode.storeObject(dest, destOffset + ((long) position) * scale, value, elementKind, arrayLocation, true);
+            }
         }
     }
 
+    @SuppressWarnings("unused")
     @Snippet(allowPartialIntrinsicArgumentMismatch = true)
-    public void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
+    public void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind,
+                    @ConstantParameter LocationIdentity arrayLocation,
+                    @ConstantParameter Counters counters) {
         if (probability(FREQUENT_PROBABILITY, length > 0)) {
             Object nonNullSrc = PiNode.asNonNullObject(src);
             Object nonNullDest = PiNode.asNonNullObject(dest);
@@ -234,8 +235,11 @@
         }
     }
 
+    @SuppressWarnings("unused")
     @Snippet(allowPartialIntrinsicArgumentMismatch = true)
-    public void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
+    public void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind,
+                    @ConstantParameter LocationIdentity arrayLocation,
+                    @ConstantParameter Counters counters) {
         // The length > 0 check should not be placed here because generic array copy stub should
         // enforce type check. This is fine performance-wise because this snippet is rarely used.
         counters.genericArraycopyDifferentTypeCounter.inc();
@@ -352,16 +356,17 @@
 
     public static class Templates extends SnippetTemplate.AbstractTemplates {
         private final SnippetInfo arraycopyGenericSnippet;
-        private final SnippetInfo arraycopyUnrolledSnippet;
         private final SnippetInfo arraycopyExactSnippet;
-        private final SnippetInfo arraycopyZeroLengthSnippet;
+        private final SnippetInfo arraycopyExactStubCallSnippet;
         private final SnippetInfo arraycopyCheckcastSnippet;
         private final SnippetInfo arraycopyNativeSnippet;
         private final SnippetInfo checkcastArraycopyWithSlowPathWork;
         private final SnippetInfo genericArraycopyWithSlowPathWork;
+        private final SnippetInfo exactArraycopyWithSlowPathWork;
 
         private ResolvedJavaMethod originalArraycopy;
         private final Counters counters;
+        private boolean expandArraycopyLoop;
 
         public Templates(ArrayCopySnippets receiver, OptionValues options, Iterable<DebugHandlersFactory> factories, Factory factory, Providers providers,
                         SnippetReflectionProvider snippetReflection, TargetDescription target) {
@@ -369,13 +374,13 @@
             this.counters = new Counters(factory);
 
             arraycopyGenericSnippet = snippet(receiver, "arraycopyGenericSnippet");
-            arraycopyUnrolledSnippet = snippet(receiver, "arraycopyUnrolledSnippet");
             arraycopyExactSnippet = snippet(receiver, "arraycopyExactSnippet");
-            arraycopyZeroLengthSnippet = snippet(receiver, "arraycopyZeroLengthSnippet");
+            arraycopyExactStubCallSnippet = snippet(receiver, "arraycopyExactStubCallSnippet");
             arraycopyCheckcastSnippet = snippet(receiver, "arraycopyCheckcastSnippet");
             arraycopyNativeSnippet = snippet(null, "arraycopyNativeSnippet");
             checkcastArraycopyWithSlowPathWork = snippet(receiver, "checkcastArraycopyWithSlowPathWork");
             genericArraycopyWithSlowPathWork = snippet(receiver, "genericArraycopyWithSlowPathWork");
+            exactArraycopyWithSlowPathWork = snippet(receiver, "exactArraycopyWithSlowPathWork");
         }
 
         protected SnippetInfo snippet(ArrayCopySnippets receiver, String methodName) {
@@ -401,7 +406,7 @@
 
                 if (arraycopy.isExact()) {
                     // there is a sufficient type match - we don't need any additional type checks
-                    snippetInfo = arraycopyExactSnippet;
+                    snippetInfo = arraycopyExactStubCallSnippet;
                     arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK;
                 } else if (srcComponentType == null && destComponentType == null) {
                     // we don't know anything about the types - use the generic copying
@@ -426,7 +431,7 @@
                     if (nonNullComponentType.isPrimitive()) {
                         // one involved object is a primitive array - it is sufficient to directly
                         // compare the hub.
-                        snippetInfo = arraycopyExactSnippet;
+                        snippetInfo = arraycopyExactStubCallSnippet;
                         arrayTypeCheck = ArrayCopyTypeCheck.HUB_BASED_ARRAY_TYPE_CHECK;
                         elementKind = nonNullComponentType.getJavaKind();
                     } else {
@@ -438,17 +443,8 @@
                 }
             }
 
-            // a few special cases that are easier to handle when all other variables already have a
-            // value
-            if (snippetInfo != arraycopyNativeSnippet && snippetInfo != arraycopyGenericSnippet && arraycopy.getLength().isConstant() && arraycopy.getLength().asJavaConstant().asLong() == 0) {
-                // Copying 0 element between object arrays with conflicting types will not throw an
-                // exception - once we pass the preliminary element type checks that we are not
-                // mixing arrays of different basic types, ArrayStoreException is only thrown when
-                // an *astore would have thrown it. Therefore, copying null between object arrays
-                // with conflicting types will also succeed (we do not optimize for such case here).
-                snippetInfo = arraycopyZeroLengthSnippet;
-            } else if (snippetInfo == arraycopyExactSnippet && shouldUnroll(arraycopy.getLength())) {
-                snippetInfo = arraycopyUnrolledSnippet;
+            if (this.expandArraycopyLoop && snippetInfo == arraycopyExactStubCallSnippet) {
+                snippetInfo = arraycopyExactSnippet;
             }
 
             // create the snippet
@@ -463,13 +459,9 @@
                 args.addConst("arrayTypeCheck", arrayTypeCheck);
             }
             Object locationIdentity = arraycopy.killsAnyLocation() ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(elementKind);
-            if (snippetInfo == arraycopyUnrolledSnippet) {
-                args.addConst("elementKind", elementKind != null ? elementKind : JavaKind.Illegal);
-                args.addConst("locationIdentity", locationIdentity);
-                args.addConst("unrolledLength", arraycopy.getLength().asJavaConstant().asInt());
-            }
-            if (snippetInfo == arraycopyExactSnippet) {
+            if (snippetInfo == arraycopyExactStubCallSnippet || snippetInfo == arraycopyExactSnippet) {
                 assert elementKind != null;
+                args.addConst("workSnippet", exactArraycopyWithSlowPathWork);
                 args.addConst("elementKind", elementKind);
                 args.addConst("locationIdentity", locationIdentity);
                 args.addConst("elementKindCounter", counters.arraycopyCallCounters.get(elementKind));
@@ -488,11 +480,19 @@
             instantiate(args, arraycopy);
         }
 
-        public void lower(ArrayCopyWithSlowPathNode arraycopy, LoweringTool tool) {
+        public void lower(ArrayCopyWithDelayedLoweringNode arraycopy, LoweringTool tool) {
             StructuredGraph graph = arraycopy.graph();
-            if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
-                // if an arraycopy contains a slow path, we can't lower it right away
-                return;
+
+            if (arraycopy.getSnippet() == exactArraycopyWithSlowPathWork && this.expandArraycopyLoop) {
+                if (!graph.getGuardsStage().areDeoptsFixed()) {
+                    // Don't lower until floating guards are fixed.
+                    return;
+                }
+            } else {
+                if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
+                    // Don't lower until frame states are assigned to deoptimization points.
+                    return;
+                }
             }
 
             SnippetInfo snippetInfo = arraycopy.getSnippet();
@@ -502,6 +502,12 @@
             args.add("dest", arraycopy.getDestination());
             args.add("destPos", arraycopy.getDestinationPosition());
             args.add("length", arraycopy.getLength());
+
+            JavaKind elementKind = arraycopy.getElementKind();
+            args.addConst("elementKind", (elementKind == null) ? JavaKind.Illegal : elementKind);
+
+            Object locationIdentity = (elementKind == null) ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(arraycopy.getElementKind());
+            args.addConst("arrayLocation", locationIdentity);
             args.addConst("counters", counters);
             instantiate(args, arraycopy);
         }
@@ -526,10 +532,6 @@
             return srcType.getComponentType().getJavaKind();
         }
 
-        private static boolean shouldUnroll(ValueNode length) {
-            return length.isConstant() && length.asJavaConstant().asInt() <= 8 && length.asJavaConstant().asInt() != 0;
-        }
-
         /**
          * Instantiate the snippet template and fix up the FrameState of any Invokes of
          * System.arraycopy and propagate the captured bci in the ArrayCopySlowPathNode.
@@ -551,19 +553,19 @@
                         throw new GraalError("unexpected invoke %s in snippet", call.targetMethod());
                     }
                     // Here we need to fix the bci of the invoke
-                    InvokeNode newInvoke = invoke.replaceWithNewBci(arraycopy.getBci());
-                    newInvoke.setStateDuring(null);
-                    newInvoke.setStateAfter(null);
+                    invoke.replaceBci(arraycopy.getBci());
+                    invoke.setStateDuring(null);
+                    invoke.setStateAfter(null);
                     if (arraycopy.stateDuring() != null) {
-                        newInvoke.setStateDuring(arraycopy.stateDuring());
+                        invoke.setStateDuring(arraycopy.stateDuring());
                     } else {
                         assert arraycopy.stateAfter() != null : arraycopy;
-                        newInvoke.setStateAfter(arraycopy.stateAfter());
+                        invoke.setStateAfter(arraycopy.stateAfter());
                     }
                 } else if (originalNode instanceof InvokeWithExceptionNode) {
                     throw new GraalError("unexpected invoke with exception %s in snippet", originalNode);
-                } else if (originalNode instanceof ArrayCopyWithSlowPathNode) {
-                    ArrayCopyWithSlowPathNode slowPath = (ArrayCopyWithSlowPathNode) replacements.get(originalNode);
+                } else if (originalNode instanceof ArrayCopyWithDelayedLoweringNode) {
+                    ArrayCopyWithDelayedLoweringNode slowPath = (ArrayCopyWithDelayedLoweringNode) replacements.get(originalNode);
                     assert arraycopy.stateAfter() != null : arraycopy;
                     assert slowPath.stateAfter() == arraycopy.stateAfter();
                     slowPath.setBci(arraycopy.getBci());
@@ -582,5 +584,9 @@
             }
             return originalArraycopy;
         }
+
+        public void setExpandArraycopyLoop(boolean b) {
+            this.expandArraycopyLoop = b;
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+
+package org.graalvm.compiler.replacements.arraycopy;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.type.StampTool;
+import org.graalvm.compiler.replacements.SnippetTemplate;
+import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.meta.JavaKind;
+
+@NodeInfo(allowedUsageTypes = InputType.Memory)
+public final class ArrayCopyWithDelayedLoweringNode extends BasicArrayCopyNode {
+
+    public static final NodeClass<ArrayCopyWithDelayedLoweringNode> TYPE = NodeClass.create(ArrayCopyWithDelayedLoweringNode.class);
+
+    private final SnippetTemplate.SnippetInfo snippet;
+
+    public ArrayCopyWithDelayedLoweringNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) {
+        super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI);
+        assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked";
+        this.snippet = snippet;
+    }
+
+    @NodeIntrinsic
+    public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet,
+                    @ConstantNodeParameter JavaKind elementKind);
+
+    public SnippetTemplate.SnippetInfo getSnippet() {
+        return snippet;
+    }
+
+    public void setBci(int bci) {
+        this.bci = bci;
+    }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithSlowPathNode.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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.
- */
-
-
-package org.graalvm.compiler.replacements.arraycopy;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.type.StampTool;
-import org.graalvm.compiler.replacements.SnippetTemplate;
-import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
-
-import jdk.vm.ci.code.BytecodeFrame;
-import jdk.vm.ci.meta.JavaKind;
-
-@NodeInfo(allowedUsageTypes = InputType.Memory)
-public final class ArrayCopyWithSlowPathNode extends BasicArrayCopyNode {
-
-    public static final NodeClass<ArrayCopyWithSlowPathNode> TYPE = NodeClass.create(ArrayCopyWithSlowPathNode.class);
-
-    private final SnippetTemplate.SnippetInfo snippet;
-
-    public ArrayCopyWithSlowPathNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) {
-        super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI);
-        assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked";
-        this.snippet = snippet;
-    }
-
-    @NodeIntrinsic
-    public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet,
-                    @ConstantNodeParameter JavaKind elementKind);
-
-    public SnippetTemplate.SnippetInfo getSnippet() {
-        return snippet;
-    }
-
-    public void setBci(int bci) {
-        this.bci = bci;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitCountNode.java	Fri May 03 14:59:32 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,12 +46,16 @@
 import jdk.vm.ci.meta.JavaKind;
 
 @NodeInfo(cycles = CYCLES_2, size = SIZE_1)
-public final class BitCountNode extends UnaryNode implements ArithmeticLIRLowerable {
+public class BitCountNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     public static final NodeClass<BitCountNode> TYPE = NodeClass.create(BitCountNode.class);
 
     public BitCountNode(ValueNode value) {
-        super(TYPE, computeStamp(value.stamp(NodeView.DEFAULT), value), value);
+        this(TYPE, value);
+    }
+
+    public BitCountNode(NodeClass<? extends BitCountNode> c, ValueNode value) {
+        super(c, computeStamp(value.stamp(NodeView.DEFAULT), value), value);
         assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Fri May 03 14:59:32 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
@@ -29,22 +29,38 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
 
+import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
+
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.Services;
 
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+
 /**
- * Interface to functionality that abstracts over which JDK version Graal is running on.
+ * JDK 13+ version of {@link GraalServices}.
  */
 public final class GraalServices {
 
+    private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
+
     private GraalServices() {
     }
 
@@ -54,8 +70,37 @@
      * @throws SecurityException if on JDK8 and a security manager is present and it denies
      *             {@link JVMCIPermission}
      */
+    @SuppressWarnings("unchecked")
     public static <S> Iterable<S> load(Class<S> service) {
-        Iterable<S> iterable = ServiceLoader.load(service);
+        if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
+            List<?> list = servicesCache.get(service);
+            if (list != null) {
+                return (Iterable<S>) list;
+            }
+            if (IS_IN_NATIVE_IMAGE) {
+                throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
+            }
+        }
+
+        Iterable<S> providers = load0(service);
+
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            synchronized (servicesCache) {
+                ArrayList<S> providersList = new ArrayList<>();
+                for (S provider : providers) {
+                    providersList.add(provider);
+                }
+                providers = providersList;
+                servicesCache.put(service, providersList);
+                return providers;
+            }
+        }
+
+        return providers;
+    }
+
+    protected static <S> Iterable<S> load0(Class<S> service) {
+        Iterable<S> iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader());
         return new Iterable<>() {
             @Override
             public Iterator<S> iterator() {
@@ -90,6 +135,8 @@
      * @param other all JVMCI packages will be opened to the module defining this class
      */
     static void openJVMCITo(Class<?> other) {
+        if (IS_IN_NATIVE_IMAGE) return;
+
         Module jvmciModule = JVMCI_MODULE;
         Module otherModule = other.getModule();
         if (jvmciModule != otherModule) {
@@ -98,7 +145,7 @@
                     // JVMCI initialization opens all JVMCI packages
                     // to Graal which is a prerequisite for Graal to
                     // open JVMCI packages to other modules.
-                    JVMCI.initialize();
+                    JVMCI.getRuntime();
 
                     jvmciModule.addOpens(pkg, otherModule);
                 }
@@ -179,6 +226,7 @@
         final int groupId;
         final String groupName;
         final Object[] context;
+        private SpeculationReasonEncoding encoding;
 
         DirectSpeculationReason(int groupId, String groupName, Object[] context) {
             this.groupId = groupId;
@@ -204,6 +252,123 @@
         public String toString() {
             return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
         }
+
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                encoding.addInt(groupId);
+                for (Object o : context) {
+                    if (o == null) {
+                        encoding.addInt(0);
+                    } else {
+                        addNonNullObject(encoding, o);
+                    }
+                }
+            }
+            return encoding;
+        }
+
+        static void addNonNullObject(SpeculationReasonEncoding encoding, Object o) {
+            Class<? extends Object> c = o.getClass();
+            if (c == String.class) {
+                encoding.addString((String) o);
+            } else if (c == Byte.class) {
+                encoding.addByte((Byte) o);
+            } else if (c == Short.class) {
+                encoding.addShort((Short) o);
+            } else if (c == Character.class) {
+                encoding.addShort((Character) o);
+            } else if (c == Integer.class) {
+                encoding.addInt((Integer) o);
+            } else if (c == Long.class) {
+                encoding.addLong((Long) o);
+            } else if (c == Float.class) {
+                encoding.addInt(Float.floatToRawIntBits((Float) o));
+            } else if (c == Double.class) {
+                encoding.addLong(Double.doubleToRawLongBits((Double) o));
+            } else if (o instanceof Enum) {
+                encoding.addInt(((Enum<?>) o).ordinal());
+            } else if (o instanceof ResolvedJavaMethod) {
+                encoding.addMethod((ResolvedJavaMethod) o);
+            } else if (o instanceof ResolvedJavaType) {
+                encoding.addType((ResolvedJavaType) o);
+            } else if (o instanceof ResolvedJavaField) {
+                encoding.addField((ResolvedJavaField) o);
+            } else if (o instanceof SpeculationContextObject) {
+                SpeculationContextObject sco = (SpeculationContextObject) o;
+                // These are compiler objects which all have the same class
+                // loader so the class name uniquely identifies the class.
+                encoding.addString(o.getClass().getName());
+                sco.accept(new EncodingAdapter(encoding));
+            } else if (o.getClass() == BytecodePosition.class) {
+                BytecodePosition p = (BytecodePosition) o;
+                while (p != null) {
+                    encoding.addInt(p.getBCI());
+                    encoding.addMethod(p.getMethod());
+                    p = p.getCaller();
+                }
+            } else {
+                throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName());
+            }
+        }
+    }
+
+    static class EncodingAdapter implements SpeculationContextObject.Visitor {
+        private final SpeculationReasonEncoding encoding;
+
+        EncodingAdapter(SpeculationReasonEncoding encoding) {
+            this.encoding = encoding;
+        }
+
+        @Override
+        public void visitBoolean(boolean v) {
+            encoding.addByte(v ? 1 : 0);
+        }
+
+        @Override
+        public void visitByte(byte v) {
+            encoding.addByte(v);
+        }
+
+        @Override
+        public void visitChar(char v) {
+            encoding.addShort(v);
+        }
+
+        @Override
+        public void visitShort(short v) {
+            encoding.addInt(v);
+        }
+
+        @Override
+        public void visitInt(int v) {
+            encoding.addInt(v);
+        }
+
+        @Override
+        public void visitLong(long v) {
+            encoding.addLong(v);
+        }
+
+        @Override
+        public void visitFloat(float v) {
+            encoding.addInt(Float.floatToRawIntBits(v));
+        }
+
+        @Override
+        public void visitDouble(double v) {
+            encoding.addLong(Double.doubleToRawLongBits(v));
+        }
+
+        @Override
+        public void visitObject(Object v) {
+            if (v == null) {
+                encoding.addInt(0);
+            } else {
+                DirectSpeculationReason.addNonNullObject(encoding, v);
+            }
+        }
     }
 
     static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -126,18 +126,14 @@
     public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) {
         ObjectState obj = state.getObjectState(virtual);
         assert obj.isVirtual() : "not virtual: " + obj;
-        ValueNode newValue;
         JavaKind entryKind = virtual.entryKind(index);
         JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind;
-        if (value == null) {
-            newValue = null;
-        } else {
-            newValue = closure.getAliasAndResolve(state, value);
-        }
+        ValueNode newValue = closure.getAliasAndResolve(state, value);
         getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
         ValueNode oldValue = getEntry(virtual, index);
         boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
         if (!canVirtualize) {
+            assert entryKind != JavaKind.Long || newValue != null;
             if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
                 /*
                  * Special case: If the entryKind is long, allow arbitrary kinds as long as a value
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java	Fri May 03 14:59:32 2019 -0400
@@ -634,7 +634,7 @@
         switch (type) {
             case POOL_FIELD: {
                 ResolvedJavaField field = (ResolvedJavaField) found[0];
-                Objects.nonNull(field);
+                Objects.requireNonNull(field);
                 writePoolObject(findFieldDeclaringClass(field));
                 writePoolObject(findFieldName(field));
                 writePoolObject(findFieldTypeName(field));
@@ -653,7 +653,7 @@
             }
             case POOL_NODE_SOURCE_POSITION: {
                 NodeSourcePosition pos = (NodeSourcePosition) found[0];
-                Objects.nonNull(pos);
+                Objects.requireNonNull(pos);
                 ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
                 writePoolObject(method);
                 final int bci = findNodeSourcePositionBCI(pos);
@@ -697,7 +697,7 @@
             }
             case POOL_NODE: {
                 Node node = (Node) found[0];
-                Objects.nonNull(node);
+                Objects.requireNonNull(node);
                 writeInt(findNodeId(node));
                 writePoolObject(classForNode(node));
                 break;
@@ -719,7 +719,7 @@
             }
             case POOL_CLASS: {
                 String typeName = (String) found[0];
-                Objects.nonNull(typeName);
+                Objects.requireNonNull(typeName);
                 writeString(typeName);
                 String[] enumValueNames = findEnumTypeValues(object);
                 if (enumValueNames != null) {
@@ -735,7 +735,7 @@
             }
             case POOL_METHOD: {
                 ResolvedJavaMethod method = (ResolvedJavaMethod) found[0];
-                Objects.nonNull(method);
+                Objects.requireNonNull(method);
                 writePoolObject(findMethodDeclaringClass(method));
                 writePoolObject(findMethodName(method));
                 final Signature methodSignature = findMethodSignature(method);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -40,12 +40,16 @@
 import javax.lang.model.util.SimpleTypeVisitor9;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
 
-import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.*;
+import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.EXECUTABLE_MEMBER_PARAM;
+import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER;
+import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS;
+import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.RECEIVER_TYPE;
 
 /**
  * Print method and constructor info.
@@ -79,7 +83,7 @@
         Content typeParameters = getTypeParameters(member);
         if (!typeParameters.isEmpty()) {
             htmltree.add(typeParameters);
-            htmltree.add(Contents.SPACE);
+            htmltree.add(Entity.NO_BREAK_SPACE);
         }
     }
 
@@ -107,7 +111,7 @@
         }
         String signature = utils.flatSignature((ExecutableElement) member);
         if (signature.length() > 2) {
-            deprecatedLinkContent.add(Contents.ZERO_WIDTH_SPACE);
+            deprecatedLinkContent.add(Entity.ZERO_WIDTH_SPACE);
         }
         deprecatedLinkContent.add(signature);
 
@@ -160,7 +164,7 @@
                 param.asType()).varargs(isVarArg));
         tree.add(link);
         if(name(param).length() > 0) {
-            tree.add(Contents.SPACE);
+            tree.add(Entity.NO_BREAK_SPACE);
             tree.add(name(param));
         }
     }
@@ -176,11 +180,11 @@
     protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType,
             List<? extends AnnotationMirror> annotationMirrors, Content tree) {
         writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree);
-        tree.add(Contents.SPACE);
+        tree.add(Entity.NO_BREAK_SPACE);
         tree.add(utils.getTypeName(rcvrType, false));
         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType);
         tree.add(writer.getTypeParameterLinks(linkInfo));
-        tree.add(Contents.SPACE);
+        tree.add(Entity.NO_BREAK_SPACE);
         tree.add("this");
     }
 
@@ -254,7 +258,7 @@
         if (paramTree.isEmpty()) {
             htmltree.add("()");
         } else {
-            htmltree.add(Contents.ZERO_WIDTH_SPACE);
+            htmltree.add(Entity.ZERO_WIDTH_SPACE);
             htmltree.add("(");
             htmltree.add(paramTree);
             paramTree.add(")");
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -25,9 +25,13 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
@@ -37,6 +41,7 @@
 import javax.lang.model.util.SimpleElementVisitor9;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -338,7 +343,7 @@
         dlTree.add(dt);
         Content dd = new HtmlTree(HtmlTag.DD);
         if (sii.getDescription().isEmpty()) {
-            dd.add(Contents.SPACE);
+            dd.add(Entity.NO_BREAK_SPACE);
         } else {
             dd.add(sii.getDescription());
         }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -25,10 +25,10 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.stream.Collectors;
 
 import javax.lang.model.element.Element;
@@ -39,18 +39,26 @@
 import javax.lang.model.type.TypeMirror;
 
 import com.sun.source.doctree.DocTree;
+
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 
-import static javax.lang.model.element.Modifier.*;
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.NATIVE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STRICTFP;
+import static javax.lang.model.element.Modifier.SYNCHRONIZED;
 
 /**
  * The base class for member writers.
@@ -256,7 +264,7 @@
         if (!set.isEmpty()) {
             String mods = set.stream().map(Modifier::toString).collect(Collectors.joining(" "));
             htmltree.add(mods);
-            htmltree.add(Contents.SPACE);
+            htmltree.add(Entity.NO_BREAK_SPACE);
         }
     }
 
@@ -284,7 +292,7 @@
         addModifier(member, code);
         if (type == null) {
             code.add(utils.isClass(member) ? "class" : "interface");
-            code.add(Contents.SPACE);
+            code.add(Entity.NO_BREAK_SPACE);
         } else {
             List<? extends TypeParameterElement> list = utils.isExecutableElement(member)
                     ? ((ExecutableElement)member).getTypeParameters()
@@ -297,7 +305,7 @@
                 if (typeParameters.charCount() > 10) {
                     code.add(new HtmlTree(HtmlTag.BR));
                 } else {
-                    code.add(Contents.SPACE);
+                    code.add(Entity.NO_BREAK_SPACE);
                 }
                 code.add(
                         writer.getLink(new LinkInfoImpl(configuration,
@@ -498,7 +506,7 @@
      */
     @Override
     public Content getInheritedSummaryHeader(TypeElement tElement) {
-        Content inheritedTree = writer.getMemberTreeHeader();
+        Content inheritedTree = writer.getMemberInheritedTree();
         writer.addInheritedSummaryHeader(this, tElement, inheritedTree);
         return inheritedTree;
     }
@@ -551,8 +559,8 @@
      */
     public Content getMemberTree(Content memberTree, boolean isLastContent) {
         if (isLastContent)
-            return HtmlTree.UL(HtmlStyle.blockListLast, memberTree);
+            return HtmlTree.LI(HtmlStyle.blockListLast, memberTree);
         else
-            return HtmlTree.UL(HtmlStyle.blockList, memberTree);
+            return HtmlTree.LI(HtmlStyle.blockList, memberTree);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -118,7 +118,7 @@
             Content headingContent = contents.getContent(heading);
             Content sectionHeading = HtmlTree.HEADING(Headings.CONTENT_HEADING, true,
                     headingContent);
-            HtmlTree htmlTree = HtmlTree.SECTION(sectionHeading);
+            HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.hierarchy, sectionHeading);
             addLevelInfo(!utils.isInterface(firstTypeElement) ? firstTypeElement : null,
                     sset, isEnums, htmlTree);
             div.add(htmlTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -152,11 +152,8 @@
         Content headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading);
         content.add(headerDiv);
         if (!table.isEmpty()) {
-            HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
-            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
+            HtmlTree div = new HtmlTree(HtmlTag.DIV, table.toContent());
             div.setStyle(HtmlStyle.allClassesContainer);
-            div.add(ul);
             content.add(div);
             if (table.needsScript()) {
                 getMainBodyScript().append(table.getScript());
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -125,7 +125,6 @@
                 table.addRow(pkg, packageLinkContent, summaryContent);
             }
         }
-        HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
-        content.add(HtmlTree.UL(HtmlStyle.blockList, li));
+        content.add(table.toContent());
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,18 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -72,7 +73,7 @@
             Content memberSummaryTree) {
         memberSummaryTree.add(
                 MarkerComments.START_OF_ANNOTATION_TYPE_FIELD_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -88,7 +89,7 @@
      * {@inheritDoc}
      */
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.fieldSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -101,16 +102,17 @@
     /**
      * {@inheritDoc}
      */
-    public void addAnnotationDetailsTreeHeader(TypeElement typeElement,
-            Content memberDetailsTree) {
+    public Content getAnnotationDetailsTreeHeader(TypeElement typeElement) {
+        Content memberDetailsTree = new ContentBuilder();
         if (!writer.printedAnnotationFieldHeading) {
-            memberDetailsTree.add(links.createAnchor(
-                    SectionName.ANNOTATION_TYPE_FIELD_DETAIL));
             Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                     contents.fieldDetailsLabel);
             memberDetailsTree.add(heading);
+            memberDetailsTree.add(links.createAnchor(
+                    SectionName.ANNOTATION_TYPE_FIELD_DETAIL));
             writer.printedAnnotationFieldHeading = true;
         }
+        return memberDetailsTree;
     }
 
     /**
@@ -118,12 +120,12 @@
      */
     public Content getAnnotationDocTreeHeader(Element member,
             Content annotationDetailsTree) {
-        annotationDetailsTree.add(links.createAnchor(name(member)));
-        Content annotationDocTree = writer.getMemberTreeHeader();
+        Content annotationDocTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(name(member));
         annotationDocTree.add(heading);
-        return annotationDocTree;
+        annotationDocTree.add(links.createAnchor(name(member)));
+        return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree);
     }
 
     /**
@@ -137,7 +139,7 @@
                 writer.getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.MEMBER, getType(member)));
         pre.add(link);
-        pre.add(Contents.SPACE);
+        pre.add(Entity.NO_BREAK_SPACE);
         if (configuration.linksource) {
             Content memberName = new StringContent(name(member));
             writer.addSrcLink(member, memberName, pre);
@@ -171,8 +173,11 @@
     /**
      * {@inheritDoc}
      */
-    public Content getAnnotationDetails(Content annotationDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(annotationDetailsTree));
+    public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree) {
+        Content annotationDetails = new ContentBuilder();
+        annotationDetails.add(annotationDetailsTreeHeader);
+        annotationDetails.add(annotationDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.fieldDetails, annotationDetails));
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,14 +25,14 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
@@ -74,7 +74,7 @@
             Content memberSummaryTree) {
         memberSummaryTree.add(
                 MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -84,7 +84,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.memberSummary, memberSummaryTree, memberTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,18 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -74,7 +75,7 @@
             Content memberSummaryTree) {
         memberSummaryTree.add(
                 MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -90,7 +91,7 @@
      * {@inheritDoc}
      */
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.memberSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -103,16 +104,17 @@
     /**
      * {@inheritDoc}
      */
-    public void addAnnotationDetailsTreeHeader(TypeElement te,
-            Content memberDetailsTree) {
+    public Content getAnnotationDetailsTreeHeader(TypeElement te) {
+        Content memberDetailsTree = new ContentBuilder();
         if (!writer.printedAnnotationHeading) {
-            memberDetailsTree.add(links.createAnchor(
-                    SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL));
             Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                     contents.annotationTypeDetailsLabel);
             memberDetailsTree.add(heading);
+            memberDetailsTree.add(links.createAnchor(
+                    SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL));
             writer.printedAnnotationHeading = true;
         }
+        return memberDetailsTree;
     }
 
     /**
@@ -121,13 +123,13 @@
     @Override
     public Content getAnnotationDocTreeHeader(Element member, Content annotationDetailsTree) {
         String simpleName = name(member);
-        annotationDetailsTree.add(links.createAnchor(
-                simpleName + utils.signature((ExecutableElement) member)));
-        Content annotationDocTree = writer.getMemberTreeHeader();
+        Content annotationDocTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(simpleName);
         annotationDocTree.add(heading);
-        return annotationDocTree;
+        annotationDocTree.add(links.createAnchor(
+                simpleName + utils.signature((ExecutableElement) member)));
+        return HtmlTree.SECTION(HtmlStyle.detail, annotationDocTree);
     }
 
     /**
@@ -141,7 +143,7 @@
                 writer.getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.MEMBER, getType(member)));
         pre.add(link);
-        pre.add(Contents.SPACE);
+        pre.add(Entity.NO_BREAK_SPACE);
         if (configuration.linksource) {
             Content memberName = new StringContent(name(member));
             writer.addSrcLink(member, memberName, pre);
@@ -175,8 +177,9 @@
     /**
      * {@inheritDoc}
      */
-    public Content getAnnotationDetails(Content annotationDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(annotationDetailsTree));
+    public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree) {
+        Content annotationDetails = new ContentBuilder(annotationDetailsTreeHeader, annotationDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.memberDetails, annotationDetails));
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -32,6 +32,7 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -101,7 +102,7 @@
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(annotationType);
             Content typeModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typeModuleLabel);
-            moduleNameDiv.add(Contents.SPACE);
+            moduleNameDiv.add(Entity.NO_BREAK_SPACE);
             moduleNameDiv.add(getModuleLink(mdle, new StringContent(mdle.getQualifiedName())));
             div.add(moduleNameDiv);
         }
@@ -109,7 +110,7 @@
         if (!pkg.isUnnamed()) {
             Content typePackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel);
             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, typePackageLabel);
-            pkgNameDiv.add(Contents.SPACE);
+            pkgNameDiv.add(Entity.NO_BREAK_SPACE);
             Content pkgNameContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
             pkgNameDiv.add(pkgNameContent);
             div.add(pkgNameDiv);
@@ -171,7 +172,7 @@
      */
     @Override
     public Content getAnnotationInfo(Content annotationInfoTree) {
-        return getMemberTree(HtmlStyle.description, annotationInfoTree);
+        return HtmlTree.SECTION(HtmlStyle.description, annotationInfoTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -249,14 +249,13 @@
      * @param contentTree the content tree to which the class use information will be added
      */
     protected void addClassUse(Content contentTree) {
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setStyle(HtmlStyle.blockList);
+        Content content = new ContentBuilder();
         if (configuration.packages.size() > 1) {
-            addPackageList(ul);
-            addPackageAnnotationList(ul);
+            addPackageList(content);
+            addPackageAnnotationList(content);
         }
-        addClassList(ul);
-        contentTree.add(ul);
+        addClassList(content);
+        contentTree.add(content);
     }
 
     /**
@@ -276,8 +275,7 @@
         for (PackageElement pkg : pkgSet) {
             addPackageUse(pkg, table);
         }
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
-        contentTree.add(li);
+        contentTree.add(table.toContent());
     }
 
     /**
@@ -305,8 +303,7 @@
             addSummaryComment(pkg, summary);
             table.addRow(getPackageLink(pkg), summary);
         }
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
-        contentTree.add(li);
+        contentTree.add(table.toContent());
     }
 
     /**
@@ -319,7 +316,7 @@
         ul.setStyle(HtmlStyle.blockList);
         for (PackageElement pkg : pkgSet) {
             Content markerAnchor = links.createAnchor(getPackageAnchorName(pkg));
-            HtmlTree htmlTree = HtmlTree.SECTION(markerAnchor);
+            HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.detail, markerAnchor);
             Content link = contents.getContent("doclet.ClassUse_Uses.of.0.in.1",
                     getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER,
                             typeElement)),
@@ -329,7 +326,7 @@
             addClassUse(pkg, htmlTree);
             ul.add(HtmlTree.LI(HtmlStyle.blockList, htmlTree));
         }
-        Content li = HtmlTree.LI(HtmlStyle.blockList, ul);
+        Content li = HtmlTree.SECTION(HtmlStyle.classUses, ul);
         contentTree.add(li);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,11 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
@@ -36,6 +40,9 @@
 import javax.lang.model.util.SimpleElementVisitor8;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -122,7 +129,7 @@
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
-            moduleNameDiv.add(Contents.SPACE);
+            moduleNameDiv.add(Entity.NO_BREAK_SPACE);
             moduleNameDiv.add(getModuleLink(mdle,
                     new StringContent(mdle.getQualifiedName())));
             div.add(moduleNameDiv);
@@ -131,7 +138,7 @@
         if (!pkg.isUnnamed()) {
             Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInType, contents.packageLabel);
             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
-            pkgNameDiv.add(Contents.SPACE);
+            pkgNameDiv.add(Entity.NO_BREAK_SPACE);
             Content pkgNameContent = getPackageLink(pkg,
                     new StringContent(utils.getPackageName(pkg)));
             pkgNameDiv.add(pkgNameContent);
@@ -290,26 +297,17 @@
      */
     private Content getClassInheritenceTree(TypeMirror type) {
         TypeMirror sup;
-        HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL);
-        classTreeUl.setStyle(HtmlStyle.inheritance);
-        Content liTree = null;
+        HtmlTree classTree = null;
         do {
             sup = utils.getFirstVisibleSuperClass(type);
-            if (sup != null) {
-                HtmlTree ul = new HtmlTree(HtmlTag.UL);
-                ul.setStyle(HtmlStyle.inheritance);
-                ul.add(getTreeForClassHelper(type));
-                if (liTree != null)
-                    ul.add(liTree);
-                Content li = HtmlTree.LI(ul);
-                liTree = li;
-                type = sup;
-            } else
-                classTreeUl.add(getTreeForClassHelper(type));
+            HtmlTree htmlElement = HtmlTree.DIV(HtmlStyle.inheritance, getTreeForClassHelper(type));
+            if (classTree != null)
+                htmlElement.add(classTree);
+            classTree = htmlElement;
+            type = sup;
         } while (sup != null);
-        if (liTree != null)
-            classTreeUl.add(liTree);
-        return classTreeUl;
+        classTree.put(HtmlAttr.TITLE, contents.getContent("doclet.Inheritance_Tree").toString());
+        return classTree;
     }
 
     /**
@@ -319,25 +317,25 @@
      * @return a content tree for class helper
      */
     private Content getTreeForClassHelper(TypeMirror type) {
-        Content li = new HtmlTree(HtmlTag.LI);
+        Content content = new ContentBuilder();
         if (type.equals(typeElement.asType())) {
             Content typeParameters = getTypeParameterLinks(
                     new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE,
                     typeElement));
             if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) {
-                li.add(utils.asTypeElement(type).getSimpleName());
-                li.add(typeParameters);
+                content.add(utils.asTypeElement(type).getSimpleName());
+                content.add(typeParameters);
             } else {
-                li.add(utils.asTypeElement(type).getQualifiedName());
-                li.add(typeParameters);
+                content.add(utils.asTypeElement(type).getQualifiedName());
+                content.add(typeParameters);
             }
         } else {
             Content link = getLink(new LinkInfoImpl(configuration,
                     LinkInfoImpl.Kind.CLASS_TREE_PARENT, type)
                     .label(configuration.getClassName(utils.asTypeElement(type))));
-            li.add(link);
+            content.add(link);
         }
-        return li;
+        return content;
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,10 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.Collection;
+import java.util.Set;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.PackageElement;
@@ -36,12 +34,15 @@
 import javax.lang.model.element.VariableElement;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -157,7 +158,7 @@
         Content headingContent = contents.contentsHeading;
         Content heading = HtmlTree.HEADING(Headings.CONTENT_HEADING, true,
                 headingContent);
-        HtmlTree section = HtmlTree.SECTION(heading);
+        HtmlTree section = HtmlTree.SECTION(HtmlStyle.packages, heading);
         section.add(contentListTree);
         div.add(section);
         mainTree.add(div);
@@ -194,7 +195,7 @@
         Content heading = HtmlTree.HEADING(Headings.ConstantsSummary.PACKAGE_HEADING, true,
                 pkgNameContent);
         heading.add(headingContent);
-        summaryTree = HtmlTree.SECTION(heading);
+        summaryTree = HtmlTree.SECTION(HtmlStyle.constantsSummary, heading);
     }
 
     /**
@@ -265,7 +266,7 @@
         for (Modifier mod : member.getModifiers()) {
             Content modifier = new StringContent(mod.toString());
             code.add(modifier);
-            code.add(Contents.SPACE);
+            code.add(Entity.NO_BREAK_SPACE);
         }
         Content type = getLink(new LinkInfoImpl(configuration,
                 LinkInfoImpl.Kind.CONSTANT_SUMMARY, member.asType()));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,25 +25,27 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
-import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.CONSTRUCTORS;
 
 
 /**
@@ -98,7 +100,7 @@
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_CONSTRUCTOR_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -108,7 +110,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.constructorSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -118,12 +120,12 @@
     public Content getConstructorDetailsTreeHeader(TypeElement typeElement,
             Content memberDetailsTree) {
         memberDetailsTree.add(MarkerComments.START_OF_CONSTRUCTOR_DETAILS);
-        Content constructorDetailsTree = writer.getMemberTreeHeader();
-        constructorDetailsTree.add(links.createAnchor(
-                SectionName.CONSTRUCTOR_DETAIL));
+        Content constructorDetailsTree = new ContentBuilder();
         Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                 contents.constructorDetailsLabel);
         constructorDetailsTree.add(heading);
+        constructorDetailsTree.add(links.createAnchor(
+                SectionName.CONSTRUCTOR_DETAIL));
         return constructorDetailsTree;
     }
 
@@ -134,15 +136,15 @@
     public Content getConstructorDocTreeHeader(ExecutableElement constructor,
             Content constructorDetailsTree) {
         String erasureAnchor;
-        if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
-            constructorDetailsTree.add(links.createAnchor((erasureAnchor)));
-        }
-        constructorDetailsTree.add(links.createAnchor(writer.getAnchor(constructor)));
-        Content constructorDocTree = writer.getMemberTreeHeader();
+        Content constructorDocTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(name(constructor));
         constructorDocTree.add(heading);
-        return constructorDocTree;
+        if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
+            constructorDocTree.add(links.createAnchor((erasureAnchor)));
+        }
+        constructorDocTree.add(links.createAnchor(writer.getAnchor(constructor)));
+        return HtmlTree.SECTION(HtmlStyle.detail, constructorDocTree);
     }
 
     /**
@@ -194,8 +196,9 @@
      * {@inheritDoc}
      */
     @Override
-    public Content getConstructorDetails(Content constructorDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(constructorDetailsTree));
+    public Content getConstructorDetails(Content constructorDetailsTreeHeader, Content constructorDetailsTree) {
+        Content constructorDetails = new ContentBuilder(constructorDetailsTreeHeader, constructorDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.constructorDetails, constructorDetails));
     }
 
     /**
@@ -295,7 +298,7 @@
             } else if (utils.isPrivate(member)) {
                 code.add("private ");
             } else if (utils.isPublic(member)) {
-                code.add(Contents.SPACE);
+                code.add(Entity.NO_BREAK_SPACE);
             } else {
                 code.add(
                         resources.getText("doclet.Package_private"));
@@ -303,4 +306,9 @@
             tdSummaryType.add(code);
         }
     }
+
+    @Override
+    public Content getMemberTreeHeader(){
+        return writer.getMemberTreeHeader();
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Fri May 03 14:59:32 2019 -0400
@@ -32,8 +32,8 @@
 
 import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.FixedStringContent;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
@@ -52,8 +52,6 @@
  * only created once per doclet-instance, instead of once per generated page.
  */
 public class Contents {
-    public static final Content SPACE = RawHtml.nbsp;
-    public static final Content ZERO_WIDTH_SPACE = RawHtml.zws;
 
     public final Content allClassesLabel;
     public final Content allImplementedInterfacesLabel;
@@ -400,7 +398,7 @@
         int p;
         while ((p = text.indexOf(" ", start)) != -1) {
             c.add(text.substring(start, p));
-            c.add(RawHtml.nbsp);
+            c.add(Entity.NO_BREAK_SPACE);
             start = p + 1;
         }
         c.add(text.substring(start));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -26,17 +26,17 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -70,7 +70,7 @@
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_ENUM_CONSTANT_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -80,7 +80,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.constantsSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -90,12 +90,12 @@
     public Content getEnumConstantsDetailsTreeHeader(TypeElement typeElement,
             Content memberDetailsTree) {
         memberDetailsTree.add(MarkerComments.START_OF_ENUM_CONSTANT_DETAILS);
-        Content enumConstantsDetailsTree = writer.getMemberTreeHeader();
-        enumConstantsDetailsTree.add(links.createAnchor(
-                SectionName.ENUM_CONSTANT_DETAIL));
+        Content enumConstantsDetailsTree = new ContentBuilder();
         Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                 contents.enumConstantDetailLabel);
         enumConstantsDetailsTree.add(heading);
+        enumConstantsDetailsTree.add(links.createAnchor(
+                SectionName.ENUM_CONSTANT_DETAIL));
         return enumConstantsDetailsTree;
     }
 
@@ -105,12 +105,12 @@
     @Override
     public Content getEnumConstantsTreeHeader(VariableElement enumConstant,
             Content enumConstantsDetailsTree) {
-        enumConstantsDetailsTree.add(links.createAnchor(name(enumConstant)));
-        Content enumConstantsTree = writer.getMemberTreeHeader();
+        Content enumConstantsTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(name(enumConstant));
         enumConstantsTree.add(heading);
-        return enumConstantsTree;
+        enumConstantsTree.add(links.createAnchor(name(enumConstant)));
+        return HtmlTree.SECTION(HtmlStyle.detail, enumConstantsTree);
     }
 
     /**
@@ -162,8 +162,11 @@
      * {@inheritDoc}
      */
     @Override
-    public Content getEnumConstantsDetails(Content enumConstantsDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(enumConstantsDetailsTree));
+    public Content getEnumConstantsDetails(Content enumConstantsDetailsTreeHeader,
+            Content enumConstantsDetailsTree) {
+        Content enumConstantsDetails =
+                new ContentBuilder(enumConstantsDetailsTreeHeader, enumConstantsDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.constantDetails, enumConstantsDetails));
     }
 
     /**
@@ -261,4 +264,9 @@
         String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName();
         return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name);
     }
+
+    @Override
+    public Content getMemberTreeHeader(){
+        return writer.getMemberTreeHeader();
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,9 +25,6 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import java.util.Arrays;
 import java.util.List;
 
@@ -35,10 +32,14 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.FieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -74,7 +75,7 @@
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_FIELD_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -84,7 +85,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.fieldSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -93,12 +94,12 @@
     @Override
     public Content getFieldDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) {
         memberDetailsTree.add(MarkerComments.START_OF_FIELD_DETAILS);
-        Content fieldDetailsTree = writer.getMemberTreeHeader();
-        fieldDetailsTree.add(links.createAnchor(
-                SectionName.FIELD_DETAIL));
+        Content fieldDetailsTree = new ContentBuilder();
         Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                 contents.fieldDetailsLabel);
         fieldDetailsTree.add(heading);
+        fieldDetailsTree.add(links.createAnchor(
+                SectionName.FIELD_DETAIL));
         return fieldDetailsTree;
     }
 
@@ -107,12 +108,12 @@
      */
     @Override
     public Content getFieldDocTreeHeader(VariableElement field, Content fieldDetailsTree) {
-        fieldDetailsTree.add(links.createAnchor(name(field)));
-        Content fieldTree = writer.getMemberTreeHeader();
+        Content fieldTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(name(field));
         fieldTree.add(heading);
-        return fieldTree;
+        fieldTree.add(links.createAnchor(name(field)));
+        return HtmlTree.SECTION(HtmlStyle.detail, fieldTree);
     }
 
     /**
@@ -166,8 +167,9 @@
      * {@inheritDoc}
      */
     @Override
-    public Content getFieldDetails(Content fieldDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(fieldDetailsTree));
+    public Content getFieldDetails(Content fieldDetailsTreeHeader, Content fieldDetailsTree) {
+        Content fieldDetails = new ContentBuilder(fieldDetailsTreeHeader, fieldDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.fieldDetails, fieldDetails));
     }
 
     /**
@@ -247,7 +249,7 @@
         }
         Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING,
                 label);
-        labelHeading.add(Contents.SPACE);
+        labelHeading.add(Entity.NO_BREAK_SPACE);
         labelHeading.add(classLink);
         inheritedTree.add(labelHeading);
     }
@@ -290,4 +292,9 @@
         String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName();
         return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name);
     }
+
+    @Override
+    public Content getMemberTreeHeader(){
+        return writer.getMemberTreeHeader();
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -127,7 +127,7 @@
         if (configuration.createoverview) {
             Content overviewHeading = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.overviewLabel);
-            htmlTree = HtmlTree.SECTION(overviewHeading);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, overviewHeading);
             String overviewKey = configuration.showModules
                     ? "doclet.help.overview.modules.body"
                     : "doclet.help.overview.packages.body";
@@ -143,7 +143,7 @@
         if (configuration.showModules) {
             Content moduleHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                     contents.moduleLabel);
-            htmlTree = HtmlTree.SECTION(moduleHead);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, moduleHead);
             Content moduleIntro = contents.getContent("doclet.help.module.intro");
             Content modulePara = HtmlTree.P(moduleIntro);
             htmlTree.add(modulePara);
@@ -158,7 +158,7 @@
         // Package
         Content packageHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.packageLabel);
-        htmlTree = HtmlTree.SECTION(packageHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, packageHead);
         Content packageIntro = contents.getContent("doclet.help.package.intro");
         Content packagePara = HtmlTree.P(packageIntro);
         htmlTree.add(packagePara);
@@ -175,7 +175,7 @@
         // Class/interface
         Content classHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.getContent("doclet.help.class_interface.head"));
-        htmlTree = HtmlTree.SECTION(classHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, classHead);
         Content classIntro = contents.getContent("doclet.help.class_interface.intro");
         Content classPara = HtmlTree.P(classIntro);
         htmlTree.add(classPara);
@@ -210,7 +210,7 @@
         // Annotation Types
         Content aHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.annotationType);
-        htmlTree = HtmlTree.SECTION(aHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, aHead);
         Content aIntro = contents.getContent("doclet.help.annotation_type.intro");
         Content aPara = HtmlTree.P(aIntro);
         htmlTree.add(aPara);
@@ -225,7 +225,7 @@
 
         // Enums
         Content enumHead = HtmlTree.HEADING(Headings.CONTENT_HEADING, contents.enum_);
-        htmlTree = HtmlTree.SECTION(enumHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, enumHead);
         Content eIntro = contents.getContent("doclet.help.enum.intro");
         Content enumPara = HtmlTree.P(eIntro);
         htmlTree.add(enumPara);
@@ -241,7 +241,7 @@
         if (configuration.classuse) {
             Content useHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                     contents.getContent("doclet.help.use.head"));
-            htmlTree = HtmlTree.SECTION(useHead);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, useHead);
             Content useBody = contents.getContent("doclet.help.use.body");
             Content usePara = HtmlTree.P(useBody);
             htmlTree.add(usePara);
@@ -252,7 +252,7 @@
         if (configuration.createtree) {
             Content treeHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                     contents.getContent("doclet.help.tree.head"));
-            htmlTree = HtmlTree.SECTION(treeHead);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, treeHead);
             Content treeIntro = contents.getContent("doclet.help.tree.intro",
                     links.createLink(DocPaths.OVERVIEW_TREE,
                     resources.getText("doclet.Class_Hierarchy")),
@@ -270,7 +270,7 @@
         if (!(configuration.nodeprecatedlist || configuration.nodeprecated)) {
             Content dHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                     contents.deprecatedAPI);
-            htmlTree = HtmlTree.SECTION(dHead);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, dHead);
             Content deprBody = contents.getContent("doclet.help.deprecated.body",
                     links.createLink(DocPaths.DEPRECATED_LIST,
                     resources.getText("doclet.Deprecated_API")));
@@ -291,7 +291,7 @@
             }
             Content indexHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                     contents.getContent("doclet.help.index.head"));
-            htmlTree = HtmlTree.SECTION(indexHead);
+            htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, indexHead);
             Content indexBody = contents.getContent("doclet.help.index.body", indexlink);
             Content indexPara = HtmlTree.P(indexBody);
             htmlTree.add(indexPara);
@@ -301,7 +301,7 @@
         // Serialized Form
         Content sHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.serializedForm);
-        htmlTree = HtmlTree.SECTION(sHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, sHead);
         Content serialBody = contents.getContent("doclet.help.serial_form.body");
         Content serialPara = HtmlTree.P(serialBody);
         htmlTree.add(serialPara);
@@ -310,7 +310,7 @@
         // Constant Field Values
         Content constHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.constantsSummaryTitle);
-        htmlTree = HtmlTree.SECTION(constHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, constHead);
         Content constantsBody = contents.getContent("doclet.help.constants.body",
                 links.createLink(DocPaths.CONSTANT_VALUES,
                 resources.getText("doclet.Constants_Summary")));
@@ -321,7 +321,7 @@
         // Search
         Content searchHead = HtmlTree.HEADING(Headings.CONTENT_HEADING,
                 contents.getContent("doclet.help.search.head"));
-        htmlTree = HtmlTree.SECTION(searchHead);
+        htmlTree = HtmlTree.SECTION(HtmlStyle.helpSection, searchHead);
         Content searchBody = contents.getContent("doclet.help.search.body");
         Content searchPara = HtmlTree.P(searchBody);
         htmlTree.add(searchPara);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Fri May 03 14:59:32 2019 -0400
@@ -347,7 +347,7 @@
                 }
             }
         }
-        docPaths = new DocPaths(utils, useModuleDirectories);
+        docPaths = new DocPaths(utils);
         setCreateOverview();
         setTopFile(docEnv);
         workArounds.initDocLint(doclintOpts.values(), tagletManager.getAllTagletNames());
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -25,11 +25,13 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Head;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -69,8 +71,10 @@
 import com.sun.source.doctree.SystemPropertyTree;
 import com.sun.source.doctree.TextTree;
 import com.sun.source.util.SimpleDocTreeVisitor;
-
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
+import jdk.javadoc.internal.doclets.formats.html.markup.Head;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -79,6 +83,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -97,7 +102,12 @@
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
-import static com.sun.source.doctree.DocTree.Kind.*;
+import static com.sun.source.doctree.DocTree.Kind.CODE;
+import static com.sun.source.doctree.DocTree.Kind.COMMENT;
+import static com.sun.source.doctree.DocTree.Kind.LINK;
+import static com.sun.source.doctree.DocTree.Kind.LINK_PLAIN;
+import static com.sun.source.doctree.DocTree.Kind.SEE;
+import static com.sun.source.doctree.DocTree.Kind.TEXT;
 import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER;
 
 
@@ -417,7 +427,6 @@
                 .setCharset(configuration.charset)
                 .addKeywords(metakeywords)
                 .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
-                .setUseModuleDirectories(configuration.useModuleDirectories)
                 .setIndex(configuration.createindex, mainBodyScript)
                 .addContent(extraHeadContent);
 
@@ -503,7 +512,7 @@
      */
     public Content getTableCaption(Content title) {
         Content captionSpan = HtmlTree.SPAN(title);
-        Content space = Contents.SPACE;
+        Content space = Entity.NO_BREAK_SPACE;
         Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
         Content caption = HtmlTree.CAPTION(captionSpan);
         caption.add(tabSpan);
@@ -1227,7 +1236,7 @@
             htmltree.add(div);
         }
         if (tags.isEmpty()) {
-            htmltree.add(Contents.SPACE);
+            htmltree.add(Entity.NO_BREAK_SPACE);
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -103,15 +103,14 @@
      * @return a content tree for the serializable fields content
      */
     public Content getSerializableFields(String heading, Content serializableFieldsTree) {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.setStyle(HtmlStyle.blockList);
+        HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail);
         if (serializableFieldsTree.isValid()) {
             Content headingContent = new StringContent(heading);
             Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent);
-            li.add(serialHeading);
-            li.add(serializableFieldsTree);
+            section.add(serialHeading);
+            section.add(serializableFieldsTree);
         }
-        return li;
+        return HtmlTree.LI(HtmlStyle.blockList, section);
     }
 
     @Override
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -95,9 +95,9 @@
     public Content getSerializableMethods(String heading, Content serializableMethodContent) {
         Content headingContent = new StringContent(heading);
         Content serialHeading = HtmlTree.HEADING(Headings.SerializedForm.CLASS_SUBHEADING, headingContent);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, serialHeading);
-        li.add(serializableMethodContent);
-        return li;
+        Content section = HtmlTree.SECTION(HtmlStyle.detail, serialHeading);
+        section.add(serializableMethodContent);
+        return HtmlTree.LI(HtmlStyle.blockList, section);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -35,6 +35,7 @@
 import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
@@ -162,7 +163,7 @@
             for (TypeMirror t : vars) {
                 if (many) {
                     links.add(",");
-                    links.add(Contents.ZERO_WIDTH_SPACE);
+                    links.add(Entity.ZERO_WIDTH_SPACE);
                 }
                 links.add(getTypeParameterLink(linkInfo, t));
                 many = true;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,9 +25,6 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -36,10 +33,14 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
@@ -87,7 +88,7 @@
     @Override
     public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_METHOD_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -97,7 +98,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.methodSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -106,11 +107,11 @@
     @Override
     public Content getMethodDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) {
         memberDetailsTree.add(MarkerComments.START_OF_METHOD_DETAILS);
-        Content methodDetailsTree = writer.getMemberTreeHeader();
-        methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL));
+        Content methodDetailsTree = new ContentBuilder();
         Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                 contents.methodDetailLabel);
         methodDetailsTree.add(heading);
+        methodDetailsTree.add(links.createAnchor(SectionName.METHOD_DETAIL));
         return methodDetailsTree;
     }
 
@@ -120,15 +121,15 @@
     @Override
     public Content getMethodDocTreeHeader(ExecutableElement method, Content methodDetailsTree) {
         String erasureAnchor;
-        if ((erasureAnchor = getErasureAnchor(method)) != null) {
-            methodDetailsTree.add(links.createAnchor((erasureAnchor)));
-        }
-        methodDetailsTree.add(links.createAnchor(writer.getAnchor(method)));
-        Content methodDocTree = writer.getMemberTreeHeader();
+        Content methodDocTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(name(method));
         methodDocTree.add(heading);
-        return methodDocTree;
+        if ((erasureAnchor = getErasureAnchor(method)) != null) {
+            methodDocTree.add(links.createAnchor((erasureAnchor)));
+        }
+        methodDocTree.add(links.createAnchor(writer.getAnchor(method)));
+        return HtmlTree.SECTION(HtmlStyle.detail, methodDocTree);
     }
 
     /**
@@ -190,7 +191,7 @@
                         utils.isClass(holder)
                                 ? contents.descfrmClassLabel
                                 : contents.descfrmInterfaceLabel);
-                descfrmLabel.add(Contents.SPACE);
+                descfrmLabel.add(Entity.NO_BREAK_SPACE);
                 descfrmLabel.add(codelLink);
                 methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
                 writer.addInlineComment(method, methodDocTree);
@@ -210,8 +211,9 @@
      * {@inheritDoc}
      */
     @Override
-    public Content getMethodDetails(Content methodDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(methodDetailsTree));
+    public Content getMethodDetails(Content methodDetailsTreeHeader, Content methodDetailsTree) {
+        Content methodDetails = new ContentBuilder(methodDetailsTreeHeader, methodDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.methodDetails, methodDetails));
     }
 
     /**
@@ -296,7 +298,7 @@
         }
         Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING,
                 label);
-        labelHeading.add(Contents.SPACE);
+        labelHeading.add(Entity.NO_BREAK_SPACE);
         labelHeading.add(classLink);
         inheritedTree.add(labelHeading);
     }
@@ -352,9 +354,9 @@
                     .where(writer.links.getName(writer.getAnchor(method))).label(method.getSimpleName()));
             Content codeMethLink = HtmlTree.CODE(methlink);
             Content dd = HtmlTree.DD(codeMethLink);
-            dd.add(Contents.SPACE);
+            dd.add(Entity.NO_BREAK_SPACE);
             dd.add(writer.contents.inClass);
-            dd.add(Contents.SPACE);
+            dd.add(Entity.NO_BREAK_SPACE);
             dd.add(codeOverridenTypeLink);
             dl.add(dd);
         }
@@ -388,9 +390,9 @@
                     implementedMeth.getSimpleName(), false);
             Content codeMethLink = HtmlTree.CODE(methlink);
             Content dd = HtmlTree.DD(codeMethLink);
-            dd.add(Contents.SPACE);
+            dd.add(Entity.NO_BREAK_SPACE);
             dd.add(contents.inInterface);
-            dd.add(Contents.SPACE);
+            dd.add(Entity.NO_BREAK_SPACE);
             dd.add(codeIntfacLink);
             dl.add(dd);
         }
@@ -408,7 +410,12 @@
             Content linkContent = writer.getLink(
                     new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RETURN_TYPE, type));
             htmltree.add(linkContent);
-            htmltree.add(Contents.SPACE);
+            htmltree.add(Entity.NO_BREAK_SPACE);
         }
     }
+
+    @Override
+    public Content getMemberTreeHeader(){
+        return writer.getMemberTreeHeader();
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,9 +25,6 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -46,6 +43,7 @@
 import com.sun.source.doctree.DocTree;
 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -53,6 +51,8 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
@@ -166,11 +166,6 @@
      */
     protected HtmlTree mainTree = HtmlTree.MAIN();
 
-    /**
-     * The HTML tree for section tag.
-     */
-    protected HtmlTree sectionTree = HtmlTree.SECTION();
-
     private final Navigation navBar;
 
     /**
@@ -214,7 +209,7 @@
                 ? contents.openModuleLabel : contents.moduleLabel;
         Content tHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
                 HtmlStyle.title, label);
-        tHeading.add(Contents.SPACE);
+        tHeading.add(Entity.NO_BREAK_SPACE);
         Content moduleHead = new RawHtml(heading);
         tHeading.add(moduleHead);
         div.add(tHeading);
@@ -237,9 +232,9 @@
      */
     @Override
     public Content getSummaryHeader() {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.setStyle(HtmlStyle.blockList);
-        return li;
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setStyle(HtmlStyle.blockList);
+        return ul;
     }
 
     /**
@@ -249,8 +244,7 @@
      */
     @Override
     public Content getSummaryTree(Content summaryContentTree) {
-        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
-        return ul;
+        return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree);
     }
 
     /**
@@ -506,10 +500,9 @@
             TableHeader requiresTableHeader =
                     new TableHeader(contents.modifierLabel, contents.moduleLabel,
                             contents.descriptionLabel);
-            HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.setStyle(HtmlStyle.blockList);
+            HtmlTree section = HtmlTree.SECTION(HtmlStyle.modulesSummary);
             addSummaryHeader(MarkerComments.START_OF_MODULES_SUMMARY, SectionName.MODULES,
-                    contents.navModules, li);
+                    contents.navModules, section);
             if (display(requires)) {
                 String text = resources.getText("doclet.Requires_Summary");
                 String tableSummary = resources.getText("doclet.Member_Table_Summary",
@@ -519,7 +512,7 @@
                 Table table = getTable3(caption, tableSummary, HtmlStyle.requiresSummary,
                             requiresTableHeader);
                 addModulesList(requires, table);
-                li.add(table.toContent());
+                section.add(table.toContent());
             }
             // Display indirect modules table in both "api" and "all" mode.
             if (display(indirectModules)) {
@@ -531,10 +524,9 @@
                 Table amrTable = getTable3(amrCaption, amrTableSummary, HtmlStyle.requiresSummary,
                             requiresTableHeader);
                 addModulesList(indirectModules, amrTable);
-                li.add(amrTable.toContent());
+                section.add(amrTable.toContent());
             }
-            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
-            summaryContentTree.add(ul);
+            summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section));
         }
     }
 
@@ -542,7 +534,7 @@
      * Add the list of modules.
      *
      * @param mdleMap map of modules and modifiers
-     * @param tbody the content tree to which the list will be added
+     * @param table the table to which the list will be added
      */
     private void addModulesList(Map<ModuleElement, Content> mdleMap, Table table) {
         for (ModuleElement m : mdleMap.keySet()) {
@@ -558,12 +550,11 @@
     public void addPackagesSummary(Content summaryContentTree) {
         if (display(packages)
                 || display(indirectPackages) || display(indirectOpenPackages)) {
-            HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.setStyle(HtmlStyle.blockList);
+            HtmlTree section = HtmlTree.SECTION(HtmlStyle.packagesSummary);
             addSummaryHeader(MarkerComments.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES,
-                    contents.navPackages, li);
+                    contents.navPackages, section);
             if (display(packages)) {
-                addPackageSummary(li);
+                addPackageSummary(section);
             }
             TableHeader indirectPackagesHeader =
                     new TableHeader(contents.fromLabel, contents.packagesLabel);
@@ -572,17 +563,16 @@
                 Table aepTable = getTable2(new StringContent(aepText),
                         HtmlStyle.packagesSummary, indirectPackagesHeader);
                 addIndirectPackages(aepTable, indirectPackages);
-                li.add(aepTable.toContent());
+                section.add(aepTable.toContent());
             }
             if (display(indirectOpenPackages)) {
                 String aopText = resources.getText("doclet.Indirect_Opens_Summary");
                 Table aopTable = getTable2(new StringContent(aopText), HtmlStyle.packagesSummary,
                         indirectPackagesHeader);
                 addIndirectPackages(aopTable, indirectOpenPackages);
-                li.add(aopTable.toContent());
+                section.add(aopTable.toContent());
             }
-            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
-            summaryContentTree.add(ul);
+            summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section));
         }
     }
 
@@ -737,10 +727,9 @@
         boolean haveProvides = displayServices(provides.keySet(), providesTrees);
 
         if (haveProvides || haveUses) {
-            HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.setStyle(HtmlStyle.blockList);
+            HtmlTree section = HtmlTree.SECTION(HtmlStyle.servicesSummary);
             addSummaryHeader(MarkerComments.START_OF_SERVICES_SUMMARY, SectionName.SERVICES,
-                    contents.navServices, li);
+                    contents.navServices, section);
             TableHeader usesProvidesTableHeader =
                     new TableHeader(contents.typeLabel, contents.descriptionLabel);
             if (haveProvides) {
@@ -749,7 +738,7 @@
                         usesProvidesTableHeader);
                 addProvidesList(table);
                 if (!table.isEmpty()) {
-                    li.add(table.toContent());
+                    section.add(table.toContent());
                 }
             }
             if (haveUses){
@@ -758,11 +747,10 @@
                         usesProvidesTableHeader);
                 addUsesList(table);
                 if (!table.isEmpty()) {
-                    li.add(table.toContent());
+                    section.add(table.toContent());
                 }
             }
-            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
-            summaryContentTree.add(ul);
+            summaryContentTree.add(HtmlTree.LI(HtmlStyle.blockList, section));
         }
     }
 
@@ -788,7 +776,7 @@
                     addSummaryComment(t, summary);
                 }
             } else {
-                summary.add(Contents.SPACE);
+                summary.add(Entity.NO_BREAK_SPACE);
             }
             table.addRow(typeLinkContent, summary);
         }
@@ -814,9 +802,9 @@
                 description = providesTrees.get(srv);
                 desc.add((description != null && !description.isEmpty())
                         ? HtmlTree.DIV(HtmlStyle.block, description)
-                        : Contents.SPACE);
+                        : Entity.NO_BREAK_SPACE);
             } else {
-                desc.add(Contents.SPACE);
+                desc.add(Entity.NO_BREAK_SPACE);
                 }
             // Only display the implementation details in the "all" mode.
             if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) {
@@ -824,7 +812,7 @@
                 desc.add("(");
                 HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
                 desc.add(implSpan);
-                desc.add(Contents.SPACE);
+                desc.add(Entity.NO_BREAK_SPACE);
                 String sep = "";
                 for (TypeElement impl : implSet) {
                     desc.add(sep);
@@ -866,7 +854,7 @@
     @Override
     public void addModuleDescription(Content moduleContentTree) {
         if (!utils.getFullBody(mdle).isEmpty()) {
-            Content tree = HtmlTree.SECTION();
+            Content tree = HtmlTree.SECTION(HtmlStyle.moduleDescription);
             addDeprecationInfo(tree);
             tree.add(MarkerComments.START_OF_MODULE_DESCRIPTION);
             tree.add(links.createAnchor(SectionName.MODULE_DESCRIPTION));
@@ -880,7 +868,7 @@
      */
     @Override
     public void addModuleTags(Content moduleContentTree) {
-        Content tree = HtmlTree.SECTION();
+        Content tree = HtmlTree.SECTION(HtmlStyle.moduleTags);
         addTagsInfo(mdle, tree);
         moduleContentTree.add(tree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,18 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import java.util.Arrays;
 import java.util.List;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 
@@ -71,7 +72,7 @@
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_NESTED_CLASS_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -81,7 +82,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.nestedClassSummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -154,7 +155,7 @@
                     : resources.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class"));
         }
         Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING, label);
-        labelHeading.add(Contents.SPACE);
+        labelHeading.add(Entity.NO_BREAK_SPACE);
         labelHeading.add(classLink);
         inheritedTree.add(labelHeading);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -25,21 +25,24 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -151,13 +154,12 @@
      * @param contentTree the content tree to which the package use information will be added
      */
     protected void addPackageUse(Content contentTree) {
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setStyle(HtmlStyle.blockList);
+        Content content = new ContentBuilder();
         if (configuration.packages.size() > 1) {
-            addPackageList(ul);
+            addPackageList(content);
         }
-        addClassList(ul);
-        contentTree.add(ul);
+        addClassList(content);
+        contentTree.add(content);
     }
 
     /**
@@ -181,12 +183,11 @@
             if (pkg != null && !pkg.isUnnamed()) {
                 addSummaryComment(pkg, summary);
             } else {
-                summary.add(Contents.SPACE);
+                summary.add(Entity.NO_BREAK_SPACE);
             }
             table.addRow(packageLink, summary);
         }
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
-        contentTree.add(li);
+        contentTree.add(table.toContent());
     }
 
     /**
@@ -197,11 +198,12 @@
     protected void addClassList(Content contentTree) {
         TableHeader classTableHeader = new TableHeader(
                 contents.classLabel, contents.descriptionLabel);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setStyle(HtmlStyle.blockList);
         for (String packageName : usingPackageToUsedClasses.keySet()) {
             PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName);
-            HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.setStyle(HtmlStyle.blockList);
-            li.add(links.createAnchor(getPackageAnchorName(usingPackage)));
+            HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail);
+            section.add(links.createAnchor(getPackageAnchorName(usingPackage)));
             String tableSummary = resources.getText("doclet.Use_Table_Summary",
                                                         resources.getText("doclet.classes"));
             Content caption = contents.getContent(
@@ -223,9 +225,11 @@
 
                 table.addRow(typeContent, summary);
             }
-            li.add(table.toContent());
-            contentTree.add(li);
+            section.add(table.toContent());
+            ul.add(HtmlTree.LI(HtmlStyle.blockList, section));
         }
+        Content li = HtmlTree.SECTION(HtmlStyle.packageUses, ul);
+        contentTree.add(li);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,10 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
-import java.util.*;
+import java.util.List;
+import java.util.SortedSet;
 
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
@@ -36,12 +34,15 @@
 
 import com.sun.source.doctree.DocTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
@@ -77,7 +78,7 @@
     /**
      * The HTML tree for section tag.
      */
-    protected HtmlTree sectionTree = HtmlTree.SECTION();
+    protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder());
 
     private final Navigation navBar;
 
@@ -120,7 +121,7 @@
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
-            moduleNameDiv.add(Contents.SPACE);
+            moduleNameDiv.add(Entity.NO_BREAK_SPACE);
             moduleNameDiv.add(getModuleLink(mdle,
                     new StringContent(mdle.getQualifiedName().toString())));
             div.add(moduleNameDiv);
@@ -130,7 +131,7 @@
         div.add(annotationContent);
         Content tHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
                 HtmlStyle.title, contents.packageLabel);
-        tHeading.add(Contents.SPACE);
+        tHeading.add(Entity.NO_BREAK_SPACE);
         Content packageHead = new StringContent(heading);
         tHeading.add(packageHead);
         div.add(tHeading);
@@ -320,4 +321,12 @@
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
                 description, stylesheetContent, contentTree);
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Content getPackageSummary(Content summaryContentTree) {
+        return HtmlTree.SECTION(HtmlStyle.summary, summaryContentTree);
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,23 +25,22 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-
-import jdk.javadoc.internal.doclets.formats.html.markup.Table;
-import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
-
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
 
-
 /**
  * Writes property documentation in HTML format.
  *
@@ -68,7 +67,7 @@
     @Override
     public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) {
         memberSummaryTree.add(MarkerComments.START_OF_PROPERTY_SUMMARY);
-        Content memberTree = writer.getMemberTreeHeader();
+        Content memberTree = new ContentBuilder();
         writer.addSummaryHeader(this, typeElement, memberTree);
         return memberTree;
     }
@@ -78,7 +77,7 @@
      */
     @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        writer.addMemberTree(memberSummaryTree, memberTree);
+        writer.addMemberTree(HtmlStyle.propertySummary, memberSummaryTree, memberTree);
     }
 
     /**
@@ -88,11 +87,11 @@
     public Content getPropertyDetailsTreeHeader(TypeElement typeElement,
             Content memberDetailsTree) {
         memberDetailsTree.add(MarkerComments.START_OF_PROPERTY_DETAILS);
-        Content propertyDetailsTree = writer.getMemberTreeHeader();
-        propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL));
+        Content propertyDetailsTree = new ContentBuilder();
         Content heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
                 contents.propertyDetailsLabel);
         propertyDetailsTree.add(heading);
+        propertyDetailsTree.add(links.createAnchor(SectionName.PROPERTY_DETAIL));
         return propertyDetailsTree;
     }
 
@@ -102,12 +101,12 @@
     @Override
     public Content getPropertyDocTreeHeader(ExecutableElement property,
             Content propertyDetailsTree) {
-        propertyDetailsTree.add(links.createAnchor(name(property)));
-        Content propertyDocTree = writer.getMemberTreeHeader();
+        Content propertyDocTree = new ContentBuilder();
         Content heading = new HtmlTree(Headings.TypeDeclaration.MEMBER_HEADING);
         heading.add(utils.getPropertyLabel(name(property)));
         propertyDocTree.add(heading);
-        return propertyDocTree;
+        propertyDocTree.add(links.createAnchor(name(property)));
+        return HtmlTree.SECTION(HtmlStyle.detail, propertyDocTree);
     }
 
     /**
@@ -161,7 +160,7 @@
                         utils.isClass(holder)
                                 ? contents.descfrmClassLabel
                                 : contents.descfrmInterfaceLabel);
-                descfrmLabel.add(Contents.SPACE);
+                descfrmLabel.add(Entity.NO_BREAK_SPACE);
                 descfrmLabel.add(codeLink);
                 propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
                 writer.addInlineComment(property, propertyDocTree);
@@ -181,8 +180,9 @@
      * {@inheritDoc}
      */
     @Override
-    public Content getPropertyDetails(Content propertyDetailsTree) {
-        return HtmlTree.SECTION(getMemberTree(propertyDetailsTree));
+    public Content getPropertyDetails(Content propertyDetailsTreeHeader, Content propertyDetailsTree) {
+        Content propertyDetails = new ContentBuilder(propertyDetailsTreeHeader, propertyDetailsTree);
+        return getMemberTree(HtmlTree.SECTION(HtmlStyle.propertyDetails, propertyDetails));
     }
 
     /**
@@ -262,7 +262,7 @@
         }
         Content labelHeading = HtmlTree.HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING,
                 label);
-        labelHeading.add(Contents.SPACE);
+        labelHeading.add(Entity.NO_BREAK_SPACE);
         labelHeading.add(classLink);
         inheritedTree.add(labelHeading);
     }
@@ -312,4 +312,9 @@
         return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member,
                 utils.getFullyQualifiedName(member));
     }
+
+    @Override
+    public Content getMemberTreeHeader(){
+        return writer.getMemberTreeHeader();
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Fri May 03 14:59:32 2019 -0400
@@ -25,10 +25,11 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.*;
+import java.util.Set;
 
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -109,7 +110,7 @@
      * @return the package serialized form header tree
      */
     public Content getPackageSerializedHeader() {
-        return HtmlTree.SECTION();
+        return HtmlTree.SECTION(HtmlStyle.serializedPackageContainer);
     }
 
     /**
@@ -121,7 +122,7 @@
     public Content getPackageHeader(String packageName) {
         Content heading = HtmlTree.HEADING(Headings.SerializedForm.PACKAGE_HEADING, true,
                 contents.packageLabel);
-        heading.add(Contents.SPACE);
+        heading.add(Entity.NO_BREAK_SPACE);
         heading.add(packageName);
         return heading;
     }
@@ -158,7 +159,7 @@
                 ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement)
                         .label(configuration.getClassName(typeElement)))
                 : new StringContent(utils.getFullyQualifiedName(typeElement));
-        Content li = HtmlTree.LI(HtmlStyle.blockList, links.createAnchor(
+        Content section = HtmlTree.SECTION(HtmlStyle.serializedClassDetails, links.createAnchor(
                 utils.getFullyQualifiedName(typeElement)));
         Content superClassLink = typeElement.getSuperclass() != null
                 ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.SERIALIZED_FORM,
@@ -172,8 +173,8 @@
             contents.getContent(
             "doclet.Class_0_extends_implements_serializable", classLink,
             superClassLink);
-        li.add(HtmlTree.HEADING(Headings.SerializedForm.CLASS_HEADING, className));
-        return li;
+        section.add(HtmlTree.HEADING(Headings.SerializedForm.CLASS_HEADING, className));
+        return section;
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -25,8 +25,10 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.*;
+import java.util.Set;
+import java.util.TreeSet;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -140,13 +142,13 @@
             contentTree.add(
                     links.createLink(getNameForIndex(unicode),
                             new StringContent(unicode)));
-            contentTree.add(Contents.SPACE);
+            contentTree.add(Entity.NO_BREAK_SPACE);
         }
         contentTree.add(new HtmlTree(HtmlTag.BR));
         contentTree.add(links.createLink(DocPaths.ALLCLASSES_INDEX,
                 contents.allClassesLabel));
         if (!configuration.packages.isEmpty()) {
-            contentTree.add(Contents.SPACE);
+            contentTree.add(Entity.NO_BREAK_SPACE);
             contentTree.add(links.createLink(DocPaths.ALLPACKAGES_INDEX,
                     contents.allPackagesLabel));
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -32,6 +32,7 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -163,13 +164,13 @@
             int j = i + 1;
             contentTree.add(links.createLink(DocPaths.indexN(j),
                     new StringContent(indexElements.get(i).toString())));
-            contentTree.add(Contents.SPACE);
+            contentTree.add(Entity.NO_BREAK_SPACE);
         }
         contentTree.add(new HtmlTree(HtmlTag.BR));
         contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLCLASSES_INDEX),
                 contents.allClassesLabel));
         if (!configuration.packages.isEmpty()) {
-            contentTree.add(Contents.SPACE);
+            contentTree.add(Entity.NO_BREAK_SPACE);
             contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLPACKAGES_INDEX),
                     contents.allPackagesLabel));
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -90,8 +90,8 @@
      */
     public void addInheritedSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement,
             Content inheritedTree) {
+        mw.addInheritedSummaryLabel(typeElement, inheritedTree);
         mw.addInheritedSummaryAnchor(typeElement, inheritedTree);
-        mw.addInheritedSummaryLabel(typeElement, inheritedTree);
     }
 
     /**
@@ -212,23 +212,29 @@
     /**
      * Get the member header tree
      *
-     * @return a content tree the member header
+     * @return a content tree for the member header
      */
     public Content getMemberTreeHeader() {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.setStyle(HtmlStyle.blockList);
-        return li;
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setStyle(HtmlStyle.blockList);
+        return ul;
+    }
+
+    public Content getMemberInheritedTree() {
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        div.setStyle(HtmlStyle.inheritedList);
+        return div;
     }
 
     /**
-     * Add the member tree.
-     *
+     * Adds the member tree with css style.
+     * @param style the css style to be applied to member tree
      * @param memberSummaryTree the content tree representing the member summary
      * @param memberTree the content tree representing the member
      */
-    public void addMemberTree(Content memberSummaryTree, Content memberTree) {
-        HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(memberTree));
-        memberSummaryTree.add(htmlTree);
+    public void addMemberTree(HtmlStyle style, Content memberSummaryTree, Content memberTree) {
+        HtmlTree htmlTree = HtmlTree.SECTION(style, memberTree);
+        memberSummaryTree.add(getMemberTree(htmlTree));
     }
 
     /**
@@ -238,8 +244,7 @@
      * @return a content tree for the member
      */
     public Content getMemberTree(Content contentTree) {
-        Content ul = HtmlTree.UL(HtmlStyle.blockList, contentTree);
-        return ul;
+        return HtmlTree.LI(HtmlStyle.blockList, contentTree);
     }
 
     /**
@@ -249,7 +254,7 @@
      * @return a content tree for the member summary
      */
     public Content getMemberSummaryTree(Content contentTree) {
-        return getMemberTree(HtmlStyle.summary, contentTree);
+        return HtmlTree.SECTION(HtmlStyle.summary, contentTree);
     }
 
     /**
@@ -259,7 +264,7 @@
      * @return a content tree for the member details
      */
     public Content getMemberDetailsTree(Content contentTree) {
-        return getMemberTree(HtmlStyle.details, contentTree);
+        return HtmlTree.SECTION(HtmlStyle.details, contentTree);
     }
 
     /**
@@ -270,7 +275,6 @@
      * @return the member tree
      */
     public Content getMemberTree(HtmlStyle style, Content contentTree) {
-        Content div = HtmlTree.DIV(style, getMemberTree(contentTree));
-        return div;
+        return HtmlTree.SECTION(style, contentTree);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Entity.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,125 @@
+/*
+ * 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 jdk.javadoc.internal.doclets.formats.html.markup;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * A representation of HTML entities.
+ */
+public class Entity extends Content {
+    public static final Entity LESS_THAN = new Entity("&lt;");
+    public static final Entity GREATER_THAN = new Entity("&gt;");
+    public static final Entity AMPERSAND = new Entity("&amp;");
+    public static final Entity NO_BREAK_SPACE = new Entity("&nbsp;");
+    public static final Entity ZERO_WIDTH_SPACE = new Entity("&#8203;") {
+        @Override
+        public int charCount() {
+            return 0;
+        }
+    };
+
+    public final String text;
+
+    private Entity(String text) {
+        this.text = text;
+    }
+
+    @Override
+    public void add(Content content) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void add(CharSequence stringContent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean write(Writer writer, boolean atNewline) throws IOException {
+        writer.write(text);
+        return false;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    @Override
+    public int charCount() {
+        return 1;
+    }
+
+
+    /**
+     * Escapes the special HTML characters in a given string using the appropriate
+     * entities.
+     *
+     * @param s the string to escape
+     * @return the string with all of the HTML characters escaped
+     */
+    static String escapeHtmlChars(CharSequence s) {
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                // only start building a new string if we need to
+                case '<': case '>': case '&':
+                    StringBuilder sb = new StringBuilder(s.subSequence(0, i));
+                    escapeHtmlChars(s, i, sb);
+                    return sb.toString();
+            }
+        }
+        return s.toString();
+    }
+
+    /**
+     * Escapes the special HTML characters in a given string using the appropriate
+     * entities, appending the results into a string builder.
+     *
+     * @param s the string
+     * @param sb the string builder
+     */
+    static void escapeHtmlChars(CharSequence s, StringBuilder sb) {
+        escapeHtmlChars(s, 0, sb);
+    }
+
+    private static void escapeHtmlChars(CharSequence s, int start, StringBuilder sb) {
+        for (int i = start ; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                case '<': sb.append(Entity.LESS_THAN.text);     break;
+                case '>': sb.append(Entity.GREATER_THAN.text);  break;
+                case '&': sb.append(Entity.AMPERSAND.text);     break;
+                default:  sb.append(ch);                        break;
+            }
+        }
+    }
+
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/FixedStringContent.java	Fri May 03 14:59:32 2019 -0400
@@ -47,9 +47,7 @@
      * @param content content for the object
      */
     public FixedStringContent(CharSequence content) {
-        string = needEscape(content)
-                ? escape(content)
-                : content.toString();
+        string = Entity.escapeHtmlChars(content);
     }
 
     /**
@@ -105,29 +103,4 @@
         return string.endsWith(DocletConstants.NL);
     }
 
-    private boolean needEscape(CharSequence cs) {
-        for (int i = 0; i < cs.length(); i++) {
-            switch (cs.charAt(i)) {
-                case '<':
-                case '>':
-                case '&':
-                    return true;
-            }
-        }
-        return false;
-    }
-    private String escape(CharSequence s) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < s.length(); i++) {
-            char ch = s.charAt(i);
-            switch (ch) {
-                case '<': sb.append("&lt;");  break;
-                case '>': sb.append("&gt;");  break;
-                case '&': sb.append("&amp;"); break;
-                default:  sb.append(ch);      break;
-            }
-        }
-        return sb.toString();
-    }
-
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Fri May 03 14:59:32 2019 -0400
@@ -59,7 +59,6 @@
     private String description;
     private String generator;
     private boolean showTimestamp;
-    private boolean useModuleDirectories;
     private DocFile mainStylesheetFile;
     private List<DocFile> additionalStylesheetFiles = Collections.emptyList();
     private boolean index;
@@ -170,17 +169,6 @@
     }
 
     /**
-     * Sets whether the module directories should be used. This is used to set the JavaScript variable.
-     *
-     * @param useModuleDirectories true if the module directories should be used
-     * @return  this object
-     */
-    public Head setUseModuleDirectories(boolean useModuleDirectories) {
-        this.useModuleDirectories = useModuleDirectories;
-        return this;
-    }
-
-    /**
      * Sets whether or not to include the supporting scripts and stylesheets for the
      * "search" feature.
      * If the feature is enabled, a {@code Script} must be provided into which some
@@ -330,7 +318,6 @@
                 mainBodyScript.append("var pathtoroot = ")
                         .appendStringLiteral(ptrPath + "/")
                         .append(";\n")
-                        .append("var useModuleDirectories = " + useModuleDirectories + ";\n")
                         .append("loadScripts(document, \'script\');");
             }
             addJQueryFile(tree, DocPaths.JSZIP_MIN);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Fri May 03 14:59:32 2019 -0400
@@ -48,12 +48,16 @@
     bottomNav,
     circle,
     classUseContainer,
+    classUses,
     colConstructorName,
     colDeprecatedItemName,
     colFirst,
     colLast,
     colSecond,
     constantsSummary,
+    constructorDetails,
+    constructorSummary,
+    constantDetails,
     constantValuesContainer,
     contentContainer,
     deprecatedLabel,
@@ -63,40 +67,58 @@
     description,
     descfrmTypeLabel,
     details,
+    detail,
     docSummary,
     emphasizedPhrase,
     externalLink,
+    fieldDetails,
+    fieldSummary,
     fixedNav,
     header,
+    helpSection,
+    hierarchy,
     horizontal,
     footer,
     implementationLabel,
     indexContainer,
     indexNav,
     inheritance,
+    inheritedList,
     interfaceName,
     leftContainer,
     leftTop,
     leftBottom,
     legalCopy,
     mainContainer,
+    memberDetails,
     memberNameLabel,
     memberNameLink,
     memberSummary,
+    methodDetails,
     methodSignature,
+    methodSummary,
+    moduleDescription,
     moduleLabelInPackage,
     moduleLabelInType,
+    moduleTags,
+    modulesSummary,
     nameValue,
     navBarCell1Rev,
     navList,
     navListSearch,
     navPadding,
+    nestedClassSummary,
     overrideSpecifyLabel,
     overviewSummary,
+    packages,
+    packageDescription,
     packageHierarchyLabel,
     packageLabelInType,
     packagesSummary,
+    packageUses,
     paramLabel,
+    propertyDetails,
+    propertySummary,
     providesSummary,
     requiresSummary,
     returnLabel,
@@ -107,6 +129,9 @@
     searchTagResult,
     seeLabel,
     serializedFormContainer,
+    serializedPackageContainer,
+    serializedClassDetails,
+    servicesSummary,
     simpleTagLabel,
     skipNav,
     sourceContainer,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Fri May 03 14:59:32 2019 -0400
@@ -100,7 +100,7 @@
     public HtmlTree put(HtmlAttr attrName, String attrValue) {
         if (attrs.isEmpty())
             attrs = new LinkedHashMap<>(3);
-        attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue));
+        attrs.put(nullCheck(attrName), Entity.escapeHtmlChars(attrValue));
         return this;
     }
 
@@ -188,35 +188,6 @@
         return n;
     }
 
-    /**
-     * Given a string, escape all special HTML characters and
-     * return the result.
-     *
-     * @param s The string to check.
-     * @return the original string with all of the HTML characters escaped.
-     */
-    private static String escapeHtmlChars(String s) {
-        for (int i = 0; i < s.length(); i++) {
-            char ch = s.charAt(i);
-            switch (ch) {
-                // only start building a new string if we need to
-                case '<': case '>': case '&':
-                    StringBuilder sb = new StringBuilder(s.substring(0, i));
-                    for ( ; i < s.length(); i++) {
-                        ch = s.charAt(i);
-                        switch (ch) {
-                            case '<': sb.append("&lt;");  break;
-                            case '>': sb.append("&gt;");  break;
-                            case '&': sb.append("&amp;"); break;
-                            default:  sb.append(ch);      break;
-                        }
-                    }
-                    return sb.toString();
-            }
-        }
-        return s;
-    }
-
     /*
      * The sets of ASCII URI characters to be left unencoded.
      * See "Uniform Resource Identifier (URI): Generic Syntax"
@@ -717,22 +688,30 @@
     }
 
     /**
-     * Generates a SECTION tag with role attribute.
+     * Generates a SECTION tag with style class attribute.
      *
+     * @param styleClass the style class for the tag
      * @return an HtmlTree object for the SECTION tag
      */
-    public static HtmlTree SECTION() {
-        return new HtmlTree(HtmlTag.SECTION);
+    public static HtmlTree SECTION(HtmlStyle styleClass) {
+        HtmlTree htmlTree = new HtmlTree(HtmlTag.SECTION);
+        htmlTree.setStyle(styleClass);
+        return htmlTree;
     }
 
     /**
-     * Generates a SECTION tag with role attribute and some content.
+     * Generates a SECTION tag with style class attribute and some content.
      *
+     * @param styleClass the style class for the tag
      * @param body content of the section tag
      * @return an HtmlTree object for the SECTION tag
      */
-    public static HtmlTree SECTION(Content body) {
-        return new HtmlTree(HtmlTag.SECTION, nullCheck(body));
+    public static HtmlTree SECTION(HtmlStyle styleClass, Content body) {
+        HtmlTree htmlTree = new HtmlTree(HtmlTag.SECTION, nullCheck(body));
+        if (styleClass != null) {
+            htmlTree.setStyle(styleClass);
+        }
+        return htmlTree;
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Fri May 03 14:59:32 2019 -0400
@@ -429,7 +429,7 @@
                 }
                 if (!listContents.isEmpty()) {
                     Content li = HtmlTree.LI(contents.summaryLabel);
-                    li.add(Contents.SPACE);
+                    li.add(Entity.NO_BREAK_SPACE);
                     tree.add(li);
                     addListToNav(listContents, tree);
                 }
@@ -461,7 +461,7 @@
                 }
                 if (!listContents.isEmpty()) {
                     Content li = HtmlTree.LI(contents.moduleSubNavLabel);
-                    li.add(Contents.SPACE);
+                    li.add(Entity.NO_BREAK_SPACE);
                     tree.add(li);
                     addListToNav(listContents, tree);
                 }
@@ -665,7 +665,7 @@
                 }
                 if (!listContents.isEmpty()) {
                     Content li = HtmlTree.LI(contents.detailLabel);
-                    li.add(Contents.SPACE);
+                    li.add(Entity.NO_BREAK_SPACE);
                     tree.add(li);
                     addListToNav(listContents, tree);
                 }
@@ -801,9 +801,9 @@
         int count = 0;
         for (Content liContent : listContents) {
             if (count < listContents.size() - 1) {
-                liContent.add(Contents.SPACE);
+                liContent.add(Entity.NO_BREAK_SPACE);
                 liContent.add("|");
-                liContent.add(Contents.SPACE);
+                liContent.add(Entity.NO_BREAK_SPACE);
             }
             tree.add(liContent);
             count++;
@@ -935,11 +935,10 @@
         String reset = "reset";
         HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId);
         HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset);
-        HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchLabel));
-        liInput.add(inputText);
-        liInput.add(inputReset);
-        HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput);
-        tree.add(ulSearch);
+        HtmlTree searchDiv = HtmlTree.DIV(HtmlStyle.navListSearch, HtmlTree.LABEL(searchValueId, searchLabel));
+        searchDiv.add(inputText);
+        searchDiv.add(inputReset);
+        tree.add(searchDiv);
     }
 
     private void addFixedNavScript(Content tree) {
@@ -1006,7 +1005,7 @@
                 fixedNavDiv.add(queue.poll());
                 fixedNavDiv.add(Position.TOP.endOfNav());
                 tree.add(fixedNavDiv);
-                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE);
+                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Entity.NO_BREAK_SPACE);
                 tree.add(paddingDiv);
                 addFixedNavScript(tree);
             } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java	Fri May 03 14:59:32 2019 -0400
@@ -45,10 +45,6 @@
 
     private final String rawHtmlContent;
 
-    public static final Content nbsp = new RawHtml("&nbsp;");
-
-    public static final Content zws = new RawHtml("&#8203;");
-
     /**
      * Constructor to construct a RawHtml object.
      *
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java	Fri May 03 14:59:32 2019 -0400
@@ -59,7 +59,7 @@
      */
     public StringContent(CharSequence initialContent) {
         stringContent = new StringBuilder();
-        appendChars(initialContent);
+        Entity.escapeHtmlChars(initialContent, stringContent);
     }
 
     /**
@@ -81,7 +81,7 @@
      */
     @Override
     public void add(CharSequence strContent) {
-        appendChars(strContent);
+        Entity.escapeHtmlChars(strContent, stringContent);
     }
 
     /**
@@ -114,16 +114,4 @@
         out.write(s);
         return s.endsWith(DocletConstants.NL);
     }
-
-    private void appendChars(CharSequence s) {
-        for (int i = 0; i < s.length(); i++) {
-            char ch = s.charAt(i);
-            switch (ch) {
-                case '<': stringContent.append("&lt;");  break;
-                case '>': stringContent.append("&gt;");  break;
-                case '&': stringContent.append("&amp;"); break;
-                default:  stringContent.append(ch);      break;
-            }
-        }
-    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Fri May 03 14:59:32 2019 -0400
@@ -531,6 +531,6 @@
     private HtmlTree getCaption(Content title) {
         return new HtmlTree(HtmlTag.CAPTION,
                 HtmlTree.SPAN(title),
-                HtmlTree.SPAN(tabEnd, Contents.SPACE));
+                HtmlTree.SPAN(tabEnd, Entity.NO_BREAK_SPACE));
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js	Fri May 03 14:59:32 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,42 +30,63 @@
 var catMembers = "Members";
 var catSearchTags = "SearchTags";
 var highlight = "<span class=\"resultHighlight\">$&</span>";
-var camelCaseRegexp = "";
-var secondaryMatcher = "";
+var searchPattern = "";
+var RANKING_THRESHOLD = 2;
+var NO_MATCH = 0xffff;
+var MAX_RESULTS_PER_CATEGORY = 500;
 function escapeHtml(str) {
     return str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
 }
-function getHighlightedText(item) {
-    var ccMatcher = new RegExp(escapeHtml(camelCaseRegexp));
+function getHighlightedText(item, matcher) {
     var escapedItem = escapeHtml(item);
-    var label = escapedItem.replace(ccMatcher, highlight);
-    if (label === escapedItem) {
-        var secMatcher = new RegExp(escapeHtml(secondaryMatcher.source), "i");
-        label = escapedItem.replace(secMatcher, highlight);
-    }
-    return label;
+    return escapedItem.replace(matcher, highlight);
 }
 function getURLPrefix(ui) {
     var urlPrefix="";
-    if (useModuleDirectories) {
-        var slash = "/";
-        if (ui.item.category === catModules) {
-            return ui.item.l + slash;
-        } else if (ui.item.category === catPackages && ui.item.m) {
-            return ui.item.m + slash;
-        } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {
-            $.each(packageSearchIndex, function(index, item) {
-                if (item.m && ui.item.p == item.l) {
-                    urlPrefix = item.m + slash;
-                }
-            });
-            return urlPrefix;
-        } else {
-            return urlPrefix;
-        }
+    var slash = "/";
+    if (ui.item.category === catModules) {
+        return ui.item.l + slash;
+    } else if (ui.item.category === catPackages && ui.item.m) {
+        return ui.item.m + slash;
+    } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {
+        $.each(packageSearchIndex, function(index, item) {
+            if (item.m && ui.item.p == item.l) {
+                urlPrefix = item.m + slash;
+            }
+        });
+        return urlPrefix;
+    } else {
+        return urlPrefix;
     }
     return urlPrefix;
 }
+function makeCamelCaseRegex(term) {
+    var pattern = "";
+    var isWordToken = false;
+    term.replace(/,\s*/g, ", ").trim().split(/\s+/).forEach(function(w, index) {
+        if (index > 0) {
+            // whitespace between identifiers is significant
+            pattern += (isWordToken && /^\w/.test(w)) ? "\\s+" : "\\s*";
+        }
+        var tokens = w.split(/(?=[A-Z,.()<>[\/])/);
+        for (var i = 0; i < tokens.length; i++) {
+            var s = tokens[i];
+            if (s === "") {
+                continue;
+            }
+            pattern += $.ui.autocomplete.escapeRegex(s);
+            isWordToken =  /\w$/.test(s);
+            if (isWordToken) {
+                pattern += "([a-z0-9_$<>\\[\\]]*?)";
+            }
+        }
+    });
+    return pattern;
+}
+function createMatcher(pattern, flags) {
+    var isCamelCase = /[A-Z]/.test(pattern);
+    return new RegExp(pattern, flags + (isCamelCase ? "" : "i"));
+}
 var watermark = 'Search';
 $(function() {
     $("#search").val('');
@@ -95,8 +116,8 @@
         this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
     },
     _renderMenu: function(ul, items) {
-        var rMenu = this,
-                currentCategory = "";
+        var rMenu = this;
+        var currentCategory = "";
         rMenu.menu.bindings = $();
         $.each(items, function(index, item) {
             var li;
@@ -116,20 +137,21 @@
     },
     _renderItem: function(ul, item) {
         var label = "";
+        var matcher = createMatcher(escapeHtml(searchPattern), "g");
         if (item.category === catModules) {
-            label = getHighlightedText(item.l);
+            label = getHighlightedText(item.l, matcher);
         } else if (item.category === catPackages) {
             label = (item.m)
-                    ? getHighlightedText(item.m + "/" + item.l)
-                    : getHighlightedText(item.l);
+                    ? getHighlightedText(item.m + "/" + item.l, matcher)
+                    : getHighlightedText(item.l, matcher);
         } else if (item.category === catTypes) {
             label = (item.p)
-                    ? getHighlightedText(item.p + "." + item.l)
-                    : getHighlightedText(item.l);
+                    ? getHighlightedText(item.p + "." + item.l, matcher)
+                    : getHighlightedText(item.l, matcher);
         } else if (item.category === catMembers) {
-            label = getHighlightedText(item.p + "." + (item.c + "." + item.l));
+            label = getHighlightedText(item.p + "." + (item.c + "." + item.l), matcher);
         } else if (item.category === catSearchTags) {
-            label = getHighlightedText(item.l);
+            label = getHighlightedText(item.l, matcher);
         } else {
             label = item.l;
         }
@@ -148,128 +170,137 @@
         return li;
     }
 });
+function rankMatch(match, category) {
+    if (!match) {
+        return NO_MATCH;
+    }
+    var index = match.index;
+    var input = match.input;
+    var leftBoundaryMatch = 2;
+    var periferalMatch = 0;
+    var delta = 0;
+    // make sure match is anchored on a left word boundary
+    if (index === 0 || /\W/.test(input[index - 1]) || "_" === input[index - 1] || "_" === input[index]) {
+        leftBoundaryMatch = 0;
+    } else if (input[index] === input[index].toUpperCase() && !/^[A-Z0-9_$]+$/.test(input)) {
+        leftBoundaryMatch = 1;
+    }
+    var matchEnd = index + match[0].length;
+    var leftParen = input.indexOf("(");
+    // exclude peripheral matches
+    if (category !== catModules && category !== catSearchTags) {
+        var endOfName = leftParen > -1 ? leftParen : input.length;
+        var delim = category === catPackages ? "/" : ".";
+        if (leftParen > -1 && leftParen < index) {
+            periferalMatch += 2;
+        } else if (input.lastIndexOf(delim, endOfName) >= matchEnd) {
+            periferalMatch += 2;
+        }
+    }
+    for (var i = 1; i < match.length; i++) {
+        // lower ranking if parts of the name are missing
+        if (match[i])
+            delta += match[i].length;
+    }
+    if (category === catTypes) {
+        // lower ranking if a type name contains unmatched camel-case parts
+        if (/[A-Z]/.test(input.substring(matchEnd)))
+            delta += 5;
+        if (/[A-Z]/.test(input.substring(0, index)))
+            delta += 5;
+    }
+    return leftBoundaryMatch + periferalMatch + (delta / 200);
+
+}
 $(function() {
     $("#search").catcomplete({
         minLength: 1,
         delay: 300,
         source: function(request, response) {
-            var result = new Array();
-            var presult = new Array();
-            var tresult = new Array();
-            var mresult = new Array();
-            var tgresult = new Array();
-            var secondaryresult = new Array();
-            var displayCount = 0;
-            var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i");
-            camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)");
-            var camelCaseMatcher = new RegExp("^" + camelCaseRegexp);
-            secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
+            var result = [];
+            var newResults = [];
 
-            // Return the nested innermost name from the specified object
-            function nestedName(e) {
-                return e.l.substring(e.l.lastIndexOf(".") + 1);
+            searchPattern = makeCamelCaseRegex(request.term);
+            if (searchPattern === "") {
+                return this.close();
             }
+            var camelCaseMatcher = createMatcher(searchPattern, "");
+            var boundaryMatcher = createMatcher("\\b" + searchPattern, "");
 
             function concatResults(a1, a2) {
-                a1 = a1.concat(a2);
+                a2.sort(function(e1, e2) {
+                    return e1.ranking - e2.ranking;
+                });
+                a1 = a1.concat(a2.map(function(e) { return e.item; }));
                 a2.length = 0;
                 return a1;
             }
 
             if (moduleSearchIndex) {
-                var mdleCount = 0;
                 $.each(moduleSearchIndex, function(index, item) {
                     item.category = catModules;
-                    if (exactMatcher.test(item.l)) {
-                        result.push(item);
-                        mdleCount++;
-                    } else if (camelCaseMatcher.test(item.l)) {
-                        result.push(item);
-                    } else if (secondaryMatcher.test(item.l)) {
-                        secondaryresult.push(item);
+                    var ranking = rankMatch(boundaryMatcher.exec(item.l), catModules);
+                    if (ranking < RANKING_THRESHOLD) {
+                        newResults.push({ ranking: ranking, item: item });
                     }
+                    return newResults.length < MAX_RESULTS_PER_CATEGORY;
                 });
-                displayCount = mdleCount;
-                result = concatResults(result, secondaryresult);
+                result = concatResults(result, newResults);
             }
             if (packageSearchIndex) {
-                var pCount = 0;
-                var pkg = "";
                 $.each(packageSearchIndex, function(index, item) {
                     item.category = catPackages;
-                    pkg = (item.m)
+                    var name = (item.m && request.term.indexOf("/") > -1)
                             ? (item.m + "/" + item.l)
                             : item.l;
-                    if (exactMatcher.test(item.l)) {
-                        presult.push(item);
-                        pCount++;
-                    } else if (camelCaseMatcher.test(pkg)) {
-                        presult.push(item);
-                    } else if (secondaryMatcher.test(pkg)) {
-                        secondaryresult.push(item);
+                    var ranking = rankMatch(boundaryMatcher.exec(name), catPackages);
+                    if (ranking < RANKING_THRESHOLD) {
+                        newResults.push({ ranking: ranking, item: item });
                     }
+                    return newResults.length < MAX_RESULTS_PER_CATEGORY;
                 });
-                result = result.concat(concatResults(presult, secondaryresult));
-                displayCount = (pCount > displayCount) ? pCount : displayCount;
+                result = concatResults(result, newResults);
             }
             if (typeSearchIndex) {
-                var tCount = 0;
                 $.each(typeSearchIndex, function(index, item) {
                     item.category = catTypes;
-                    var s = nestedName(item);
-                    if (exactMatcher.test(s)) {
-                        tresult.push(item);
-                        tCount++;
-                    } else if (camelCaseMatcher.test(s)) {
-                        tresult.push(item);
-                    } else if (secondaryMatcher.test(item.p + "." + item.l)) {
-                        secondaryresult.push(item);
+                    var name = request.term.indexOf(".") > -1
+                        ? item.p + "." + item.l
+                        : item.l;
+                    var ranking = rankMatch(camelCaseMatcher.exec(name), catTypes);
+                    if (ranking < RANKING_THRESHOLD) {
+                        newResults.push({ ranking: ranking, item: item });
                     }
+                    return newResults.length < MAX_RESULTS_PER_CATEGORY;
                 });
-                result = result.concat(concatResults(tresult, secondaryresult));
-                displayCount = (tCount > displayCount) ? tCount : displayCount;
+                result = concatResults(result, newResults);
             }
             if (memberSearchIndex) {
-                var mCount = 0;
                 $.each(memberSearchIndex, function(index, item) {
                     item.category = catMembers;
-                    var s = nestedName(item);
-                    if (exactMatcher.test(s)) {
-                        mresult.push(item);
-                        mCount++;
-                    } else if (camelCaseMatcher.test(s)) {
-                        mresult.push(item);
-                    } else if (secondaryMatcher.test(item.c + "." + item.l)) {
-                        secondaryresult.push(item);
+                    var name = request.term.indexOf(".") > -1
+                            ? item.p + "." + item.c + "." + item.l
+                            : item.l;
+                    var ranking = rankMatch(camelCaseMatcher.exec(name), catMembers);
+                    if (ranking < RANKING_THRESHOLD) {
+                        newResults.push({ ranking: ranking, item: item });
                     }
+                    return newResults.length < MAX_RESULTS_PER_CATEGORY;
                 });
-                result = result.concat(concatResults(mresult, secondaryresult));
-                displayCount = (mCount > displayCount) ? mCount : displayCount;
+                result = concatResults(result, newResults);
             }
             if (tagSearchIndex) {
-                var tgCount = 0;
                 $.each(tagSearchIndex, function(index, item) {
                     item.category = catSearchTags;
-                    if (exactMatcher.test(item.l)) {
-                        tgresult.push(item);
-                        tgCount++;
-                    } else if (secondaryMatcher.test(item.l)) {
-                        secondaryresult.push(item);
+                    var ranking = rankMatch(boundaryMatcher.exec(item.l), catSearchTags);
+                    if (ranking < RANKING_THRESHOLD) {
+                        newResults.push({ ranking: ranking, item: item });
                     }
+                    return newResults.length < MAX_RESULTS_PER_CATEGORY;
                 });
-                result = result.concat(concatResults(tgresult, secondaryresult));
-                displayCount = (tgCount > displayCount) ? tgCount : displayCount;
+                result = concatResults(result, newResults);
             }
-            displayCount = (displayCount > 500) ? displayCount : 500;
-            var counter = function() {
-                var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0};
-                var f = function(item) {
-                    count[item.category] += 1;
-                    return (count[item.category] <= displayCount);
-                };
-                return f;
-            }();
-            response(result.filter(counter));
+            response(result);
         },
         response: function(event, ui) {
             if (!ui.content.length) {
@@ -286,11 +317,7 @@
             if (ui.item.l !== noResult.l) {
                 var url = getURLPrefix(ui);
                 if (ui.item.category === catModules) {
-                    if (useModuleDirectories) {
-                        url += "module-summary.html";
-                    } else {
-                        url = ui.item.l + "-summary.html";
-                    }
+                    url += "module-summary.html";
                 } else if (ui.item.category === catPackages) {
                     if (ui.item.url) {
                         url = ui.item.url;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Fri May 03 14:59:32 2019 -0400
@@ -94,6 +94,7 @@
 doclet.Interfaces=Interfaces
 doclet.Enclosing_Class=Enclosing class:
 doclet.Enclosing_Interface=Enclosing interface:
+doclet.Inheritance_Tree=Inheritance Tree
 doclet.System_Property=System Property
 doclet.Window_Source_title=Source code
 doclet.Window_Help_title=API Help
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeFieldWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -62,10 +62,8 @@
      * Add the annotation type details tree header.
      *
      * @param typeElement the annotation type being documented
-     * @param memberDetailsTree the content tree representing member details
      */
-    public void addAnnotationDetailsTreeHeader(TypeElement typeElement,
-            Content memberDetailsTree);
+    public Content getAnnotationDetailsTreeHeader(TypeElement typeElement);
 
     /**
      * Get the annotation type documentation tree header.
@@ -79,10 +77,11 @@
     /**
      * Get the annotation type details tree.
      *
+     * @param annotationDetailsTreeHeader the content tree representing annotation type details header
      * @param annotationDetailsTree the content tree representing annotation type details
      * @return content tree for the annotation type details
      */
-    public Content getAnnotationDetails(Content annotationDetailsTree);
+    public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree);
 
     /**
      * Get the annotation type documentation.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeRequiredMemberWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -61,10 +61,8 @@
      * Add the annotation type details tree header.
      *
      * @param typeElement the annotation type being documented
-     * @param memberDetailsTree the content tree representing member details
      */
-    public void addAnnotationDetailsTreeHeader(TypeElement typeElement,
-            Content memberDetailsTree);
+    public Content getAnnotationDetailsTreeHeader(TypeElement typeElement);
 
     /**
      * Get the annotation type documentation tree header.
@@ -79,10 +77,11 @@
     /**
      * Get the annotation type details tree.
      *
+     * @param annotationDetailsTreeHeader the content tree representing annotation type details header
      * @param annotationDetailsTree the content tree representing annotation type details
      * @return content tree for the annotation type details
      */
-    public Content getAnnotationDetails(Content annotationDetailsTree);
+    public Content getAnnotationDetails(Content annotationDetailsTreeHeader, Content annotationDetailsTree);
 
     /**
      * Get the annotation type documentation.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Fri May 03 14:59:32 2019 -0400
@@ -295,12 +295,6 @@
      // A list of pairs containing urls and package list
     private final List<Pair<String, String>> linkOfflineList = new ArrayList<>();
 
-    /**
-     * Flag to enable/disable use of module directories when generating docs for modules
-     * Default: on (module directories are enabled).
-     */
-    public boolean useModuleDirectories = true;
-
     public boolean dumpOnError = false;
 
     private List<Pair<String, String>> groupPairs;
@@ -748,13 +742,6 @@
                         showTaglets = true;
                         return true;
                     }
-                },
-                new XOption(resources, "--no-module-directories") {
-                    @Override
-                    public boolean process(String option, List<String> args) {
-                        useModuleDirectories = false;
-                        return true;
-                    }
                 }
         };
         Set<Doclet.Option> set = new TreeSet<>();
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstructorWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -99,10 +99,11 @@
     /**
      * Get the constructor details tree.
      *
+     * memberDetailsTreeHeader the content tree representing member details header
      * @param memberDetailsTree the content tree representing member details
      * @return content tree for the constructor details
      */
-    public Content getConstructorDetails(Content memberDetailsTree);
+    public Content getConstructorDetails(Content memberDetailsTreeHeader, Content memberDetailsTree);
 
     /**
      * Get the constructor documentation.
@@ -119,4 +120,11 @@
      * @param foundNonPubConstructor true if we found a non public constructor.
      */
     public void setFoundNonPubConstructor(boolean foundNonPubConstructor);
+
+    /**
+     * Gets the member header tree.
+     *
+     * @return a content tree for the member header
+     */
+    public Content getMemberTreeHeader();
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/EnumConstantWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -102,7 +102,7 @@
      * @param memberDetailsTree the content tree representing member details
      * @return content tree for the enum constant details
      */
-    public Content getEnumConstantsDetails(Content memberDetailsTree);
+    public Content getEnumConstantsDetails(Content memberDetailsTreeHeader, Content memberDetailsTree);
 
     /**
      * Get the enum constants documentation.
@@ -112,4 +112,11 @@
      * @return content tree for the enum constants documentation
      */
     public Content getEnumConstants(Content enumConstantsTree, boolean isLastContent);
+
+    /**
+     * Gets the member header tree.
+     *
+     * @return a content tree for the member header
+     */
+    public Content getMemberTreeHeader();
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/FieldWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -100,10 +100,11 @@
     /**
      * Get the field details tree.
      *
+     * @param memberDetailsTreeHeader the content tree representing member details tree header
      * @param memberDetailsTree the content tree representing member details
      * @return content tree for the field details
      */
-    public Content getFieldDetails(Content memberDetailsTree);
+    public Content getFieldDetails(Content memberDetailsTreeHeader, Content memberDetailsTree);
 
     /**
      * Get the field documentation.
@@ -113,4 +114,11 @@
      * @return content tree for the field documentation
      */
     public Content getFieldDoc(Content fieldDocTree, boolean isLastContent);
+
+    /**
+     * Gets the member header tree.
+     *
+     * @return a content tree for the member header
+     */
+    public Content getMemberTreeHeader();
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MethodWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -101,10 +101,11 @@
     /**
      * Get the method details tree.
      *
+     * @param methodDetailsTreeHeader the content tree representing method details header
      * @param methodDetailsTree the content tree representing method details
      * @return content tree for the method details
      */
-    public Content getMethodDetails(Content methodDetailsTree);
+    public Content getMethodDetails(Content methodDetailsTreeHeader, Content methodDetailsTree);
 
     /**
      * Get the method documentation.
@@ -114,4 +115,11 @@
      * @return content tree for the method documentation
      */
     public Content getMethodDoc(Content methodDocTree, boolean isLastContent);
+
+    /**
+     * Gets the member header tree.
+     *
+     * @return a content tree for the member header
+     */
+    public Content getMemberTreeHeader();
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -163,4 +163,11 @@
      */
     public abstract void printDocument(Content contentTree) throws DocFileIOException;
 
+    /**
+     * Gets the package summary tree.
+     * @param summaryContentTree the content tree representing the package summary
+     * @return a content tree for the package summary
+     */
+    public abstract Content getPackageSummary(Content summaryContentTree);
+
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -99,10 +99,11 @@
     /**
      * Get the property details tree.
      *
+     * @param memberDetailsTreeHeader the content tree representing member details header
      * @param memberDetailsTree the content tree representing member details
      * @return content tree for the property details
      */
-    public Content getPropertyDetails(Content memberDetailsTree);
+    public Content getPropertyDetails(Content memberDetailsTreeHeader, Content memberDetailsTree);
 
     /**
      * Get the property documentation.
@@ -112,4 +113,11 @@
      * @return content tree for the property documentation
      */
     public Content getPropertyDoc(Content propertyDocTree, boolean isLastContent);
+
+    /**
+     * Gets the member header tree.
+     *
+     * @return a content tree for the member header
+     */
+    public Content getMemberTreeHeader();
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java	Fri May 03 14:59:32 2019 -0400
@@ -163,6 +163,14 @@
     public abstract void printDocument(Content serializedTree) throws DocFileIOException;
 
     /**
+     * Gets the member tree.
+     *
+     * @param contentTree the tree used to generate the complete member tree
+     * @return a content tree for the member
+     */
+    public Content getMemberTree(Content contentTree);
+
+    /**
      * Write the serialized form for a given field.
      */
     public interface SerialFieldWriter {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,7 @@
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
@@ -149,8 +150,7 @@
      */
     protected void buildAnnotationTypeInfo(Content annotationContentTree)
             throws DocletException {
-        Content annotationInfoTree = writer.getAnnotationInfoTreeHeader();
-
+        Content annotationInfoTree = new ContentBuilder();
         buildAnnotationTypeSignature(annotationInfoTree);
         buildDeprecationInfo(annotationInfoTree);
         buildAnnotationTypeDescription(annotationInfoTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -139,12 +139,12 @@
         }
         if (hasMembersToDocument()) {
             writer.addAnnotationFieldDetailsMarker(memberDetailsTree);
+            Content annotationDetailsTreeHeader = writer.getAnnotationDetailsTreeHeader(typeElement);
+            Content detailsTree = writer.getMemberTreeHeader();
 
             Element lastElement = members.get(members.size() - 1);
             for (Element member : members) {
                 currentMember = member;
-                Content detailsTree = writer.getMemberTreeHeader();
-                writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree);
                 Content annotationDocTree = writer.getAnnotationDocTreeHeader(currentMember,
                         detailsTree);
 
@@ -155,8 +155,8 @@
 
                 detailsTree.add(writer.getAnnotationDoc(
                         annotationDocTree, currentMember == lastElement));
-                memberDetailsTree.add(writer.getAnnotationDetails(detailsTree));
             }
+            memberDetailsTree.add(writer.getAnnotationDetails(annotationDetailsTreeHeader, detailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -142,11 +142,11 @@
         }
         if (hasMembersToDocument()) {
             writer.addAnnotationDetailsMarker(memberDetailsTree);
+            Content annotationDetailsTreeHeader = writer.getAnnotationDetailsTreeHeader(typeElement);
+            Content detailsTree = writer.getMemberTreeHeader();
             Element lastMember = members.get((members.size() - 1));
             for (Element member : members) {
                 currentMember = member;
-                Content detailsTree = writer.getMemberTreeHeader();
-                writer.addAnnotationDetailsTreeHeader(typeElement, detailsTree);
                 Content annotationDocTree = writer.getAnnotationDocTreeHeader(
                         currentMember, detailsTree);
 
@@ -154,8 +154,8 @@
 
                 detailsTree.add(writer.getAnnotationDoc(
                         annotationDocTree, currentMember == lastMember));
-                memberDetailsTree.add(writer.getAnnotationDetails(detailsTree));
             }
+            memberDetailsTree.add(writer.getAnnotationDetails(annotationDetailsTreeHeader, detailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -28,6 +28,7 @@
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
@@ -166,8 +167,7 @@
      * @throws DocletException if there is a problem while building the documentation
      */
     protected void buildClassInfo(Content classContentTree) throws DocletException {
-        Content classInfoTree = writer.getClassInfoTreeHeader();
-
+        Content classInfoTree = new ContentBuilder();
         buildTypeParamInfo(classInfoTree);
         buildSuperInterfacesInfo(classInfoTree);
         buildImplementedInterfacesInfo(classInfoTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -135,8 +135,9 @@
             return;
         }
         if (hasMembersToDocument()) {
-            Content constructorDetailsTree = writer.getConstructorDetailsTreeHeader(typeElement,
+            Content constructorDetailsTreeHeader = writer.getConstructorDetailsTreeHeader(typeElement,
                     memberDetailsTree);
+            Content constructorDetailsTree = writer.getMemberTreeHeader();
 
             Element lastElement = constructors.get(constructors.size() - 1);
             for (Element contructor : constructors) {
@@ -152,7 +153,7 @@
                         currentConstructor == lastElement));
             }
             memberDetailsTree.add(
-                    writer.getConstructorDetails(constructorDetailsTree));
+                    writer.getConstructorDetails(constructorDetailsTreeHeader, constructorDetailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -123,8 +123,9 @@
             return;
         }
         if (hasMembersToDocument()) {
-            Content enumConstantsDetailsTree = writer.getEnumConstantsDetailsTreeHeader(typeElement,
+            Content enumConstantsDetailsTreeHeader = writer.getEnumConstantsDetailsTreeHeader(typeElement,
                     memberDetailsTree);
+            Content enumConstantsDetailsTree = writer.getMemberTreeHeader();
             Element lastElement = enumConstants.get(enumConstants.size() - 1);
             for (Element enumConstant : enumConstants) {
                 currentElement = (VariableElement)enumConstant;
@@ -140,7 +141,7 @@
                         enumConstantsTree, currentElement == lastElement));
             }
             memberDetailsTree.add(
-                    writer.getEnumConstantsDetails(enumConstantsDetailsTree));
+                    writer.getEnumConstantsDetails(enumConstantsDetailsTreeHeader, enumConstantsDetailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -125,7 +125,8 @@
             return;
         }
         if (!fields.isEmpty()) {
-            Content fieldDetailsTree = writer.getFieldDetailsTreeHeader(typeElement, memberDetailsTree);
+            Content fieldDetailsTreeHeader = writer.getFieldDetailsTreeHeader(typeElement, memberDetailsTree);
+            Content fieldDetailsTree = writer.getMemberTreeHeader();
 
             Element lastElement = fields.get(fields.size() - 1);
             for (Element element : fields) {
@@ -141,7 +142,7 @@
                         fieldDocTree, currentElement == lastElement));
             }
             memberDetailsTree.add(
-                    writer.getFieldDetails(fieldDetailsTree));
+                    writer.getFieldDetails(fieldDetailsTreeHeader, fieldDetailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -465,7 +465,7 @@
                 Content linksTree = writer.getInheritedSummaryLinksTree();
                 addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
                 inheritedTree.add(linksTree);
-                summaryTreeList.add(writer.getMemberTree(inheritedTree));
+                summaryTreeList.add(inheritedTree);
             }
         }
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -126,8 +126,9 @@
             return;
         }
         if (hasMembersToDocument()) {
-            Content methodDetailsTree = writer.getMethodDetailsTreeHeader(typeElement,
+            Content methodDetailsTreeHeader = writer.getMethodDetailsTreeHeader(typeElement,
                     memberDetailsTree);
+            Content methodDetailsTree = writer.getMemberTreeHeader();
 
             Element lastElement = methods.get(methods.size() - 1);
             for (Element method : methods) {
@@ -142,7 +143,7 @@
                 methodDetailsTree.add(writer.getMethodDoc(
                         methodDocTree, currentMethod == lastElement));
             }
-            memberDetailsTree.add(writer.getMethodDetails(methodDetailsTree));
+            memberDetailsTree.add(writer.getMethodDetails(methodDetailsTreeHeader, methodDetailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -163,7 +163,7 @@
         buildErrorSummary(summaryContentTree);
         buildAnnotationTypeSummary(summaryContentTree);
 
-        packageContentTree.add(summaryContentTree);
+        packageContentTree.add(packageWriter.getPackageSummary(summaryContentTree));
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -125,8 +125,9 @@
             return;
         }
         if (hasMembersToDocument()) {
-            Content propertyDetailsTree = writer.getPropertyDetailsTreeHeader(typeElement,
+            Content propertyDetailsTreeHeader = writer.getPropertyDetailsTreeHeader(typeElement,
                     memberDetailsTree);
+            Content propertyDetailsTree = writer.getMemberTreeHeader();
             Element lastElement = properties.get(properties.size() - 1);
             for (Element property : properties) {
                 currentProperty = (ExecutableElement)property;
@@ -141,7 +142,7 @@
                         propertyDocTree, currentProperty == lastElement));
             }
             memberDetailsTree.add(
-                    writer.getPropertyDetails(propertyDetailsTree));
+                    writer.getPropertyDetails(propertyDetailsTreeHeader, propertyDetailsTree));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -232,7 +232,7 @@
                 buildSerialUIDInfo(classTree);
                 buildClassContent(classTree);
 
-                classSerializedTree.add(classTree);
+                classSerializedTree.add(writer.getMemberTree(classTree));
             }
         }
         packageSerializedTree.add(classSerializedTree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js	Fri May 03 14:59:32 2019 -0400
@@ -29,11 +29,11 @@
 var memberSearchIndex;
 var tagSearchIndex;
 function loadScripts(doc, tag) {
-    createElem(doc, tag, 'jquery/jszip/dist/jszip.js');
-    createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js');
+    createElem(doc, tag, 'script-dir/jszip/dist/jszip.js');
+    createElem(doc, tag, 'script-dir/jszip-utils/dist/jszip-utils.js');
     if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 ||
             window.navigator.userAgent.indexOf('Edge/') > 0) {
-        createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js');
+        createElem(doc, tag, 'script-dir/jszip-utils/dist/jszip-utils-ie.js');
     }
     createElem(doc, tag, 'search.js');
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Fri May 03 14:59:32 2019 -0400
@@ -207,18 +207,13 @@
     padding: 5px 6px;
     text-transform:uppercase;
 }
-ul.navListSearch {
+.subNav .navListSearch {
     float:right;
     margin:0 0 0 0;
-    padding:0;
+    padding:5px 6px;
+    clear:none;
 }
-ul.navListSearch li {
-    list-style:none;
-    float:right;
-    padding: 5px 6px;
-    text-transform:uppercase;
-}
-ul.navListSearch li label {
+.navListSearch label {
     position:relative;
     right:-16px;
 }
@@ -304,7 +299,8 @@
     margin:15px 0;
 }
 body.class-declaration .summary h3,
-body.class-declaration .details h3 {
+body.class-declaration .details h3,
+body.class-declaration .summary .inheritedList h2 {
     background-color:#dee3e9;
     border:1px solid #d0d9e0;
     margin:0 0 6px -8px;
@@ -368,49 +364,22 @@
     display:inline;
     font-size:0.9em;
 }
-ul.inheritance {
+div.inheritance {
     margin:0;
     padding:0;
 }
-ul.inheritance li {
-    display:inline;
-    list-style:none;
-}
-ul.inheritance li ul.inheritance {
-    margin-left:15px;
-    padding-left:15px;
-    padding-top:1px;
+div.inheritance div.inheritance {
+    margin-left:2em;
 }
 ul.blockList, ul.blockListLast {
     margin:10px 0 10px 0;
     padding:0;
 }
-ul.blockList li.blockList, ul.blockListLast li.blockList {
+ul.blockList li.blockList, ul.blockList li.blockListLast {
     list-style:none;
     margin-bottom:15px;
     line-height:1.4;
 }
-ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
-    padding:0px 20px 5px 10px;
-    border:1px solid #ededed; 
-    background-color:#f8f8f8;
-}
-ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
-    padding:0 0 5px 8px;
-    background-color:#ffffff;
-    border:none;
-}
-ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
-    margin-left:0;
-    padding-left:0;
-    padding-bottom:15px;
-    border:none;
-}
-ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
-    list-style:none;
-    border-bottom:none;
-    padding-bottom:0;
-}
 table tr td dl, table tr td dl dt, table tr td dl dd {
     margin-top:0;
     margin-bottom:1px;
@@ -787,6 +756,23 @@
 .methodSignature {
     white-space:normal;
 }
+.inheritedList {
+    margin: 10px 0 10px 0;
+}
+section.description {
+    line-height: 1.4;
+}
+.summary section[class$="Summary"], .details section[class$="Details"],
+.classUses .detail, .serializedClassDetails {
+    padding: 0px 20px 5px 10px;
+    border: 1px solid #ededed;
+    background-color: #f8f8f8;
+}
+.inheritedList, section[class$="Details"] .detail {
+    padding:0 0 5px 8px;
+    background-color:#ffffff;
+    border:none;
+}
 
 /*
  * Styles for user-provided tables.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java	Fri May 03 14:59:32 2019 -0400
@@ -39,14 +39,12 @@
  *
  */
 public class DocPaths {
-    private final boolean useModuleDirectories;
     private final String moduleSeparator;
     private final Utils utils;
 
-    public DocPaths(Utils utils, boolean useModuleDirectories) {
+    public DocPaths(Utils utils) {
         this.utils = utils;
-        this.useModuleDirectories = useModuleDirectories;
-        moduleSeparator = useModuleDirectories ? "/module-" : "-";
+        moduleSeparator = "/module-";
     }
 
     public static final DocPath DOT_DOT = DocPath.create("..");
@@ -239,12 +237,8 @@
         }
 
         DocPath pkgPath = DocPath.create(pkgElement.getQualifiedName().toString().replace('.', '/'));
-        if (useModuleDirectories) {
-            ModuleElement mdle = (ModuleElement) pkgElement.getEnclosingElement();
-            return forModule(mdle).resolve(pkgPath);
-        } else {
-            return pkgPath;
-        }
+        ModuleElement mdle = (ModuleElement) pkgElement.getEnclosingElement();
+        return forModule(mdle).resolve(pkgPath);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Fri May 03 14:59:32 2019 -0400
@@ -402,7 +402,7 @@
                         moduleItems.put(moduleName, item);
                     } else {
                         DocPath pkgPath = DocPath.create(elemname.replace('.', '/'));
-                        if (configuration.useModuleDirectories && moduleName != null) {
+                        if (moduleName != null) {
                             elempath = elempath.resolve(DocPath.create(moduleName).resolve(pkgPath));
                         } else {
                             elempath = elempath.resolve(pkgPath);
--- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c	Fri May 03 14:59:32 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
@@ -1673,7 +1673,7 @@
     /* Create jstrings for property name and value */
     nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName);
     if (nameString != NULL) {
-        valueString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyValue);
+        valueString = JNU_NewStringPlatform(env, propertyValue);
         if (valueString != NULL) {
             /* invoke Properties.setProperty */
             JNI_FUNC_PTR(env,CallObjectMethod)
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java	Fri May 03 14:59:32 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
@@ -49,20 +49,17 @@
  * @author Steve Drach
  */
 class JarFileSystem extends ZipFileSystem {
-    private Function<byte[],byte[]> lookup;
+    // lookup needs to be initialized because isMultiReleaseJar is called before createVersionedLinks
+    private Function<byte[], byte[]> lookup = path -> path;
 
     @Override
     IndexNode getInode(byte[] path) {
         // check for an alias to a versioned entry
-        byte[] versionedPath = lookup.apply(path);
-        return versionedPath == null ? super.getInode(path) : super.getInode(versionedPath);
+        return super.getInode(lookup.apply(path));
     }
 
-    JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env)
-            throws IOException {
+    JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env) throws IOException {
         super(provider, zfpath, env);
-        lookup = path -> path;  // lookup needs to be set before isMultiReleaseJar is called
-                                // because it eventually calls getEntry
         if (isMultiReleaseJar()) {
             int version;
             Object o = env.get("multi-release");
@@ -81,7 +78,7 @@
                 throw new IllegalArgumentException("env parameter must be String, Integer, "
                         + "or Version");
             }
-            lookup = createVersionedLinks(version < 0 ? 0 : version);
+            createVersionedLinks(version < 0 ? 0 : version);
             setReadOnly();
         }
     }
@@ -89,7 +86,7 @@
     private boolean isMultiReleaseJar() throws IOException {
         try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) {
             String multiRelease = new Manifest(is).getMainAttributes()
-                    .getValue(Attributes.Name.MULTI_RELEASE);
+                .getValue(Attributes.Name.MULTI_RELEASE);
             return "true".equalsIgnoreCase(multiRelease);
         } catch (NoSuchFileException x) {
             return false;
@@ -106,27 +103,71 @@
      * then wrap the map in a function that getEntry can use to override root
      * entry lookup for entries that have corresponding versioned entries
      */
-    private Function<byte[],byte[]> createVersionedLinks(int version) {
-        HashMap<IndexNode,byte[]> aliasMap = new HashMap<>();
+    private void createVersionedLinks(int version) {
         IndexNode verdir = getInode(getBytes("/META-INF/versions"));
-        if (verdir != null) {
-            getVersionMap(version, verdir).values()
-                .forEach(versionNode -> {   // for each META-INF/versions/{n} directory
-                    // put all the leaf inodes, i.e. entries, into the alias map
-                    // possibly shadowing lower versioned entries
-                    walk(versionNode, entryNode -> {
-                        byte[] rootName = getRootName(versionNode, entryNode);
-                        if (rootName != null) {
-                            IndexNode rootNode = getInode(rootName);
-                            if (rootNode == null) { // no matching root node, make a virtual one
-                                rootNode = IndexNode.keyOf(rootName);
-                            }
-                            aliasMap.put(rootNode, entryNode.name);
-                        }
-                    });
-                });
+        // nothing to do, if no /META-INF/versions
+        if (verdir == null) {
+            return;
+        }
+        // otherwise, create a map and for each META-INF/versions/{n} directory
+        // put all the leaf inodes, i.e. entries, into the alias map
+        // possibly shadowing lower versioned entries
+        HashMap<IndexNode, byte[]> aliasMap = new HashMap<>();
+        getVersionMap(version, verdir).values().forEach(versionNode ->
+            walk(versionNode.child, entryNode ->
+                aliasMap.put(
+                    getNodeInRootTree(getRootName(entryNode, versionNode), entryNode.isdir),
+                    entryNode.name))
+        );
+        lookup = path -> {
+            byte[] entry = aliasMap.get(IndexNode.keyOf(path));
+            return entry == null ? path : entry;
+        };
+    }
+
+    /**
+     * Return the node from the root tree. Create it, if it doesn't exist.
+     */
+    private IndexNode getNodeInRootTree(byte[] path, boolean isdir) {
+        IndexNode node = getInode(path);
+        if (node != null) {
+            return node;
         }
-        return path -> aliasMap.get(IndexNode.keyOf(path));
+        IndexNode parent = getParentDir(path);
+        beginWrite();
+        try {
+            node = new IndexNode(path, isdir);
+            node.sibling = parent.child;
+            parent.child = node;
+            inodes.put(node, node);
+            return node;
+        } finally {
+            endWrite();
+        }
+    }
+
+    /**
+     * Return the parent directory node of a path. If the node doesn't exist,
+     * it will be created. Parent directories will be created recursively.
+     * Recursion fuse: We assume at latest the root path can be resolved to a node.
+     */
+    private IndexNode getParentDir(byte[] path) {
+        byte[] parentPath = getParent(path);
+        IndexNode node = inodes.get(IndexNode.keyOf(parentPath));
+        if (node != null) {
+            return node;
+        }
+        IndexNode parent = getParentDir(parentPath);
+        beginWrite();
+        try {
+            node = new IndexNode(parentPath, true);
+            node.sibling = parent.child;
+            parent.child = node;
+            inodes.put(node, node);
+            return node;
+        } finally {
+            endWrite();
+        }
     }
 
     /**
@@ -138,7 +179,7 @@
         TreeMap<Integer,IndexNode> map = new TreeMap<>();
         IndexNode child = metaInfVersions.child;
         while (child != null) {
-            Integer key = getVersion(child.name, metaInfVersions.name.length + 1);
+            Integer key = getVersion(child, metaInfVersions);
             if (key != null && key <= version) {
                 map.put(key, child);
             }
@@ -150,9 +191,11 @@
     /**
      * extract the integer version number -- META-INF/versions/9 returns 9
      */
-    private Integer getVersion(byte[] name, int offset) {
+    private Integer getVersion(IndexNode inode, IndexNode metaInfVersions) {
         try {
-            return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length)));
+            byte[] fullName = inode.name;
+            return Integer.parseInt(getString(Arrays
+                .copyOfRange(fullName, metaInfVersions.name.length + 1, fullName.length)));
         } catch (NumberFormatException x) {
             // ignore this even though it might indicate issues with the JAR structure
             return null;
@@ -162,14 +205,14 @@
     /**
      * walk the IndexNode tree processing all leaf nodes
      */
-    private void walk(IndexNode inode, Consumer<IndexNode> process) {
+    private void walk(IndexNode inode, Consumer<IndexNode> consumer) {
         if (inode == null) return;
         if (inode.isDir()) {
-            walk(inode.child, process);
+            walk(inode.child, consumer);
         } else {
-            process.accept(inode);
+            consumer.accept(inode);
         }
-        walk(inode.sibling, process);
+        walk(inode.sibling, consumer);
     }
 
     /**
@@ -178,9 +221,8 @@
      *   and prefix META-INF/versions/9/
      *   returns foo/bar.class
      */
-    private byte[] getRootName(IndexNode prefix, IndexNode inode) {
-        int offset = prefix.name.length;
+    private byte[] getRootName(IndexNode inode, IndexNode prefix) {
         byte[] fullName = inode.name;
-        return Arrays.copyOfRange(fullName, offset, fullName.length);
+        return Arrays.copyOfRange(fullName, prefix.name.length, fullName.length);
     }
 }
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Fri May 03 14:59:32 2019 -0400
@@ -599,11 +599,11 @@
             throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
     }
 
-
     // Returns an output SeekableByteChannel for either
     // (1) writing the contents of a new entry, if the entry doesn't exit, or
     // (2) updating/replacing the contents of an existing entry.
-    // Note: The content is not compressed.
+    // Note: The content of the channel is not compressed until the
+    // channel is closed
     private class EntryOutputChannel extends ByteArrayChannel {
         Entry e;
 
@@ -622,19 +622,19 @@
 
         @Override
         public void close() throws IOException {
-            e.bytes = toByteArray();
-            e.size = e.bytes.length;
-            e.crc = -1;
+            // will update the entry
+            try (OutputStream os = getOutputStream(e)) {
+                os.write(toByteArray());
+            }
             super.close();
-            update(e);
         }
     }
 
-    private int getCompressMethod(FileAttribute<?>... attrs) {
+    private int getCompressMethod() {
          return defaultMethod;
     }
 
-    // Returns a Writable/ReadByteChannel for now. Might consdier to use
+    // Returns a Writable/ReadByteChannel for now. Might consider to use
     // newFileChannel() instead, which dump the entry data into a regular
     // file on the default file system and create a FileChannel on top of
     // it.
@@ -647,10 +647,9 @@
         if (options.contains(StandardOpenOption.WRITE) ||
             options.contains(StandardOpenOption.APPEND)) {
             checkWritable();
-            beginRead();    // only need a readlock, the "update()" will obtain
-                            // thewritelock when the channel is closed
+            beginRead();    // only need a read lock, the "update()" will obtain
+                            // the write lock when the channel is closed
             try {
-                ensureOpen();
                 Entry e = getEntry(path);
                 if (e != null) {
                     if (e.isDir() || options.contains(CREATE_NEW))
@@ -675,8 +674,7 @@
                     throw new NoSuchFileException(getString(path));
                 checkParents(path);
                 return new EntryOutputChannel(
-                    new Entry(path, Entry.NEW, false, getCompressMethod(attrs)));
-
+                    new Entry(path, Entry.NEW, false, getCompressMethod()));
             } finally {
                 endRead();
             }
@@ -743,7 +741,7 @@
             final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
             if (forWrite) {
                 u.flag = FLAG_DATADESCR;
-                u.method = getCompressMethod(attrs);
+                u.method = getCompressMethod();
             }
             // is there a better way to hook into the FileChannel's close method?
             return new FileChannel() {
@@ -844,7 +842,11 @@
 
     // the outstanding input streams that need to be closed
     private Set<InputStream> streams =
-        Collections.synchronizedSet(new HashSet<InputStream>());
+        Collections.synchronizedSet(new HashSet<>());
+
+    // the ex-channel and ex-path that need to close when their outstanding
+    // input streams are all closed by the obtainers.
+    private Set<ExistingChannelCloser> exChClosers = new HashSet<>();
 
     private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
     private Path getTempPathForEntry(byte[] path) throws IOException {
@@ -882,7 +884,7 @@
     }
 
     private static byte[] ROOTPATH = new byte[] { '/' };
-    private static byte[] getParent(byte[] path) {
+    static byte[] getParent(byte[] path) {
         int off = getParentOff(path);
         if (off <= 1)
             return ROOTPATH;
@@ -897,11 +899,11 @@
         return off;
     }
 
-    private final void beginWrite() {
+    final void beginWrite() {
         rwlock.writeLock().lock();
     }
 
-    private final void endWrite() {
+    final void endWrite() {
         rwlock.writeLock().unlock();
     }
 
@@ -924,7 +926,7 @@
     private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
 
     // name -> pos (in cen), IndexNode itself can be used as a "key"
-    private LinkedHashMap<IndexNode, IndexNode> inodes;
+    LinkedHashMap<IndexNode, IndexNode> inodes;
 
     final byte[] getBytes(String name) {
         return zc.getBytes(name);
@@ -1202,25 +1204,20 @@
         return written;
     }
 
-    private long writeEntry(Entry e, OutputStream os, byte[] buf)
+    private long writeEntry(Entry e, OutputStream os)
         throws IOException {
 
         if (e.bytes == null && e.file == null)    // dir, 0-length data
             return 0;
 
         long written = 0;
-        try (OutputStream os2 = e.method == METHOD_STORED ?
-            new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) {
-            if (e.bytes != null) {                 // in-memory
-                os2.write(e.bytes, 0, e.bytes.length);
-            } else if (e.file != null) {           // tmp file
-                if (e.type == Entry.NEW || e.type == Entry.FILECH) {
-                    try (InputStream is = Files.newInputStream(e.file)) {
-                        is.transferTo(os2);
-                    }
-                }
-                Files.delete(e.file);
-                tmppaths.remove(e.file);
+        if (e.crc != 0 && e.csize > 0) {
+            // pre-compressed entry, write directly to output stream
+            writeTo(e, os);
+        } else {
+            try (OutputStream os2 = (e.method == METHOD_STORED) ?
+                    new EntryOutputStreamCRC32(e, os) : new EntryOutputStreamDef(e, os)) {
+                writeTo(e, os2);
             }
         }
         written += e.csize;
@@ -1230,18 +1227,38 @@
         return written;
     }
 
+    private void writeTo(Entry e, OutputStream os) throws IOException {
+        if (e.bytes != null) {
+            os.write(e.bytes, 0, e.bytes.length);
+        } else if (e.file != null) {
+            if (e.type == Entry.NEW || e.type == Entry.FILECH) {
+                try (InputStream is = Files.newInputStream(e.file)) {
+                    is.transferTo(os);
+                }
+            }
+            Files.delete(e.file);
+            tmppaths.remove(e.file);
+        }
+    }
+
     // sync the zip file system, if there is any udpate
     private void sync() throws IOException {
-
+        // check ex-closer
+        if (!exChClosers.isEmpty()) {
+            for (ExistingChannelCloser ecc : exChClosers) {
+                if (ecc.closeAndDeleteIfDone()) {
+                    exChClosers.remove(ecc);
+                }
+            }
+        }
         if (!hasUpdate)
             return;
         Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
-        try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
-        {
+        try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE))) {
             ArrayList<Entry> elist = new ArrayList<>(inodes.size());
             long written = 0;
-            byte[] buf = new byte[8192];
-            Entry e = null;
+            byte[] buf = null;
+            Entry e;
 
             // write loc
             for (IndexNode inode : inodes.values()) {
@@ -1254,11 +1271,13 @@
                             // LOC in new file and simply copy the rest (data and
                             // ext) without enflating/deflating from the old zip
                             // file LOC entry.
+                            if (buf == null)
+                                buf = new byte[8192];
                             written += copyLOCEntry(e, true, os, written, buf);
                         } else {                          // NEW, FILECH or CEN
                             e.locoff = written;
                             written += e.writeLOC(os);    // write loc header
-                            written += writeEntry(e, os, buf);
+                            written += writeEntry(e, os);
                         }
                         elist.add(e);
                     } catch (IOException x) {
@@ -1274,6 +1293,8 @@
                     }
                     e = Entry.readCEN(this, inode);
                     try {
+                        if (buf == null)
+                            buf = new byte[8192];
                         written += copyLOCEntry(e, false, os, written, buf);
                         elist.add(e);
                     } catch (IOException x) {
@@ -1291,9 +1312,23 @@
             end.cenlen = written - end.cenoff;
             end.write(os, written, forceEnd64);
         }
+        if (!streams.isEmpty()) {
+            //
+            // There are outstanding input streams open on existing "ch",
+            // so, don't close the "cha" and delete the "file for now, let
+            // the "ex-channel-closer" to handle them
+            Path path = createTempFileInSameDirectoryAs(zfpath);
+            ExistingChannelCloser ecc = new ExistingChannelCloser(path,
+                                                                  ch,
+                                                                  streams);
+            Files.move(zfpath, path, REPLACE_EXISTING);
+            exChClosers.add(ecc);
+            streams = Collections.synchronizedSet(new HashSet<>());
+        } else {
+            ch.close();
+            Files.delete(zfpath);
+        }
 
-        ch.close();
-        Files.delete(zfpath);
         Files.move(tmpFile, zfpath, REPLACE_EXISTING);
         hasUpdate = false;    // clear
     }
@@ -1351,11 +1386,15 @@
         } else {
             os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
         }
-        return new EntryOutputStream(e, os);
+        if (e.method == METHOD_DEFLATED) {
+            return new DeflatingEntryOutputStream(e, os);
+        } else {
+            return new EntryOutputStream(e, os);
+        }
     }
 
     private class EntryOutputStream extends FilterOutputStream {
-        private Entry e;
+        private final Entry e;
         private long written;
         private boolean isClosed;
 
@@ -1392,13 +1431,56 @@
         }
     }
 
+    // Output stream returned when writing "deflated" entries into memory,
+    // to enable eager (possibly parallel) deflation and reduce memory required.
+    private class DeflatingEntryOutputStream extends DeflaterOutputStream {
+        private final CRC32 crc;
+        private final Entry e;
+        private boolean isClosed;
+
+        DeflatingEntryOutputStream(Entry e, OutputStream os) throws IOException {
+            super(os, getDeflater());
+            this.e = Objects.requireNonNull(e, "Zip entry is null");
+            this.crc = new CRC32();
+        }
+
+        @Override
+        public synchronized void write(int b) throws IOException {
+            super.write(b);
+            crc.update(b);
+        }
+
+        @Override
+        public synchronized void write(byte b[], int off, int len)
+                throws IOException {
+            super.write(b, off, len);
+            crc.update(b, off, len);
+        }
+
+        @Override
+        public synchronized void close() throws IOException {
+            if (isClosed)
+                return;
+            isClosed = true;
+            finish();
+            e.size  = def.getBytesRead();
+            e.csize = def.getBytesWritten();
+            e.crc = crc.getValue();
+            if (out instanceof ByteArrayOutputStream)
+                e.bytes = ((ByteArrayOutputStream)out).toByteArray();
+            super.close();
+            update(e);
+            releaseDeflater(def);
+        }
+    }
+
     // Wrapper output stream class to write out a "stored" entry.
     // (1) this class does not close the underlying out stream when
     //     being closed.
     // (2) no need to be "synchronized", only used by sync()
     private class EntryOutputStreamCRC32 extends FilterOutputStream {
-        private Entry e;
-        private CRC32 crc;
+        private final CRC32 crc;
+        private final Entry e;
         private long written;
         private boolean isClosed;
 
@@ -1438,8 +1520,8 @@
     //     being closed.
     // (2) no need to be "synchronized", only used by sync()
     private class EntryOutputStreamDef extends DeflaterOutputStream {
-        private CRC32 crc;
-        private Entry e;
+        private final CRC32 crc;
+        private final Entry e;
         private boolean isClosed;
 
         EntryOutputStreamDef(Entry e, OutputStream os) throws IOException {
@@ -1471,14 +1553,12 @@
     private InputStream getInputStream(Entry e)
         throws IOException
     {
-        InputStream eis = null;
-
+        InputStream eis;
         if (e.type == Entry.NEW) {
-            // now bytes & file is uncompressed.
             if (e.bytes != null)
-                return new ByteArrayInputStream(e.bytes);
+                eis = new ByteArrayInputStream(e.bytes);
             else if (e.file != null)
-                return Files.newInputStream(e.file);
+                eis = Files.newInputStream(e.file);
             else
                 throw new ZipException("update entry data is missing");
         } else if (e.type == Entry.FILECH) {
@@ -1579,7 +1659,7 @@
                 len = (int) rem;
             }
             // readFullyAt()
-            long n = 0;
+            long n;
             ByteBuffer bb = ByteBuffer.wrap(b);
             bb.position(off);
             bb.limit(off + len);
@@ -1905,7 +1985,7 @@
             this.type = type;
         }
 
-        Entry (Entry e, int type) {
+        Entry(Entry e, int type) {
             name(e.name);
             this.isdir     = e.isdir;
             this.version   = e.version;
@@ -1928,7 +2008,7 @@
             this.type      = type;
         }
 
-        Entry (byte[] name, Path file, int type) {
+        Entry(byte[] name, Path file, int type) {
             this(name, type, false, METHOD_STORED);
             this.file = file;
         }
@@ -2424,6 +2504,36 @@
         }
     }
 
+    private static class ExistingChannelCloser {
+        private final Path path;
+        private final SeekableByteChannel ch;
+        private final Set<InputStream> streams;
+        ExistingChannelCloser(Path path,
+                              SeekableByteChannel ch,
+                              Set<InputStream> streams) {
+            this.path = path;
+            this.ch = ch;
+            this.streams = streams;
+        }
+
+        /**
+         * If there are no more outstanding streams, close the channel and
+         * delete the backing file
+         *
+         * @return true if we're done and closed the backing file,
+         *         otherwise false
+         * @throws IOException
+         */
+        public boolean closeAndDeleteIfDone() throws IOException {
+            if (streams.isEmpty()) {
+                ch.close();
+                Files.delete(path);
+                return true;
+            }
+            return false;
+        }
+    }
+
     // ZIP directory has two issues:
     // (1) ZIP spec does not require the ZIP file to include
     //     directory entry
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, 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
@@ -104,7 +104,7 @@
                 if (filesystems.containsKey(realPath))
                     throw new FileSystemAlreadyExistsException();
             }
-            ZipFileSystem zipfs = null;
+            ZipFileSystem zipfs;
             try {
                 if (env.containsKey("multi-release")) {
                     zipfs = new JarFileSystem(this, path, env);
@@ -131,13 +131,13 @@
         throws IOException
     {
         ensureFile(path);
-         try {
-             ZipFileSystem zipfs;
-             if (env.containsKey("multi-release")) {
-                 zipfs = new JarFileSystem(this, path, env);
-             } else {
-                 zipfs = new ZipFileSystem(this, path, env);
-             }
+        try {
+            ZipFileSystem zipfs;
+            if (env.containsKey("multi-release")) {
+                zipfs = new JarFileSystem(this, path, env);
+            } else {
+                zipfs = new ZipFileSystem(this, path, env);
+            }
             return zipfs;
         } catch (ZipException ze) {
             String pname = path.toString();
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java	Fri May 03 11:28:14 2019 -0700
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java	Fri May 03 14:59:32 2019 -0400
@@ -676,7 +676,7 @@
 
     @Override
     public Iterator<Path> iterator() {
-        return new Iterator<Path>() {
+        return new Iterator<>() {
             private int i = 0;
 
             @Override
@@ -746,8 +746,8 @@
     void setAttribute(String attribute, Object value, LinkOption... options)
         throws IOException
     {
-        String type = null;
-        String attr = null;
+        String type;
+        String attr;
         int colonPos = attribute.indexOf(':');
         if (colonPos == -1) {
             type = "basic";
@@ -772,8 +772,8 @@
         throws IOException
 
     {
-        String view = null;
-        String attrs = null;
+        String view;
+        String attrs;
         int colonPos = attributes.indexOf(':');
         if (colonPos == -1) {
             view = "basic";
--- a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp	Fri May 03 14:59:32 2019 -0400
@@ -22,7 +22,7 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/collectorPolicy.hpp"
+#include "gc/serial/serialArguments.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/flags/flagSetting.hpp"
 #include "runtime/globals_extension.hpp"
@@ -54,32 +54,22 @@
     BinaryExecutor(size_t val1, size_t val2) : param1(val1), param2(val2) { }
   };
 
-  class MinHeapSizeGuard {
-   private:
-    const size_t _stored_min_heap_size;
-   public:
-    MinHeapSizeGuard() : _stored_min_heap_size(Arguments::min_heap_size()) { }
-    ~MinHeapSizeGuard() {
-      Arguments::set_min_heap_size(_stored_min_heap_size);
-    }
-  };
-
   class TestWrapper {
    public:
     static void test(Executor* setter1, Executor* setter2, Executor* checker) {
+      FLAG_GUARD(MinHeapSize);
       FLAG_GUARD(InitialHeapSize);
       FLAG_GUARD(MaxHeapSize);
       FLAG_GUARD(MaxNewSize);
       FLAG_GUARD(MinHeapDeltaBytes);
       FLAG_GUARD(NewSize);
       FLAG_GUARD(OldSize);
-      MinHeapSizeGuard min_heap_size_guard;
 
+      MinHeapSize = 40 * M;
       FLAG_SET_ERGO(size_t, InitialHeapSize, 100 * M);
       FLAG_SET_ERGO(size_t, OldSize, 4 * M);
       FLAG_SET_ERGO(size_t, NewSize, 1 * M);
       FLAG_SET_ERGO(size_t, MaxNewSize, 80 * M);
-      Arguments::set_min_heap_size(40 * M);
 
       ASSERT_NO_FATAL_FAILURE(setter1->execute());
 
@@ -106,27 +96,31 @@
    public:
     CheckYoungMin(size_t param) : UnaryExecutor(param) { }
     void execute() {
-      MarkSweepPolicy msp;
-      msp.initialize_all();
-      ASSERT_LE(msp.min_young_size(), param);
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
+      ASSERT_LE(MinNewSize, param);
     }
   };
 
+  static size_t scale_by_NewRatio_aligned(size_t value, size_t alignment) {
+    // Accessible via friend declaration
+    return GenArguments::scale_by_NewRatio_aligned(value, alignment);
+  }
+
   class CheckScaledYoungInitial : public Executor {
    public:
     void execute() {
       size_t initial_heap_size = InitialHeapSize;
-      MarkSweepPolicy msp;
-      msp.initialize_all();
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
 
       if (InitialHeapSize > initial_heap_size) {
-        // InitialHeapSize was adapted by msp.initialize_all, e.g. due to alignment
+        // InitialHeapSize was adapted by sa.initialize_heap_sizes, e.g. due to alignment
         // caused by 64K page size.
         initial_heap_size = InitialHeapSize;
       }
 
-      size_t expected = msp.scale_by_NewRatio_aligned(initial_heap_size);
-      ASSERT_EQ(expected, msp.initial_young_size());
+      size_t expected = scale_by_NewRatio_aligned(initial_heap_size, GenAlignment);
       ASSERT_EQ(expected, NewSize);
     }
   };
@@ -143,10 +137,10 @@
    public:
     CheckYoungInitial(size_t param) : UnaryExecutor(param) { }
     void execute() {
-      MarkSweepPolicy msp;
-      msp.initialize_all();
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
 
-      ASSERT_EQ(param, msp.initial_young_size());
+      ASSERT_EQ(param, NewSize);
     }
   };
 
@@ -162,7 +156,7 @@
    public:
     SetMaxNewSizeCmd(size_t param1, size_t param2) : BinaryExecutor(param1, param2) { }
     void execute() {
-      size_t heap_alignment = CollectorPolicy::compute_heap_alignment();
+      size_t heap_alignment = GCArguments::compute_heap_alignment();
       size_t new_size_value = align_up(MaxHeapSize, heap_alignment)
               - param1 + param2;
       FLAG_SET_CMDLINE(size_t, MaxNewSize, new_size_value);
@@ -173,24 +167,24 @@
    public:
     CheckOldMin(size_t param) : UnaryExecutor(param) { }
     void execute() {
-      MarkSweepPolicy msp;
-      msp.initialize_all();
-      ASSERT_LE(msp.min_old_size(), param);
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
+      ASSERT_LE(MinOldSize, param);
     }
   };
 
   class CheckOldInitial : public Executor {
    public:
     void execute() {
-      size_t heap_alignment = CollectorPolicy::compute_heap_alignment();
+      size_t heap_alignment = GCArguments::compute_heap_alignment();
 
-      MarkSweepPolicy msp;
-      msp.initialize_all();
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
 
       size_t expected_old_initial = align_up(InitialHeapSize, heap_alignment)
               - MaxNewSize;
 
-      ASSERT_EQ(expected_old_initial, msp.initial_old_size());
+      ASSERT_EQ(expected_old_initial, OldSize);
     }
   };
 
@@ -198,17 +192,17 @@
    public:
     CheckOldInitialMaxNewSize(size_t param1, size_t param2) : BinaryExecutor(param1, param2) { }
     void execute() {
-      size_t heap_alignment = CollectorPolicy::compute_heap_alignment();
+      size_t heap_alignment = GCArguments::compute_heap_alignment();
       size_t new_size_value = align_up(MaxHeapSize, heap_alignment)
               - param1 + param2;
 
-      MarkSweepPolicy msp;
-      msp.initialize_all();
+      SerialArguments sa;
+      sa.initialize_heap_sizes();
 
       size_t expected_old_initial = align_up(MaxHeapSize, heap_alignment)
               - new_size_value;
 
-      ASSERT_EQ(expected_old_initial, msp.initial_old_size());
+      ASSERT_EQ(expected_old_initial, OldSize);
     }
   };
 };
--- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp	Fri May 03 14:59:32 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
@@ -138,7 +138,7 @@
 }
 
 static bool process_deferred_updates(OopStorage& storage) {
-  MutexLockerEx ml(TestAccess::allocation_mutex(storage), Mutex::_no_safepoint_check_flag);
+  MutexLocker ml(TestAccess::allocation_mutex(storage), Mutex::_no_safepoint_check_flag);
   bool result = false;
   while (TestAccess::reduce_deferred_updates(storage)) {
     result = true;
--- a/test/hotspot/gtest/gc/z/test_zAddress.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/gc/z/test_zAddress.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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,9 +30,8 @@
 protected:
   static void is_good_bit(uintptr_t bit_mask) {
     // Setup
-    uintptr_t mask_before = ZAddressGoodMask;
-
-    ZAddressMasks::set_good_mask(bit_mask);
+    ZAddress::initialize();
+    ZAddress::set_good_mask(bit_mask);
 
     // Test that a pointer with only the given bit is considered good.
     EXPECT_EQ(ZAddress::is_good(ZAddressMetadataMarked0),  (bit_mask == ZAddressMetadataMarked0));
@@ -46,16 +45,12 @@
 
     // Test that null is not considered good.
     EXPECT_FALSE(ZAddress::is_good(0));
-
-    // Teardown
-    ZAddressMasks::set_good_mask(mask_before);
   }
 
   static void is_good_or_null_bit(uintptr_t bit_mask) {
     // Setup
-    uintptr_t mask_before = ZAddressGoodMask;
-
-    ZAddressMasks::set_good_mask(bit_mask);
+    ZAddress::initialize();
+    ZAddress::set_good_mask(bit_mask);
 
     // Test that a pointer with only the given bit is considered good.
     EXPECT_EQ(ZAddress::is_good_or_null(ZAddressMetadataMarked0),  (bit_mask == ZAddressMetadataMarked0));
@@ -69,15 +64,12 @@
 
     // Test that null is considered good_or_null.
     EXPECT_TRUE(ZAddress::is_good_or_null(0));
-
-    // Teardown
-    ZAddressMasks::set_good_mask(mask_before);
   }
 
   static void finalizable() {
     // Setup
-    ZAddressMasks::initialize();
-    ZAddressMasks::flip_to_marked();
+    ZAddress::initialize();
+    ZAddress::flip_to_marked();
 
     // Test that a normal good pointer is good and weak good, but not finalizable
     const uintptr_t addr1 = ZAddress::good(1);
@@ -100,7 +92,7 @@
     EXPECT_FALSE(ZAddress::is_good_or_null(addr2));
 
     // Flip to remapped and test that it's no longer weak good
-    ZAddressMasks::flip_to_remapped();
+    ZAddress::flip_to_remapped();
     EXPECT_TRUE(ZAddress::is_finalizable(addr2));
     EXPECT_TRUE(ZAddress::is_marked(addr2));
     EXPECT_FALSE(ZAddress::is_remapped(addr2));
--- a/test/hotspot/gtest/memory/test_is_metaspace_obj.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/memory/test_is_metaspace_obj.cpp	Fri May 03 14:59:32 2019 -0400
@@ -53,7 +53,7 @@
   void do_test(Metaspace::MetadataType mdType) {
     _lock = new Mutex(Monitor::native, "gtest-IsMetaspaceObjTest-lock", false, Monitor::_safepoint_check_never);
     {
-      MutexLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(_lock, Mutex::_no_safepoint_check_flag);
       _ms = new ClassLoaderMetaspace(_lock, Metaspace::StandardMetaspaceType);
     }
 
--- a/test/hotspot/gtest/memory/test_metaspace.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/memory/test_metaspace.cpp	Fri May 03 14:59:32 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
@@ -77,7 +77,7 @@
 
 TEST_VM(MetaspaceUtils, virtual_space_list_large_chunk) {
   VirtualSpaceList* vs_list = new VirtualSpaceList(os::vm_allocation_granularity());
-  MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
+  MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
   // A size larger than VirtualSpaceSize (256k) and add one page to make it _not_ be
   // vm_allocation_granularity aligned on Windows.
   size_t large_size = (size_t)(2*256*K + (os::vm_page_size() / BytesPerWord));
--- a/test/hotspot/gtest/memory/test_metaspace_allocation.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/memory/test_metaspace_allocation.cpp	Fri May 03 14:59:32 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.
  * Copyright (c) 2018, SAP.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -108,7 +108,7 @@
     {
       // Pull lock during space creation, since this is what happens in the VM too
       // (see ClassLoaderData::metaspace_non_null(), which we mimick here).
-      MutexLockerEx ml(_spaces[i].lock,  Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(_spaces[i].lock,  Mutex::_no_safepoint_check_flag);
       _spaces[i].space = new ClassLoaderMetaspace(_spaces[i].lock, msType);
     }
     _spaces[i].allocated = 0;
--- a/test/hotspot/gtest/runtime/test_threads.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/runtime/test_threads.cpp	Fri May 03 14:59:32 2019 -0400
@@ -120,7 +120,7 @@
 public:
   void doit() {
     // Prevent changes to the NJT list while we're conducting our test.
-    MutexLockerEx ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
+    MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
 
     _thread_claim_token = max_uintx - 1;
 
--- a/test/hotspot/gtest/threadHelper.inline.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/gtest/threadHelper.inline.hpp	Fri May 03 14:59:32 2019 -0400
@@ -105,7 +105,7 @@
       Threads::add(this);
     }
     {
-      MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
+      MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     }
   }
 
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Fri May 03 14:59:32 2019 -0400
@@ -221,6 +221,18 @@
 compiler/arguments/TestScavengeRootsInCode.java         8207267   generic-all
 compiler/loopopts/TestOverunrolling.java                8207267   generic-all
 
+runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java        8222582 generic-all
+
+vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java 8220032 generic-all
+vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java        8220032 generic-all
+
+vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java 8222422 generic-all
+vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java 8222422 generic-all
+
+runtime/exceptionMsgs/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsExceptionTest.java 8222292 generic-all
+
+serviceability/dcmd/compiler/CodelistTest.java 8220449 generic-all
+
 # Graal unit tests
 org.graalvm.compiler.core.test.CheckGraalInvariants                              8205081
 org.graalvm.compiler.core.test.OptionsVerifierTest                               8205081
--- a/test/hotspot/jtreg/ProblemList.txt	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/ProblemList.txt	Fri May 03 14:59:32 2019 -0400
@@ -159,7 +159,7 @@
 vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java 8065773 generic-all
 vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java 8065773 generic-all
 
-vmTestbase/nsk/jdb/eval/eval001/eval001.java 8221503 generic-all
+vmTestbase/nsk/jdb/eval/eval001/eval001.java 8212117 generic-all
 
 vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all
 vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all
--- a/test/hotspot/jtreg/TEST.groups	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/TEST.groups	Fri May 03 14:59:32 2019 -0400
@@ -438,7 +438,8 @@
 
 # JVMTI tests
 vmTestbase_nsk_jvmti = \
-  vmTestbase/nsk/jvmti
+  vmTestbase/nsk/jvmti \
+  vmTestbase/nsk/share/ExceptionCheckingJniEnv
 
 # JDWP tests
 vmTestbase_nsk_jdwp = \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/c2/Test8202414.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019, Huawei Technologies Co. Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8202414
+ * @summary Unsafe write after primitive array creation may result in array length change
+ * @requires (os.arch != "sparc") & (os.arch != "sparcv9")
+ * @run main/othervm compiler.c2.Test8202414
+ */
+
+package compiler.c2;
+
+import sun.misc.Unsafe;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class Test8202414 {
+
+    public static void main(String[] args) {
+        System.err.close();
+        int count = 0;
+        while (count++ < 120000) {
+          test();
+        }
+    }
+
+    public static void test() {
+        byte[] newBufb = serByte(397);
+        short[] newBufs = serShort(397);
+        int[] newBufi = serInt(397);
+        long[] newBufl = serLong(397);
+        if (newBufb.length != 397 || newBufs.length != 397
+            || newBufi.length != 397 || newBufl.length != 397) {
+            System.out.println("array length internal error");
+            throw new RuntimeException("Test failed");
+        }
+
+    }
+
+    public static byte[] serByte(int bufLen) {
+        byte[] buf = new byte[bufLen];
+        THE_UNSAFE.putByte(buf, BYTE_ARRAY_BASE_OFFSET + 1, (byte) buf.length);
+        System.err.println("ref " + buf);
+        return buf;
+    }
+
+    public static short[] serShort(int bufLen) {
+        short[] buf = new short[bufLen];
+        THE_UNSAFE.putShort(buf, SHORT_ARRAY_BASE_OFFSET + 1, (short) buf.length);
+        System.err.println("ref " + buf);
+        return buf;
+    }
+
+    public static int[] serInt(int bufLen) {
+        int[] buf = new int[bufLen];
+        THE_UNSAFE.putInt(buf, INT_ARRAY_BASE_OFFSET + 1, buf.length);
+        System.err.println("ref " + buf);
+        return buf;
+    }
+
+    public static long[] serLong(int bufLen) {
+        long[] buf = new long[bufLen];
+        THE_UNSAFE.putLong(buf, LONG_ARRAY_BASE_OFFSET + 1, buf.length);
+        System.err.println("ref " + buf);
+        return buf;
+    }
+
+    /* Unsafe fields and initialization
+     */
+    static final Unsafe THE_UNSAFE;
+    static final long BYTE_ARRAY_BASE_OFFSET;
+    static final long SHORT_ARRAY_BASE_OFFSET;
+    static final long INT_ARRAY_BASE_OFFSET;
+    static final long LONG_ARRAY_BASE_OFFSET;
+    static {
+        THE_UNSAFE = (Unsafe) AccessController.doPrivileged (
+            new PrivilegedAction<Object>() {
+                @Override
+                public Object run() {
+                    try {
+                        Field f = Unsafe.class.getDeclaredField("theUnsafe");
+                        f.setAccessible(true);
+                        return f.get(null);
+                    } catch (NoSuchFieldException | IllegalAccessException e) {
+                        throw new Error();
+                    }
+                }
+            }
+        );
+        BYTE_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(byte[].class);
+        SHORT_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(short[].class);
+        INT_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(int[].class);
+        LONG_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(long[].class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/c2/TestIfWithDeadRegion.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,57 @@
+/*
+ * 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 8219807
+ * @summary Test IfNode::up_one_dom() with dead regions.
+ * @compile -XDstringConcat=inline TestIfWithDeadRegion.java
+ * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestIfWithDeadRegion::test
+ *                   compiler.c2.TestIfWithDeadRegion
+ */
+
+package compiler.c2;
+
+import java.util.function.Supplier;
+
+public class TestIfWithDeadRegion {
+
+    static String msg;
+
+    static String getString(String s, int i) {
+        String current = s + String.valueOf(i);
+        System.nanoTime();
+        return current;
+    }
+
+    static void test(Supplier<String> supplier) {
+        msg = supplier.get();
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 20_000; ++i) {
+            test(() -> getString("Test1", 42));
+            test(() -> getString("Test2", 42));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/HotspotAarch64Test.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * @summary
+ * @requires vm.opt.final.EnableJVMCI == true
+ *
+ * @modules jdk.internal.vm.compiler
+ *
+ * @library /test/lib /compiler/graalunit /
+ *
+ * @build compiler.graalunit.common.GraalUnitTestLauncher
+ *
+ * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
+ *
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.hotspot.aarch64.test -exclude ExcludeList.txt
+ */
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt	Fri May 03 14:59:32 2019 -0400
@@ -10,6 +10,7 @@
 EA9           org.graalvm.compiler.core.jdk9.test.ea
 Debug         org.graalvm.compiler.debug.test
 Graph         org.graalvm.compiler.graph.test      @requires vm.graal.enabled
+HotspotAarch64 org.graalvm.compiler.hotspot.aarch64.test
 HotspotAmd64  org.graalvm.compiler.hotspot.amd64.test
 HotspotJdk9   org.graalvm.compiler.hotspot.jdk9.test
 HotspotSparc  org.graalvm.compiler.hotspot.sparc.test @requires vm.simpleArch == "sparcv9"
--- a/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -84,7 +84,7 @@
         NO_JVMCI {
             @Override
             public Class<? extends Throwable> getExpectedException() {
-                return InternalError.class;
+                return Error.class;
             }
         },
         ALL_PERM {
@@ -172,12 +172,8 @@
                 }
             };
             Utils.runAndCheckException(() -> {
-                try {
-                    // CompilerToVM::<cinit> provokes CompilerToVM::<init>
-                    Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper");
-                } catch (ClassNotFoundException e) {
-                    throw new Error("TESTBUG : " + e, e);
-                }
+                // CompilerToVM::<cinit> provokes CompilerToVM::<init>
+                Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper");
             }, exceptionCheck);
         }
 
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Fri May 03 14:59:32 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,7 +28,10 @@
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.code.stack.InspectedFrameVisitor;
 import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.runtime.JVMCI;
 import java.lang.reflect.Executable;
 
 /**
@@ -36,6 +39,7 @@
  */
 public class CompilerToVMHelper {
     public static final CompilerToVM CTVM = new CompilerToVM();
+    private static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
 
     public static byte[] getBytecode(HotSpotResolvedJavaMethod method) {
         return CTVM.getBytecode((HotSpotResolvedJavaMethodImpl)method);
@@ -80,8 +84,12 @@
     }
 
     public static HotSpotResolvedObjectType lookupType(String name,
-            Class<?> accessingClass, boolean resolve) throws ClassNotFoundException {
-        return CTVM.lookupType(name, accessingClass, resolve);
+            Class<?> accessClass, boolean resolve) throws ClassNotFoundException {
+        if (accessClass == null) {
+            throw new NullPointerException();
+        }
+        HotSpotResolvedObjectTypeImpl accessingClass = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType(accessClass);
+        return (HotSpotResolvedObjectType) CTVM.lookupType(name, accessingClass, resolve);
     }
 
     public static HotSpotResolvedObjectType lookupTypeHelper(String name,
@@ -94,11 +102,13 @@
     }
 
     public static Object resolveConstantInPool(ConstantPool constantPool, int cpi) {
-        return CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        DirectHotSpotObjectConstantImpl obj = (DirectHotSpotObjectConstantImpl) CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        return obj.object;
     }
 
     public static Object resolvePossiblyCachedConstantInPool(ConstantPool constantPool, int cpi) {
-        return CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        DirectHotSpotObjectConstantImpl obj = (DirectHotSpotObjectConstantImpl) CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        return obj.object;
     }
 
     public static int lookupNameAndTypeRefIndexInPool(ConstantPool constantPool, int cpi) {
@@ -158,7 +168,16 @@
 
     public static int installCode(TargetDescription target,
             HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog) {
-        return CTVM.installCode(target, compiledCode, code, speculationLog);
+        byte[] speculations;
+        long failedSpeculationsAddress;
+        if (speculationLog != null) {
+            speculations = speculationLog.getFlattenedSpeculations(true);
+            failedSpeculationsAddress = speculationLog.getFailedSpeculationsAddress();
+        } else {
+            speculations = new byte[0];
+            failedSpeculationsAddress = 0L;
+        }
+        return CTVM.installCode(target, compiledCode, code, failedSpeculationsAddress, speculations);
     }
 
     public static int getMetadata(TargetDescription target,
@@ -208,9 +227,9 @@
         return CTVM.getStackTraceElement((HotSpotResolvedJavaMethodImpl)method, bci);
     }
 
-    public static Object executeInstalledCode(Object[] args,
-            InstalledCode installedCode) throws InvalidInstalledCodeException {
-        return CTVM.executeInstalledCode(args, installedCode);
+    public static Object executeHotSpotNmethod(Object[] args,
+            HotSpotNmethod nmethodMirror) throws InvalidInstalledCodeException {
+        return CTVM.executeHotSpotNmethod(args, nmethodMirror);
     }
 
     public static long[] getLineNumberTable(HotSpotResolvedJavaMethod method) {
@@ -233,8 +252,8 @@
         CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static void invalidateInstalledCode(InstalledCode installedCode) {
-        CTVM.invalidateInstalledCode(installedCode);
+    public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror) {
+        CTVM.invalidateHotSpotNmethod(nmethodMirror);
     }
 
     public static long[] collectCounters() {
@@ -289,33 +308,33 @@
         CTVM.flushDebugOutput();
     }
 
-    public static HotSpotResolvedJavaMethod getResolvedJavaMethod(Object base,
+    public static HotSpotResolvedJavaMethod getResolvedJavaMethod(HotSpotObjectConstantImpl base,
             long displacement) {
         return CTVM.getResolvedJavaMethod(base, displacement);
     }
 
-    public static HotSpotConstantPool getConstantPool(Object object) {
+    public static HotSpotConstantPool getConstantPool(MetaspaceObject object) {
         return CTVM.getConstantPool(object);
     }
 
-    public static HotSpotResolvedObjectType getResolvedJavaType(Object base,
+    public static HotSpotResolvedObjectType getResolvedJavaType(MetaspaceObject base,
             long displacement, boolean compressed) {
         return CTVM.getResolvedJavaType(base, displacement, compressed);
     }
 
     public static long getMetaspacePointer(Object o) {
-        return ((MetaspaceWrapperObject) o).getMetaspacePointer();
+        return ((MetaspaceObject) o).getMetaspacePointer();
     }
 
     public static Class<?> CompilerToVMClass() {
         return CompilerToVM.class;
     }
 
-    public static Class<?> getMirror(HotSpotResolvedObjectType type) {
-        return ((HotSpotResolvedJavaType) type).mirror();
+    public static JavaConstant getJavaMirror(HotSpotResolvedObjectType type) {
+        return ((HotSpotResolvedJavaType) type).getJavaMirror();
     }
 
     public static HotSpotResolvedObjectType fromObjectClass(Class<?> theClass) {
-        return HotSpotResolvedObjectTypeImpl.fromObjectClass(theClass);
+          return (HotSpotResolvedObjectType) metaAccess.lookupJavaType(theClass);
     }
 }
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java	Fri May 03 14:59:32 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
@@ -26,4 +26,4 @@
 /**
  * A public available version of MetaspaceWrapperObject interface.
  */
-public interface PublicMetaspaceWrapperObject extends MetaspaceWrapperObject { }
+public interface PublicMetaspaceWrapperObject extends MetaspaceHandleObject { }
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Fri May 03 14:59:32 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
@@ -69,7 +69,7 @@
 
     private void checkNull() {
         Utils.runAndCheckException(
-                () -> CompilerToVMHelper.disassembleCodeBlob(null),
+                () -> { CompilerToVMHelper.disassembleCodeBlob(null); },
                 NullPointerException.class);
     }
 
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Fri May 03 14:59:32 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 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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 @@
  * @requires vm.jvmci
  * @library / /test/lib
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc:+open
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open
  *
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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 @@
  * @requires vm.jvmci
  * @library / /test/lib
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  *          jdk.internal.vm.ci/jdk.vm.ci.meta
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
  * @bug 8136421
  * @requires vm.jvmci
  * @library /test/lib /
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc:open
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:open
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
--- a/test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -32,7 +32,9 @@
 import jdk.vm.ci.code.site.Site;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
+import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.meta.Assumptions.Assumption;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PlatformKind;
@@ -50,7 +52,7 @@
     protected final MetaAccessProvider metaAccess;
     protected final HotSpotConstantReflectionProvider constantReflection;
 
-    protected final ResolvedJavaMethod dummyMethod;
+    protected final HotSpotResolvedJavaMethod dummyMethod;
 
     public static void dummyMethod() {
     }
@@ -69,12 +71,13 @@
             Assert.fail();
         }
 
-        dummyMethod = metaAccess.lookupJavaMethod(method);
+        dummyMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
     }
 
     protected void installEmptyCode(Site[] sites, Assumption[] assumptions, Comment[] comments, int dataSectionAlignment, DataPatch[] dataSectionPatches, StackSlot deoptRescueSlot) {
-        HotSpotCompiledCode code = new HotSpotCompiledCode("dummyMethod", new byte[0], 0, sites, assumptions, new ResolvedJavaMethod[]{dummyMethod}, comments, new byte[8], dataSectionAlignment,
-                        dataSectionPatches, false, 0, deoptRescueSlot);
+        HotSpotCompiledCode code = new HotSpotCompiledNmethod("dummyMethod", new byte[0], 0, sites, assumptions, new ResolvedJavaMethod[]{dummyMethod}, comments, new byte[8], dataSectionAlignment,
+                        dataSectionPatches, false, 0, deoptRescueSlot,
+                        dummyMethod, 0, 1, 0L, false);
         codeCache.addCode(dummyMethod, code, null, null);
     }
 
--- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -74,6 +74,7 @@
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
+import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
@@ -118,10 +119,11 @@
         }
         HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(SimpleClass.class, testMethod);
-        HotSpotCompiledCode compiledCode = new HotSpotCompiledCode(METHOD_NAME,
+        HotSpotCompiledCode compiledCode = new HotSpotCompiledNmethod(METHOD_NAME,
                 new byte[0], 0, new Site[0], new Assumption[0],
                 new ResolvedJavaMethod[]{method}, new Comment[0], new byte[0],
-                16, new DataPatch[0], false, 0, null);
+                16, new DataPatch[0], false, 0, null,
+                method, 0, 1, 0L, false);
         codeCache.installCode(method, compiledCode, /* installedCode = */ null,
                 /* speculationLog = */ null, /* isDefault = */ false);
         Asserts.assertEQ(gotInstallNotification, 1,
--- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java	Fri May 03 14:59:32 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
@@ -34,7 +34,7 @@
     public static void main(String args[]) {
         try {
             HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
-        } catch (InternalError e) {
+        } catch (Error e) {
             System.out.println(GOT_INTERNAL_ERROR);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot.test;
+
+import java.util.function.Supplier;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+import jdk.vm.ci.hotspot.HotSpotSpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+
+public class TestHotSpotSpeculationLog {
+
+    static final class DummyReason implements SpeculationLog.SpeculationReason {
+
+        final String name;
+        private SpeculationReasonEncoding cachedEncoding;
+
+        DummyReason(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            SpeculationReasonEncoding encoding = cachedEncoding;
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                encoding.addString(name);
+            }
+            cachedEncoding = encoding;
+            return encoding;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof DummyReason) {
+                DummyReason that = (DummyReason) obj;
+                return this.name.equals(that.name);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    @Test
+    public synchronized void testFailedSpeculations() {
+        HotSpotSpeculationLog log = new HotSpotSpeculationLog();
+        DummyReason reason1 = new DummyReason("dummy1");
+        DummyReason reason2 = new DummyReason("dummy2");
+        Assert.assertTrue(log.maySpeculate(reason1));
+        Assert.assertTrue(log.maySpeculate(reason2));
+
+        SpeculationLog.Speculation s1 = log.speculate(reason1);
+        SpeculationLog.Speculation s2 = log.speculate(reason2);
+
+        boolean added = log.addFailedSpeculation(s1);
+        Assume.assumeTrue(added);
+        log.collectFailedSpeculations();
+        Assert.assertFalse(log.maySpeculate(reason1));
+        Assert.assertTrue(log.maySpeculate(reason2));
+
+        added = log.addFailedSpeculation(s2);
+        Assume.assumeTrue(added);
+        log.collectFailedSpeculations();
+        Assume.assumeTrue(added);
+        Assert.assertFalse(log.maySpeculate(reason1));
+        Assert.assertFalse(log.toString(), log.maySpeculate(reason2));
+    }
+}
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Fri May 03 14:59:32 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
@@ -25,6 +25,7 @@
  * @test
  * @requires vm.jvmci
  * @library ../../../../../
+ * @ignore Not supported JVMCI API
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Fri May 03 14:59:32 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
@@ -25,6 +25,7 @@
  * @test
  * @requires vm.jvmci
  * @library ../../../../../
+ * @ignore Not supported JVMCI API
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java	Fri May 03 14:59:32 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
@@ -24,24 +24,107 @@
  */
 package jdk.vm.ci.runtime.test;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Supplier;
+
 import org.junit.Assert;
 import org.junit.Test;
 
+import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+import jdk.vm.ci.runtime.JVMCI;
 
 public class TestSpeculationLog extends MethodUniverse {
 
-    static class Dummy implements SpeculationLog.SpeculationReason {
+    static final class Dummy implements SpeculationLog.SpeculationReason {
+
+        final int[] ints = {Integer.MIN_VALUE, -42, -1, 0, 1, 42, Integer.MAX_VALUE};
+        final long[] longs = {Long.MIN_VALUE, -42, -1, 0, 1, 42, Long.MAX_VALUE};
+        final String[] strings = {null, "non-empty string", ""};
+        final Collection<ResolvedJavaMethod> methods = new ArrayList<>(MethodUniverse.methods.values()).subList(0, 10);
+        final Collection<ResolvedJavaMethod> constructors = new ArrayList<>(MethodUniverse.constructors.values()).subList(0, 10);
+        final Collection<ResolvedJavaType> types = new ArrayList<>(TypeUniverse.javaTypes).subList(0, 10);
+
+        private final boolean useCache;
+        private SpeculationReasonEncoding cachedEncoding;
+
+        Dummy(boolean useCache) {
+            this.useCache = useCache;
+        }
 
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            SpeculationReasonEncoding encoding = cachedEncoding;
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                for (int i : ints) {
+                    encoding.addInt(i);
+                }
+                for (long l : longs) {
+                    encoding.addLong(l);
+                }
+                for (String s : strings) {
+                    encoding.addString(s);
+                }
+                for (ResolvedJavaMethod m : methods) {
+                    encoding.addMethod(m);
+                }
+                for (ResolvedJavaMethod c : constructors) {
+                    encoding.addMethod(c);
+                }
+                for (ResolvedJavaType t : types) {
+                    encoding.addType(t);
+                }
+                encoding.addMethod(null);
+                encoding.addType(null);
+            }
+            if (useCache) {
+                cachedEncoding = encoding;
+            }
+            return encoding;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Dummy) {
+                Dummy that = (Dummy) obj;
+                return Arrays.equals(this.ints, that.ints) &&
+                                Arrays.equals(this.longs, that.longs) &&
+                                Arrays.equals(this.strings, that.strings) &&
+                                this.methods.equals(that.methods) &&
+                                this.constructors.equals(that.constructors) &&
+                                this.types.equals(that.types);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * Arrays.hashCode(ints) ^
+                            Arrays.hashCode(longs) ^
+                            Arrays.hashCode(strings) ^
+                            methods.hashCode() ^
+                            constructors.hashCode() ^
+                            types.hashCode();
+        }
     }
 
     @Test
-    public void testSpeculationIdentity() {
-        Dummy spec = new Dummy();
-        SpeculationLog log = methods.entrySet().iterator().next().getValue().getSpeculationLog();
-        SpeculationLog.Speculation s1 = log.speculate(spec);
-        SpeculationLog.Speculation s2 = log.speculate(spec);
+    public synchronized void testSpeculationIdentity() {
+        CodeCacheProvider codeCache = JVMCI.getRuntime().getHostJVMCIBackend().getCodeCache();
+        SpeculationLog log = codeCache.createSpeculationLog();
+        Dummy spec1 = new Dummy(true);
+        Dummy spec2 = new Dummy(false);
+        Assert.assertTrue(log.maySpeculate(spec1));
+        Assert.assertTrue(log.maySpeculate(spec2));
+        SpeculationLog.Speculation s1 = log.speculate(spec1);
+        SpeculationLog.Speculation s2 = log.speculate(spec2);
         Assert.assertTrue("Speculation should maintain identity", s1.equals(s2));
         JavaConstant e1 = metaAccess.encodeSpeculation(s1);
         JavaConstant e2 = metaAccess.encodeSpeculation(s2);
--- a/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java	Fri May 03 14:59:32 2019 -0400
@@ -42,7 +42,8 @@
     public static void main(String args[]) throws Exception {
         if (args.length == 0) {
             // Spawn new VM instance to execute test
-            String[] flags = {"-XX:-BytecodeVerificationRemote",
+            String[] flags = {"-XX:+UnlockDiagnosticVMOptions",
+                              "-XX:-BytecodeVerificationRemote",
                               "-XX:-BytecodeVerificationLocal",
                               "-XX:-TieredCompilation",
                               "-XX:CompileCommand=dontinline,compiler/linkage/OSRWithBadOperandStack.m*",
--- a/test/hotspot/jtreg/containers/docker/JfrNetwork.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/containers/docker/JfrNetwork.java	Fri May 03 14:59:32 2019 -0400
@@ -25,9 +25,11 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ServerSocket;
+import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.List;
 import jdk.jfr.Recording;
 import jdk.jfr.consumer.RecordedEvent;
@@ -81,15 +83,33 @@
         assertTrue(!events.isEmpty(), "No recorded network events");
         RecordedEvent e = events.get(0);
         log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host"));
-        verifyIpAddress(e.getString("address"));
+
+        // compare IP addresses
+        boolean matchFound = false;
+        InetAddress reportedByJfr = InetAddress.getByName(e.getString("address"));
+        for (InetAddress ip : getLocalIp()) {
+            if (ip.equals(reportedByJfr)) {
+                matchFound = true;
+                break;
+            }
+        }
+        assertTrue(matchFound, "IP address match not found");
     }
 
-    private static void verifyIpAddress(String eventIp) throws Exception {
-        ProcessBuilder pb = new ProcessBuilder("hostname", "--ip-address");
-        OutputAnalyzer out = new OutputAnalyzer(pb.start());
-        out.shouldHaveExitValue(0);
-        log("hostname --ip-address returned: " + out.getOutput());
-        out.shouldContain(eventIp);
+    private static List<InetAddress> getLocalIp() throws Exception {
+        List<InetAddress> addrs = new ArrayList<>();
+        InetAddress localHost = InetAddress.getLocalHost();
+        if (!localHost.isLoopbackAddress()) {
+            addrs.add(localHost);
+        }
+
+        log("getLocalIp() returning:");
+        for (InetAddress addr : addrs) {
+            log(addr.getHostName());
+            log(addr.getHostAddress());
+        }
+
+        return addrs;
     }
 
     private static void log(String msg) {
--- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java	Fri May 03 14:59:32 2019 -0400
@@ -36,6 +36,7 @@
  * @build JfrReporter
  * @run driver TestJFREvents
  */
+import java.util.List;
 import jdk.test.lib.containers.docker.Common;
 import jdk.test.lib.containers.docker.DockerRunOptions;
 import jdk.test.lib.containers.docker.DockerTestUtils;
@@ -46,6 +47,8 @@
 
 public class TestJFREvents {
     private static final String imageName = Common.imageName("jfr-events");
+    private static final String TEST_ENV_VARIABLE = "UNIQUE_VARIABLE_ABC592903XYZ";
+    private static final String TEST_ENV_VALUE = "unique_value_abc592903xyz";
     private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
 
     public static void main(String[] args) throws Exception {
@@ -119,26 +122,29 @@
     }
 
 
-    // JTReg always defines the environment variable JAVA_MAIN_CLASS_<SOME_NUMBER>.
-    // This variable fits well for use in this test, since it is rather unique.
-    private static String getTestEnvironmentVariable() throws Exception {
-        for (String key : System.getenv().keySet()) {
-            if (key.startsWith("JAVA_MAIN_CLASS")) {
-                return key;
-            }
-        }
-        throw new RuntimeException("JAVA_MAIN_CLASS_* is not defined");
-    }
-
-
     private static void testEnvironmentVariables() throws Exception {
         Common.logNewTestCase("EnvironmentVariables");
 
-        DockerTestUtils.dockerRunJava(
+        List<String> cmd = DockerTestUtils.buildJavaCommand(
                                       commonDockerOpts()
-                                      .addClassOptions("jdk.InitialEnvironmentVariable"))
-            .shouldHaveExitValue(0)
+                                      .addClassOptions("jdk.InitialEnvironmentVariable"));
+
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        // Container has JAVA_HOME defined via the Dockerfile; make sure
+        // it is reported by JFR event.
+        // Environment variable set in host system should not be visible inside a container,
+        // and should not be reported by JFR.
+        pb.environment().put(TEST_ENV_VARIABLE, TEST_ENV_VALUE);
+
+        System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb));
+        OutputAnalyzer out = new OutputAnalyzer(pb.start());
+        System.out.println("[STDERR]\n" + out.getStderr());
+        System.out.println("[STDOUT]\n" + out.getStdout());
+
+        out.shouldHaveExitValue(0)
             .shouldContain("key = JAVA_HOME")
-            .shouldNotContain(getTestEnvironmentVariable());
+            .shouldContain("value = /jdk")
+            .shouldNotContain(TEST_ENV_VARIABLE)
+            .shouldNotContain(TEST_ENV_VALUE);
     }
 }
--- a/test/hotspot/jtreg/gc/TestAgeOutput.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestAgeOutput.java	Fri May 03 14:59:32 2019 -0400
@@ -24,16 +24,27 @@
 package gc;
 
 /*
- * @test TestAgeOutput
+ * @test TestAgeOutputSerial
  * @bug 8164936
- * @summary Check that collectors using age table based aging print an age table even for the first garbage collection
  * @key gc
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -XX:+UseSerialGC gc.TestAgeOutput UseSerialGC
+ */
+
+/*
+ * @test TestAgeOutputG1
+ * @bug 8164936
+ * @summary Check that collectors using age table based aging print an age table even for the first garbage collection
+ * @key gc
+ * @requires vm.gc.G1
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -XX:+UseG1GC gc.TestAgeOutput UseG1GC
  */
 
@@ -42,7 +53,7 @@
  * @bug 8164936
  * @key gc
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
  * @build sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java	Fri May 03 14:59:32 2019 -0400
@@ -27,9 +27,9 @@
 import gc.testlibrary.PerfCounters;
 
 
-/* @test TestGenerationPerfCounter
+/* @test TestGenerationPerfCounterSerial
  * @bug 8080345
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
  * @library /test/lib /
  * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs.
  * @modules java.base/jdk.internal.misc
@@ -37,14 +37,36 @@
  *          java.management/sun.management
  *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseSerialGC gc.TestGenerationPerfCounter
+ */
+
+/* @test TestGenerationPerfCounterParallel
+ * @bug 8080345
+ * @requires vm.gc.Parallel
+ * @library /test/lib /
+ * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseParallelGC gc.TestGenerationPerfCounter
+ */
+
+/* @test TestGenerationPerfCounterG1
+ * @bug 8080345
+ * @requires vm.gc.G1
+ * @library /test/lib /
+ * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseG1GC gc.TestGenerationPerfCounter
  */
 
 /* @test TestGenerationPerfCounterCMS
  * @bug 8080345
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib /
  * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs.
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/TestHumongousReferenceObject.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestHumongousReferenceObject.java	Fri May 03 14:59:32 2019 -0400
@@ -26,12 +26,20 @@
 import jdk.internal.vm.annotation.Contended;
 
 /*
- * @test
- * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries on G1, with references in them works.
- * @requires vm.gc == "null"
+ * @test TestHumongousReferenceObjectParallel
+ * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries, with references in them works.
+ * @requires vm.gc.Parallel
  * @bug 8151499 8153734
  * @modules java.base/jdk.internal.vm.annotation
  * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 gc.TestHumongousReferenceObject
+ */
+
+/*
+ * @test TestHumongousReferenceObjectG1
+ * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries on G1, with references in them works.
+ * @requires vm.gc.G1
+ * @bug 8151499 8153734
+ * @modules java.base/jdk.internal.vm.annotation
  * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 gc.TestHumongousReferenceObject
  * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 gc.TestHumongousReferenceObject
  * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 gc.TestHumongousReferenceObject
--- a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java	Fri May 03 14:59:32 2019 -0400
@@ -28,15 +28,33 @@
 import static jdk.test.lib.Asserts.*;
 import java.util.stream.*;
 
-/* @test TestMemoryMXBeansAndPoolsPresence
+/* @test TestMemoryMXBeansAndPoolsPresenceG1
  * @bug 8191564
  * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created.
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
- * @requires vm.gc == null
+ * @requires vm.gc.G1
  * @run main/othervm -XX:+UseG1GC gc.TestMemoryMXBeansAndPoolsPresence G1
+ */
+
+/* @test TestMemoryMXBeansAndPoolsPresenceParallel
+ * @bug 8191564
+ * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @requires vm.gc.Parallel
  * @run main/othervm -XX:+UseParallelGC gc.TestMemoryMXBeansAndPoolsPresence Parallel
+ */
+
+/* @test TestMemoryMXBeansAndPoolsPresenceSerial
+ * @bug 8191564
+ * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @requires vm.gc.Serial
  * @run main/othervm -XX:+UseSerialGC gc.TestMemoryMXBeansAndPoolsPresence Serial
  */
 
@@ -46,7 +64,7 @@
  * @modules java.base/jdk.internal.misc
  *          java.management
  * @comment Graal does not support CMS
- * @requires vm.gc == null & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @run main/othervm -XX:+UseConcMarkSweepGC gc.TestMemoryMXBeansAndPoolsPresence CMS
  */
 
--- a/test/hotspot/jtreg/gc/TestNumWorkerOutput.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java	Fri May 03 14:59:32 2019 -0400
@@ -24,11 +24,11 @@
 package gc;
 
 /*
- * @test TestNumWorkerOutput
+ * @test TestNumWorkerOutputG1
  * @bug 8165292
  * @summary Check that when PrintGCDetails is enabled, gc,task output is printed only once per collection.
  * @key gc
- * @requires vm.gc=="null"
+ * @requires vm.gc.G1
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
  * @build sun.hotspot.WhiteBox
@@ -41,7 +41,7 @@
  * @bug 8165292
  * @key gc
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
  * @build sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/gc/TestPolicyNamePerfCounter.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestPolicyNamePerfCounter.java	Fri May 03 14:59:32 2019 -0400
@@ -27,9 +27,9 @@
 import gc.testlibrary.PerfCounters;
 
 
-/* @test TestPolicyNamePerfCounter
+/* @test TestPolicyNamePerfCounterSerial
  * @bug 8210192
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
  * @library /test/lib /
  * @summary Tests that sun.gc.policy.name returns expected values for different GCs.
  * @modules java.base/jdk.internal.misc
@@ -37,14 +37,36 @@
  *          java.management/sun.management
  *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseSerialGC gc.TestPolicyNamePerfCounter Copy:MSC
+ */
+
+/* @test TestPolicyNamePerfCounterParallel
+ * @bug 8210192
+ * @requires vm.gc.Parallel
+ * @library /test/lib /
+ * @summary Tests that sun.gc.policy.name returns expected values for different GCs.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseParallelGC gc.TestPolicyNamePerfCounter ParScav:MSC
+ */
+
+/* @test TestPolicyNamePerfCounterG1
+ * @bug 8210192
+ * @requires vm.gc.G1
+ * @library /test/lib /
+ * @summary Tests that sun.gc.policy.name returns expected values for different GCs.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+UsePerfData -XX:+UseG1GC gc.TestPolicyNamePerfCounter GarbageFirst
  */
 
 /* @test TestPolicyNamePerfCounterCMS
  * @bug 8210192
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib /
  * @summary Tests that sun.gc.policy.name returns expected values for different GCs.
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/TestSmallHeap.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestSmallHeap.java	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,6 @@
 /**
  * @test TestSmallHeap
  * @bug 8067438 8152239
- * @requires vm.gc=="null"
  * @summary Verify that starting the VM with a small heap works
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -64,7 +63,9 @@
 
 import java.util.LinkedList;
 
+import jtreg.SkippedException;
 import sun.hotspot.WhiteBox;
+import sun.hotspot.gc.GC;
 
 public class TestSmallHeap {
 
@@ -76,11 +77,27 @@
         int pageSize = wb.getVMPageSize();
         int heapBytesPerCard = 512;
         long expectedMaxHeap = pageSize * heapBytesPerCard;
+        boolean noneGCSupported = true;
 
-        verifySmallHeapSize("-XX:+UseParallelGC", expectedMaxHeap);
-        verifySmallHeapSize("-XX:+UseSerialGC", expectedMaxHeap);
-        verifySmallHeapSize("-XX:+UseG1GC", expectedMaxHeap);
-        verifySmallHeapSize("-XX:+UseConcMarkSweepGC", expectedMaxHeap);
+        if (GC.Parallel.isSupported()) {
+            noneGCSupported = false;
+            verifySmallHeapSize("-XX:+UseParallelGC", expectedMaxHeap);
+        }
+        if (GC.Serial.isSupported()) {
+            noneGCSupported = false;
+            verifySmallHeapSize("-XX:+UseSerialGC", expectedMaxHeap);
+        }
+        if (GC.G1.isSupported()) {
+            noneGCSupported = false;
+            verifySmallHeapSize("-XX:+UseG1GC", expectedMaxHeap);
+        }
+        if (GC.ConcMarkSweep.isSupported()) {
+            noneGCSupported = false;
+            verifySmallHeapSize("-XX:+UseConcMarkSweepGC", expectedMaxHeap);
+        }
+        if (noneGCSupported) {
+            throw new SkippedException("Skipping test because none of Parallel/Serial/G1/ConcMarkSweep is supported.");
+        }
     }
 
     private static void verifySmallHeapSize(String gc, long expectedMaxHeap) throws Exception {
--- a/test/hotspot/jtreg/gc/TestSystemGC.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/TestSystemGC.java	Fri May 03 14:59:32 2019 -0400
@@ -24,14 +24,27 @@
 package gc;
 
 /*
- * @test TestSystemGC
+ * @test TestSystemGCSerial
  * @key gc
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
  * @summary Runs System.gc() with different flags.
- * @run main/othervm gc.TestSystemGC
  * @run main/othervm -XX:+UseSerialGC gc.TestSystemGC
+ */
+
+/*
+ * @test TestSystemGCParallel
+ * @key gc
+ * @requires vm.gc.Parallel
+ * @summary Runs System.gc() with different flags.
  * @run main/othervm -XX:+UseParallelGC gc.TestSystemGC
  * @run main/othervm -XX:+UseParallelGC -XX:-UseParallelOldGC gc.TestSystemGC
+ */
+
+/*
+ * @test TestSystemGCG1
+ * @key gc
+ * @requires vm.gc.G1
+ * @summary Runs System.gc() with different flags.
  * @run main/othervm -XX:+UseG1GC gc.TestSystemGC
  * @run main/othervm -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent gc.TestSystemGC
  * @run main/othervm -XX:+UseLargePages gc.TestSystemGC
@@ -42,7 +55,7 @@
  * @test TestSystemGCCMS
  * @key gc
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @run main/othervm -XX:+UseConcMarkSweepGC gc.TestSystemGC
  * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent gc.TestSystemGC
  */
--- a/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java	Fri May 03 14:59:32 2019 -0400
@@ -24,18 +24,31 @@
 package gc.arguments;
 
 /**
- * @test TestAlignmentToUseLargePages
+ * @test TestAlignmentToUseLargePagesSerial
  * @key gc regression
- * @summary All parallel GC variants may use large pages without the requirement that the
- * heap alignment is large page aligned. Other collectors also need to start up with odd sized heaps.
  * @bug 8024396
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
+ * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
+ * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
+ */
+
+/**
+ * @test TestAlignmentToUseLargePagesParallel
+ * @key gc regression
+ * @summary All parallel GC variants may use large pages without the requirement that the heap alignment is large page aligned. Other collectors also need to start up with odd sized heaps.
+ * @bug 8024396
+ * @requires vm.gc.Parallel
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
- * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
- * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
+ */
+
+/**
+ * @test TestAlignmentToUseLargePagesG1
+ * @key gc regression
+ * @bug 8024396
+ * @requires vm.gc.G1
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
  */
@@ -45,7 +58,7 @@
  * @key gc regression
  * @bug 8024396
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:+UseLargePages gc.arguments.TestAlignmentToUseLargePages
  * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:-UseLargePages gc.arguments.TestAlignmentToUseLargePages
  */
--- a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java	Fri May 03 14:59:32 2019 -0400
@@ -24,17 +24,43 @@
 package gc.arguments;
 
 /*
- * @test TestMaxNewSize
+ * @test TestMaxNewSizeSerial
+ * @key gc
+ * @bug 7057939
+ * @summary Make sure that MaxNewSize always has a useful value after argument
+ * processing.
+ * @requires vm.gc.Serial
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main gc.arguments.TestMaxNewSize -XX:+UseSerialGC
+ * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com
+ */
+
+/*
+ * @test TestMaxNewSizeParallel
  * @key gc
  * @bug 7057939
  * @summary Make sure that MaxNewSize always has a useful value after argument
  * processing.
- * @requires vm.gc=="null"
+ * @requires vm.gc.Parallel
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
- * @run main gc.arguments.TestMaxNewSize -XX:+UseSerialGC
  * @run main gc.arguments.TestMaxNewSize -XX:+UseParallelGC
+ * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com
+ */
+
+/*
+ * @test TestMaxNewSizeG1
+ * @key gc
+ * @bug 7057939
+ * @summary Make sure that MaxNewSize always has a useful value after argument
+ * processing.
+ * @requires vm.gc.G1
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
  * @run main gc.arguments.TestMaxNewSize -XX:+UseG1GC
  * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com
  */
@@ -44,7 +70,7 @@
  * @key gc
  * @bug 7057939
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/gc/arguments/TestMinInitialErgonomics.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestMinInitialErgonomics.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,8 @@
  * @test TestMinInitialErgonomics
  * @key gc
  * @bug 8006088
- * @summary Test ergonomics decisions related to minimum and initial heap size.
+ * @requires vm.gc.Parallel
+ * @summary Test Parallel GC ergonomics decisions related to minimum and initial heap size.
  * @library /test/lib
  * @library /
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java	Fri May 03 14:59:32 2019 -0400
@@ -32,12 +32,18 @@
  * @library /
  * @modules java.base/jdk.internal.misc
  *          java.management
- * @run driver gc.arguments.TestParallelGCThreads
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestParallelGCThreads
  */
 
+import java.util.ArrayList;
+import java.util.List;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
+import sun.hotspot.gc.GC;
 
 public class TestParallelGCThreads {
 
@@ -75,7 +81,23 @@
 
   public static void testFlags() throws Exception {
     // For each parallel collector (G1, Parallel, ParNew/CMS)
-    for (String gc : new String[] {"G1", "Parallel", "ConcMarkSweep"}) {
+    List<String> supportedGC = new ArrayList<String>();
+
+    if (GC.G1.isSupported()) {
+      supportedGC.add("G1");
+    }
+    if (GC.Parallel.isSupported()) {
+      supportedGC.add("Parallel");
+    }
+    if (GC.ConcMarkSweep.isSupported()) {
+      supportedGC.add("ConcMarkSweep");
+    }
+
+    if (supportedGC.isEmpty()) {
+      throw new SkippedException("Skipping test because none of G1/Parallel/ConcMarkSweep is supported.");
+    }
+
+    for (String gc : supportedGC) {
 
       // Make sure the VM does not allow ParallelGCThreads set to 0
       String[] flags = new String[] {"-XX:+Use" + gc + "GC", "-XX:ParallelGCThreads=0", "-XX:+PrintFlagsFinal", "-version"};
--- a/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,7 @@
  * @bug 8006088
  * @summary Tests argument processing for initial and maximum heap size for the
  * parallel collectors.
- * @requires vm.gc=="null"
+ * @requires vm.gc.Parallel
  * @library /test/lib
  * @library /
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,9 @@
  * @key gc
  * @summary Test defaults processing for -XX:+ParallelRefProcEnabled.
  * @library /test/lib
- * @run driver gc.arguments.TestParallelRefProc
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestParallelRefProc
  */
 
 import java.util.Arrays;
@@ -37,15 +39,34 @@
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
 
+import jtreg.SkippedException;
+import sun.hotspot.gc.GC;
+
 public class TestParallelRefProc {
 
     public static void main(String args[]) throws Exception {
-        testFlag(new String[] { "-XX:+UseSerialGC" }, false);
-        testFlag(new String[] { "-XX:+UseConcMarkSweepGC" }, false);
-        testFlag(new String[] { "-XX:+UseParallelGC" }, false);
-        testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=1" }, false);
-        testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=2" }, true);
-        testFlag(new String[] { "-XX:+UseG1GC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false);
+        boolean noneGCSupported = true;
+        if (GC.Serial.isSupported()) {
+            noneGCSupported = false;
+            testFlag(new String[] { "-XX:+UseSerialGC" }, false);
+        }
+        if (GC.ConcMarkSweep.isSupported()) {
+            noneGCSupported = false;
+            testFlag(new String[] { "-XX:+UseConcMarkSweepGC" }, false);
+        }
+        if (GC.Parallel.isSupported()) {
+            noneGCSupported = false;
+            testFlag(new String[] { "-XX:+UseParallelGC" }, false);
+        }
+        if (GC.G1.isSupported()) {
+            noneGCSupported = false;
+            testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=1" }, false);
+            testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=2" }, true);
+            testFlag(new String[] { "-XX:+UseG1GC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false);
+        }
+        if (noneGCSupported) {
+            throw new SkippedException("Skipping test because none of Serial/ConcMarkSweep/Parallel/G1 is supported.");
+        }
     }
 
     private static final String parallelRefProcEnabledPattern =
--- a/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java	Fri May 03 14:59:32 2019 -0400
@@ -29,7 +29,7 @@
  * @bug 8068582
  * @key gc
  * @library /test/lib
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial & vm.gc.G1
  * @modules java.base/jdk.internal.misc
  *          java.management
  * @run driver gc.arguments.TestSelectDefaultGC
--- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java	Fri May 03 14:59:32 2019 -0400
@@ -24,11 +24,44 @@
 package gc.arguments;
 
 /*
- * @test TestUseCompressedOopsErgo
+ * @test TestUseCompressedOopsErgoSerial
  * @key gc
  * @bug 8010722
  * @summary Tests ergonomics for UseCompressedOops.
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc
+ *          java.management/sun.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseSerialGC
+ */
+
+/*
+ * @test TestUseCompressedOopsErgoParallel
+ * @key gc
+ * @bug 8010722
+ * @summary Tests ergonomics for UseCompressedOops.
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc
+ *          java.management/sun.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseParallelGC
+ * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC
+ */
+
+/*
+ * @test TestUseCompressedOopsErgoG1
+ * @key gc
+ * @bug 8010722
+ * @summary Tests ergonomics for UseCompressedOops.
+ * @requires vm.gc.G1
  * @library /test/lib
  * @library /
  * @modules java.base/jdk.internal.misc
@@ -37,9 +70,6 @@
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseG1GC
- * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseParallelGC
- * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC
- * @run main/othervm gc.arguments.TestUseCompressedOopsErgo -XX:+UseSerialGC
  */
 
 /*
@@ -47,7 +77,7 @@
  * @key gc
  * @bug 8010722
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @library /
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,7 @@
  * @test
  * @key gc
  * @bug 8049831
- * @requires !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java	Fri May 03 14:59:32 2019 -0400
@@ -24,12 +24,50 @@
 package gc.class_unloading;
 
 /*
- * @test
+ * @test TestClassUnloadingDisabledSerial
+ * @key gc
+ * @bug 8114823
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @requires vm.opt.ClassUnloading != true
+ * @requires vm.gc.Serial
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:-ClassUnloading -XX:+UseSerialGC gc.class_unloading.TestClassUnloadingDisabled
+ *
+ */
+
+/*
+ * @test TestClassUnloadingDisabledParallel
  * @key gc
  * @bug 8114823
- * @requires vm.gc == null
  * @requires vm.opt.ExplicitGCInvokesConcurrent != true
  * @requires vm.opt.ClassUnloading != true
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:-ClassUnloading -XX:+UseParallelGC gc.class_unloading.TestClassUnloadingDisabled
+ *
+ */
+
+/*
+ * @test TestClassUnloadingDisabledG1
+ * @key gc
+ * @bug 8114823
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @requires vm.opt.ClassUnloading != true
+ * @requires vm.gc.G1
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
@@ -40,20 +78,14 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:-ClassUnloading -XX:+UseG1GC gc.class_unloading.TestClassUnloadingDisabled
  *
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *                   -XX:-ClassUnloading -XX:+UseSerialGC gc.class_unloading.TestClassUnloadingDisabled
- *
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *                   -XX:-ClassUnloading -XX:+UseParallelGC gc.class_unloading.TestClassUnloadingDisabled
- *
  */
 
 /*
- * @test
+ * @test TestClassUnloadingDisabledCMS
  * @key gc
  * @bug 8114823
  * @comment Graal does not support CMS
- * @requires vm.gc=="null" & !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @requires vm.opt.ExplicitGCInvokesConcurrent != true
  * @requires vm.opt.ClassUnloading != true
  * @library /test/lib
--- a/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
  * @test
  * @key gc
  * @bug 8049831
+ * @requires vm.gc.G1
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,7 @@
  * @key gc regression
  * @summary Remove warning about CMS generation shrinking.
  * @bug 8012111
- * @requires !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
  * @test TestDynamicNumberOfGCThreads
  * @bug 8017462
  * @summary Ensure that UseDynamicNumberOfGCThreads runs
- * @requires vm.gc=="null"
  * @key gc
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
@@ -38,19 +37,35 @@
 
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
 import sun.hotspot.gc.GC;
 
 public class TestDynamicNumberOfGCThreads {
   public static void main(String[] args) throws Exception {
+    boolean noneGCSupported = true;
 
-    testDynamicNumberOfGCThreads("UseConcMarkSweepGC");
+    if (GC.ConcMarkSweep.isSupported()) {
+      noneGCSupported = false;
+      testDynamicNumberOfGCThreads("UseConcMarkSweepGC");
+    }
 
-    testDynamicNumberOfGCThreads("UseG1GC");
+    if (GC.G1.isSupported()) {
+      noneGCSupported = false;
+      testDynamicNumberOfGCThreads("UseG1GC");
+    }
 
-    testDynamicNumberOfGCThreads("UseParallelGC");
+    if (GC.Parallel.isSupported()) {
+      noneGCSupported = false;
+      testDynamicNumberOfGCThreads("UseParallelGC");
+    }
 
     if (GC.Shenandoah.isSupported()) {
-        testDynamicNumberOfGCThreads("UseShenandoahGC");
+      noneGCSupported = false;
+      testDynamicNumberOfGCThreads("UseShenandoahGC");
+    }
+
+    if (noneGCSupported) {
+      throw new SkippedException("Skipping test because none of ConcMarkSweep/G1/Parallel/Shenandoah is supported.");
     }
   }
 
--- a/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
  * @test TestInitialGCThreadLogging
  * @bug 8157240
  * @summary Check trace logging of initial GC threads.
- * @requires vm.gc=="null"
  * @key gc
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
@@ -38,19 +37,35 @@
 
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jtreg.SkippedException;
 import sun.hotspot.gc.GC;
 
 public class TestInitialGCThreadLogging {
   public static void main(String[] args) throws Exception {
+    boolean noneGCSupported = true;
 
-    testInitialGCThreadLogging("UseConcMarkSweepGC", "GC Thread");
+    if (GC.ConcMarkSweep.isSupported()) {
+      noneGCSupported = false;
+      testInitialGCThreadLogging("UseConcMarkSweepGC", "GC Thread");
+    }
 
-    testInitialGCThreadLogging("UseG1GC", "GC Thread");
+    if (GC.G1.isSupported()) {
+      noneGCSupported = false;
+      testInitialGCThreadLogging("UseG1GC", "GC Thread");
+    }
 
-    testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
+    if (GC.Parallel.isSupported()) {
+      noneGCSupported = false;
+      testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
+    }
 
     if (GC.Shenandoah.isSupported()) {
-        testInitialGCThreadLogging("UseShenandoahGC", "Shenandoah GC Thread");
+      noneGCSupported = false;
+      testInitialGCThreadLogging("UseShenandoahGC", "Shenandoah GC Thread");
+    }
+
+    if (noneGCSupported) {
+      throw new SkippedException("Skipping test because none of ConcMarkSweep/G1/Parallel/Shenandoah is supported.");
     }
   }
 
--- a/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java	Fri May 03 14:59:32 2019 -0400
@@ -34,6 +34,7 @@
  *     3. invoke gc and check that memory returned to the system (amount of committed memory got down)
  *
  * @library /test/lib /
+ * @requires vm.gc.G1
  * @modules java.base/jdk.internal.misc
  *          java.management/sun.management
  * @run main gc.g1.TestShrinkDefragmentedHeap
--- a/test/hotspot/jtreg/gc/logging/TestGCId.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/logging/TestGCId.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,6 @@
  * @test TestGCId
  * @bug 8043607
  * @summary Ensure that the GCId is logged
- * @requires vm.gc=="null"
  * @key gc
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -39,16 +38,36 @@
 
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
 import sun.hotspot.gc.GC;
 
 public class TestGCId {
   public static void main(String[] args) throws Exception {
-    testGCId("UseParallelGC");
-    testGCId("UseG1GC");
-    testGCId("UseConcMarkSweepGC");
-    testGCId("UseSerialGC");
+    boolean noneGCSupported = true;
+
+    if (GC.Parallel.isSupported()) {
+      noneGCSupported = false;
+      testGCId("UseParallelGC");
+    }
+    if (GC.G1.isSupported()) {
+      noneGCSupported = false;
+      testGCId("UseG1GC");
+    }
+    if (GC.ConcMarkSweep.isSupported()) {
+      noneGCSupported = false;
+      testGCId("UseConcMarkSweepGC");
+    }
+    if (GC.Serial.isSupported()) {
+      noneGCSupported = false;
+      testGCId("UseSerialGC");
+    }
     if (GC.Shenandoah.isSupported()) {
-        testGCId("UseShenandoahGC");
+      noneGCSupported = false;
+      testGCId("UseShenandoahGC");
+    }
+
+    if (noneGCSupported) {
+      throw new SkippedException("Skipping test because none of Parallel/G1/ConcMarkSweep/Serial/Shenandoah is supported.");
     }
   }
 
--- a/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java	Fri May 03 14:59:32 2019 -0400
@@ -33,13 +33,14 @@
 import jdk.test.lib.Asserts;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jtreg.SkippedException;
+import sun.hotspot.gc.GC;
 import sun.hotspot.WhiteBox;
 
 /*
  * @test TestMetaSpaceLog
  * @bug 8211123
  * @summary Ensure that the Metaspace is updated in the log
- * @requires vm.gc=="null"
  * @key gc
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -47,7 +48,7 @@
  *
  * @compile TestMetaSpaceLog.java
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- * @run main gc.logging.TestMetaSpaceLog
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.logging.TestMetaSpaceLog
  */
 
 public class TestMetaSpaceLog {
@@ -59,10 +60,27 @@
   }
 
   public static void main(String[] args) throws Exception {
-    testMetaSpaceUpdate("UseParallelGC");
-    testMetaSpaceUpdate("UseG1GC");
-    testMetaSpaceUpdate("UseConcMarkSweepGC");
-    testMetaSpaceUpdate("UseSerialGC");
+    boolean noneGCSupported = true;
+
+    if (GC.Parallel.isSupported()) {
+      noneGCSupported = false;
+      testMetaSpaceUpdate("UseParallelGC");
+    }
+    if (GC.G1.isSupported()) {
+      noneGCSupported = false;
+      testMetaSpaceUpdate("UseG1GC");
+    }
+    if (GC.ConcMarkSweep.isSupported()) {
+      noneGCSupported = false;
+      testMetaSpaceUpdate("UseConcMarkSweepGC");
+    }
+    if (GC.Serial.isSupported()) {
+      noneGCSupported = false;
+      testMetaSpaceUpdate("UseSerialGC");
+    }
+    if (noneGCSupported) {
+      throw new SkippedException("Skipping test because none of Parallel/G1/ConcMarkSweep/Serial is supported.");
+    }
   }
 
   private static void verifyContainsMetaSpaceUpdate(OutputAnalyzer output) {
--- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
  * @test TestPrintReferences
  * @bug 8136991 8186402 8186465 8188245
  * @summary Validate the reference processing logging
+ * @requires vm.gc.G1
  * @key gc
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java	Fri May 03 14:59:32 2019 -0400
@@ -30,7 +30,7 @@
 /* @test TestMetaspaceCMSCancel
  * @bug 8026752
  * @summary Tests cancel of CMS concurrent cycle for Metaspace after a full GC
- * @requires !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  * @build sun.hotspot.WhiteBox
--- a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java	Fri May 03 14:59:32 2019 -0400
@@ -37,9 +37,9 @@
 import gc.testlibrary.PerfCounter;
 import gc.testlibrary.PerfCounters;
 
-/* @test TestMetaspacePerfCounters
+/* @test TestMetaspacePerfCountersSerial
  * @bug 8014659
- * @requires vm.gc=="null"
+ * @requires vm.gc.Serial
  * @library /test/lib /
  * @summary Tests that performance counters for metaspace and compressed class
  *          space exists and works.
@@ -48,11 +48,34 @@
  *          java.management/sun.management
  *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters
+ */
+
+/* @test TestMetaspacePerfCountersParallel
+ * @bug 8014659
+ * @requires vm.gc.Parallel
+ * @library /test/lib /
+ * @summary Tests that performance counters for metaspace and compressed class
+ *          space exists and works.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC gc.metaspace.TestMetaspacePerfCounters
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC gc.metaspace.TestMetaspacePerfCounters
+ */
+
+/* @test TestMetaspacePerfCountersG1
+ * @bug 8014659
+ * @requires vm.gc.G1
+ * @library /test/lib /
+ * @summary Tests that performance counters for metaspace and compressed class
+ *          space exists and works.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC gc.metaspace.TestMetaspacePerfCounters
- *
- * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC gc.metaspace.TestMetaspacePerfCounters
- * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC gc.metaspace.TestMetaspacePerfCounters
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC gc.metaspace.TestMetaspacePerfCounters
  */
 
--- a/test/hotspot/jtreg/gc/parallel/AdaptiveGCBoundary.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/parallel/AdaptiveGCBoundary.java	Fri May 03 14:59:32 2019 -0400
@@ -26,6 +26,7 @@
 /**
  * @test AdaptiveGCBoundary
  * @key gc regression
+ * @requires vm.gc.Parallel
  * @summary UseAdaptiveGCBoundary is broken
  * @bug 8014546
  * @library /test/lib
--- a/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,7 @@
  * @key gc
  * @bug 8006398 8155948 8179013
  * @summary Test that CMS prints a warning message
- * @requires !vm.graal.enabled
+ * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/gc/startup_warnings/TestG1.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestG1.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
 * @test TestG1
 * @key gc
 * @bug 8006398
+* @requires vm.gc.G1
 * @summary Test that the G1 collector does not print a warning message
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/startup_warnings/TestParallelGC.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestParallelGC.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
 * @test TestParallelGC
 * @key gc
 * @bug 8006398
+* @requires vm.gc.Parallel
 * @summary Test that ParallelGC does not print a warning message
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/startup_warnings/TestParallelScavengeSerialOld.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestParallelScavengeSerialOld.java	Fri May 03 14:59:32 2019 -0400
@@ -27,6 +27,7 @@
 * @test TestParallelScavengeSerialOld
 * @key gc
 * @bug 8006398
+* @requires vm.gc.Parallel
 * @summary Test that the ParallelScavenge+SerialOld combination does not print a warning message
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java	Fri May 03 14:59:32 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
@@ -21,7 +21,6 @@
  * questions.
  */
 
-import static java.io.File.createTempFile;
 import static java.lang.Long.parseLong;
 import static java.lang.System.getProperty;
 import static java.nio.file.Files.readAllBytes;
@@ -30,6 +29,7 @@
 import static java.util.stream.Collectors.toList;
 import static jdk.test.lib.process.ProcessTools.createJavaProcessBuilder;
 import static jdk.test.lib.Platform.isWindows;
+import jdk.test.lib.Utils;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -43,7 +43,7 @@
 
 /*
  * @test TestInheritFD
- * @bug 8176717 8176809
+ * @bug 8176717 8176809 8222500
  * @summary a new process should not inherit open file descriptors
  * @comment On Aix lsof requires root privileges.
  * @requires os.family != "aix"
@@ -79,8 +79,8 @@
 
     // first VM
     public static void main(String[] args) throws Exception {
-        String logPath = createTempFile("logging", LOG_SUFFIX).getName();
-        File commFile = createTempFile("communication", ".txt");
+        String logPath = Utils.createTempFile("logging", LOG_SUFFIX).toFile().getName();
+        File commFile = Utils.createTempFile("communication", ".txt").toFile();
 
         if (!isWindows() && !lsofCommand().isPresent()) {
             System.out.println("Could not find lsof like command");
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Fri May 03 14:59:32 2019 -0400
@@ -47,6 +47,7 @@
         {"TLABStats",                 "false"},
         {"ThreadLocalHandshakes",     "true"},
         {"AllowJNIEnvProxy",          "true"},
+        {"AllowRedefinitionToAddDeleteMethods", "true"},
 
         // deprecated alias flags (see also aliased_jvm_flags):
         {"DefaultMaxRAMFraction", "4"},
--- a/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java	Fri May 03 14:59:32 2019 -0400
@@ -60,7 +60,7 @@
         output.shouldContain("Baseline succeeded");
 
         wb.NMTFree(addr);
-        addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 7 /* mtInternal */ );
+        addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 8 /* mtInternal */ );
         pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff"});
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("(malloc=0KB type=Test -4KB)");
--- a/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java	Fri May 03 14:59:32 2019 -0400
@@ -32,7 +32,7 @@
  *          MissingMethodWithSuper.jcod
  *          MissingNestHost.jcod
  * @run main TestInvokeErrors true
- * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestInvokeErrors false
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestInvokeErrors false
  */
 
 public class TestInvokeErrors {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Shutdown/ShutdownTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,91 @@
+/*
+ * 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 4656449 4945125 8074355
+ * @summary Make MutexLocker smarter about non-Java threads
+ * @library /test/lib
+ * @run driver/timeout=240 ShutdownTest
+ */
+
+// This test is adapted from an old regression test for bug 4945125, where VerifyBeforeExit
+// crashes before exit for the regression test for bug 4656449.
+// The fix is to acquire the Heap_lock before exit after the JavaThread is removed from
+// the threads list.  This fix is still valid.  This code requires Heap_lock be acquired
+// without a safepoint check at exit.
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ShutdownTest {
+   Object[] obj;
+
+   ShutdownTest() {
+       // Allocate to get some GC pressure.
+       obj = new Object[100000];
+   }
+
+    static class ShutdownTestThread extends Thread {
+       public void run() {
+         while (true) {
+           ShutdownTest st = new ShutdownTest();
+         }
+       }
+
+       public static void main(String args[]) {
+         System.out.println("- ShutdownTest -");
+
+         for (int i = 0; i < 100; i++) {
+           ShutdownTestThread st = new ShutdownTestThread();
+           st.setDaemon(true);
+           st.start();
+         }
+       }
+    }
+
+    private static void startVM(List<String> options) throws Throwable {
+        // Combine VM flags given from command-line and your additional options
+        OutputAnalyzer output = ProcessTools.executeTestJvm(options.toArray(new String[options.size()]));
+        output.shouldContain("- ShutdownTest -");
+        output.shouldHaveExitValue(0);
+
+    }
+
+    public static void main(String[] args) throws Throwable {
+        List<String> options = new ArrayList<>();
+
+        // To reproduce original bug you may need this option: "-Xmx2500k",
+        Collections.addAll(options,
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:+VerifyBeforeExit");
+        options.add(ShutdownTestThread.class.getName());
+
+        for (int iteration = 0; iteration < 5; ++iteration) {
+            startVM(options);
+        }
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/VerifierTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest.java	Fri May 03 14:59:32 2019 -0400
@@ -38,7 +38,7 @@
     // Test verification settings for dumping & runtime
     static final String VFY_ALL = "-Xverify:all";
     static final String VFY_REMOTE = "-Xverify:remote"; // default
-    static final String VFY_NONE = "-XX:-BytecodeVerificationRemote, -XX:-BytecodeVerificationLocal";
+    static final String VFY_NONE = "-XX:+UnlockDiagnosticVMOptions, -XX:-BytecodeVerificationRemote, -XX:-BytecodeVerificationLocal";
 
     static final String ERR =
         "ERROR: class VerifierTestC was loaded unexpectedly";
@@ -188,18 +188,20 @@
             if (!dump_setting.equals(prev_dump_setting)) {
                 String dump_arg1;
                 String dump_arg2;
+                String dump_arg3;
                 // Need to break this into two separate arguments.
                 if (dump_setting.equals(VFY_NONE)) {
-                    dump_arg1 = "-XX:-BytecodeVerificationRemote";
-                    dump_arg2 = "-XX:-BytecodeVerificationLocal";
+                    dump_arg1 = "-XX:+UnlockDiagnosticVMOptions";
+                    dump_arg2 = "-XX:-BytecodeVerificationRemote";
+                    dump_arg3 = "-XX:-BytecodeVerificationLocal";
                 } else {
                     // Redundant args should be harmless.
-                    dump_arg1 = dump_arg2 = dump_setting;
+                    dump_arg1 = dump_arg2 = dump_arg3 = dump_setting;
                 }
 
                 OutputAnalyzer dumpOutput = TestCommon.dump(
                                                             jar, dump_list, dump_arg1, dump_arg2,
-                                                            CDS_LOGGING,
+                                                            dump_arg3, CDS_LOGGING,
                                                             // FIXME: the following options are for working around a GC
                                                             // issue - assert failure when dumping archive with the -Xverify:all
                                                             "-Xms256m",
@@ -211,15 +213,17 @@
             }
             String runtime_arg1;
             String runtime_arg2;
+            String runtime_arg3;
             if (runtime_setting.equals(VFY_NONE)) {
-                runtime_arg1 = "-XX:-BytecodeVerificationRemote";
-                runtime_arg2 = "-XX:-BytecodeVerificationLocal";
+                runtime_arg1 = "-XX:+UnlockDiagnosticVMOptions";
+                runtime_arg2 = "-XX:-BytecodeVerificationRemote";
+                runtime_arg3 = "-XX:-BytecodeVerificationLocal";
             } else {
                 // Redundant args should be harmless.
-                runtime_arg1 = runtime_arg2 = runtime_setting;
+                runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting;
             }
             TestCommon.run("-cp", jar,
-                           runtime_arg1, runtime_arg2,
+                           runtime_arg1, runtime_arg2, runtime_arg3,
                            "VerifierTest0")
                 .ifNoMappingFailure(output -> checkRuntimeOutput(output, expected_output_str));
             prev_dump_setting = dump_setting;
@@ -266,16 +270,18 @@
             if (!dump_setting.equals(prev_dump_setting)) {
                 String dump_arg1;
                 String dump_arg2;
+                String dump_arg3;
                 if (dump_setting.equals(VFY_NONE)) {
-                    dump_arg1 = "-XX:-BytecodeVerificationRemote";
-                    dump_arg2 = "-XX:-BytecodeVerificationLocal";
+                    dump_arg1 = "-XX:+UnlockDiagnosticVMOptions";
+                    dump_arg2 = "-XX:-BytecodeVerificationRemote";
+                    dump_arg3 = "-XX:-BytecodeVerificationLocal";
                 } else {
                     // Redundant args should be harmless.
-                    dump_arg1 = dump_arg2 = dump_setting;
+                    dump_arg1 = dump_arg2 = dump_arg3 = dump_setting;
                 }
                 OutputAnalyzer dumpOutput = TestCommon.dump(
                                                             jar, appClasses, dump_arg1, dump_arg2,
-                                                            CDS_LOGGING,
+                                                            dump_arg3, CDS_LOGGING,
                                                             // FIXME: the following options are for working around a GC
                                                             // issue - assert failure when dumping archive with the -Xverify:all
                                                             "-Xms256m",
@@ -287,15 +293,17 @@
             }
             String runtime_arg1;
             String runtime_arg2;
+            String runtime_arg3;
             if (runtime_setting.equals(VFY_NONE)) {
-                runtime_arg1 = "-XX:-BytecodeVerificationRemote";
-                runtime_arg2 = "-XX:-BytecodeVerificationLocal";
+                runtime_arg1 = "-XX:+UnlockDiagnosticVMOptions";
+                runtime_arg2 = "-XX:-BytecodeVerificationRemote";
+                runtime_arg3 = "-XX:-BytecodeVerificationLocal";
             } else {
                 // Redundant args should be harmless.
-                runtime_arg1 = runtime_arg2 = runtime_setting;
+                runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting;
             }
             TestCommon.run("-cp", jar,
-                           runtime_arg1, runtime_arg2,
+                           runtime_arg1, runtime_arg2, runtime_arg3,
                            "Hi")
                 .ifNoMappingFailure(output -> checkRuntimeOutput(output, expected_output_str));
            prev_dump_setting = dump_setting;
--- a/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/clone/invokevirtual/HasLocalClone.jasm	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,7 @@
  * @summary Check that invokevirtual of clone() finds the clone() method that
  *          is local to the calling class.
  * @compile DefMethClone.jasm SuperClass.jasm I1.java HasLocalClone.jasm
- * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal HasLocalClone
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal HasLocalClone
  */
 
 // The below .jasm code implements the following java code:
--- a/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalClone.jasm	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,7 @@
  * @summary Check that invokevirtual of clone() calls java.lang.Object.clone()
  *          even if a superinterface has a default method named clone().
  * @compile DefMethClone.jasm SuperClass.jasm I1.java NoLocalClone.jasm
- * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalClone
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalClone
  */
 
 // The below .jasm code implements the following java code:
--- a/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/clone/invokevirtual/NoLocalCloneAbstr.jasm	Fri May 03 14:59:32 2019 -0400
@@ -28,7 +28,7 @@
  * @summary Check that invokevirtual of clone() calls java.lang.Object.clone()
  *          even if a superinterface has an abstract method named clone().
  * @compile DefMethClone.jasm SuperClass.jasm I1Abstr.java NoLocalCloneAbstr.jasm
- * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalCloneAbstr
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal NoLocalCloneAbstr
  */
 
 // The below .jasm code implements the following java code:
--- a/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/lambda-features/TestStaticandInstance.java	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,7 @@
  * @bug 8087342
  * @summary Test linkresolver search static, instance and overpass duplicates
  * @modules java.base/jdk.internal.org.objectweb.asm
- * @run main/othervm -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestStaticandInstance
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote -XX:-BytecodeVerificationLocal TestStaticandInstance
  */
 
 
--- a/test/hotspot/jtreg/runtime/verifier/TestSigParse.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/runtime/verifier/TestSigParse.java	Fri May 03 14:59:32 2019 -0400
@@ -27,7 +27,7 @@
  * @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
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+BytecodeVerificationLocal -XX:-BytecodeVerificationRemote TestSigParse
  */
 
 public class TestSigParse {
--- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitor.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitor.java	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -263,8 +263,13 @@
   }
 
   public static boolean statsHaveExpectedNumberSamples(int expected, int acceptedErrorPercentage) {
-    double actual = getEventStorageElementCount();
-    double diffPercentage = Math.abs(actual - expected) / expected;
+    double actual = sampledEvents();
+    double diffPercentage = 100 * Math.abs(actual - expected) / expected;
+
+    if (diffPercentage >= acceptedErrorPercentage) {
+      System.err.println("Unexpected high difference percentage: " + diffPercentage
+          + " due to the count being " + actual + " instead of " + expected);
+    }
     return diffPercentage < acceptedErrorPercentage;
   }
 
--- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorArrayAllSampledTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorArrayAllSampledTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -47,8 +47,7 @@
   public static void main(String[] args) {
     int sizes[] = {1000, 10000, 100000, 1000000};
 
-    HeapMonitor.setSamplingInterval(0);
-    HeapMonitor.enableSamplingEvents();
+    HeapMonitor.sampleEverything();
 
     for (int currentSize : sizes) {
       System.out.println("Testing size " + currentSize);
--- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -55,12 +55,12 @@
         throw new RuntimeException("Should not have any events stored yet.");
       }
 
-      HeapMonitor.enableSamplingEvents();
-
       // 111 is as good a number as any.
       final int samplingMultiplier = 111;
       HeapMonitor.setSamplingInterval(samplingMultiplier * currentSize);
 
+      HeapMonitor.enableSamplingEvents();
+
       allocate(currentSize);
 
       HeapMonitor.disableSamplingEvents();
@@ -84,7 +84,9 @@
       // statistical geometric variable around the sampling interval. This means that the test could be
       // unlucky and not achieve the mean average fast enough for the test case.
       if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
-        throw new RuntimeException("Statistics should show about " + expected + " samples.");
+        throw new RuntimeException("Statistics should show about " + expected + " samples; "
+            + " but have " + HeapMonitor.sampledEvents() + " instead for the size "
+            + currentSize);
       }
     }
   }
--- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java	Fri May 03 14:59:32 2019 -0400
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 8192936
+ * @requires os.family != "solaris"
  * @summary RI does not follow the JVMTI RedefineClasses spec; need to disallow adding and deleting methods
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -31,108 +32,177 @@
  *          java.instrument
  *          jdk.jartool/sun.tools.jar
  * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar TestAddDeleteMethods
+ * @run main/othervm -javaagent:redefineagent.jar TestAddDeleteMethods AllowAddDelete=no
+ * @run main/othervm -javaagent:redefineagent.jar -XX:+AllowRedefinitionToAddDeleteMethods TestAddDeleteMethods AllowAddDelete=yes
  */
 
 import static jdk.test.lib.Asserts.assertEquals;
+import java.lang.Runnable;
 
 // package access top-level class to avoid problem with RedefineClassHelper
 // and nested types.
-class A {
-    private static void foo()       { System.out.println("OLD foo called"); }
-    private final  void finalFoo()  { System.out.println("OLD finalFoo called"); }
-    public         void publicFoo() { foo(); finalFoo(); }
+class A implements Runnable {
+    private        void foo()       { System.out.println(" OLD foo called"); }
+    public         void publicFoo() { System.out.println(" OLD publicFoo called"); }
+    private final  void finalFoo()  { System.out.println(" OLD finalFoo called");  }
+    private static void staticFoo() { System.out.println(" OLD staticFoo called"); }
+    public         void run()       { foo(); publicFoo(); finalFoo(); staticFoo(); }
+}
+
+class B implements Runnable {
+    public         void run() { }
 }
 
 public class TestAddDeleteMethods {
-    static A a;
+    static private boolean allowAddDeleteMethods = false;
 
+    static private A a;
+    static private B b;
+
+    // This redefinition is expected to always succeed.
     public static String newA =
-        "class A {" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
-            "public         void publicFoo() { foo(); finalFoo(); }" +
+        "class A implements Runnable {" +
+            "private        void foo()       { System.out.println(\" NEW foo called\"); }" +
+            "public         void publicFoo() { System.out.println(\" NEW publicFoo called\"); }" +
+            "private final  void finalFoo()  { System.out.println(\" NEW finalFoo called\");  }" +
+            "private static void staticFoo() { System.out.println(\" NEW staticFoo called\"); }" +
+            "public         void run()       { foo(); publicFoo(); finalFoo(); staticFoo(); }" +
         "}";
 
-    public static String newAddBar =
-        "class A {" +
-            "private        void bar()       { System.out.println(\"NEW bar called\"); }" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
-            "public         void publicFoo() { foo(); bar(); finalFoo(); }" +
+    // This redefinition is expected to always fail.
+    public static String ADeleteFoo =
+        "class A implements Runnable {" +
+            "public         void publicFoo() { System.out.println(\" NEW publicFoo called\"); }" +
+            "private final  void finalFoo()  { System.out.println(\" NEW finalFoo called\");  }" +
+            "private static void staticFoo() { System.out.println(\" NEW staticFoo called\"); }" +
+            "public         void run()       { publicFoo(); finalFoo(); staticFoo(); }" +
         "}";
 
-    public static String newAddFinalBar =
-        "class A {" +
-            "private final  void bar()       { System.out.println(\"NEW bar called\"); }" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
-            "public         void publicFoo() { foo(); bar(); finalFoo(); }" +
+    // This redefinition is expected to always fail.
+    public static String ADeletePublicFoo =
+        "class A implements Runnable {" +
+            "private        void foo()       { System.out.println(\" NEW foo called\"); }" +
+            "private final  void finalFoo()  { System.out.println(\" NEW finalFoo called\");  }" +
+            "private static void staticFoo() { System.out.println(\" NEW staticFoo called\"); }" +
+            "public         void run()       { foo(); finalFoo(); staticFoo(); }" +
         "}";
 
-    public static String newAddPublicBar =
-        "class A {" +
-            "public         void bar()       { System.out.println(\"NEW public bar called\"); }" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
-            "public         void publicFoo() { foo(); bar(); finalFoo(); }" +
+    // This redefinition is expected to succeed with option -XX:+AllowRedefinitionToAddDeleteMethods.
+    public static String ADeleteFinalFoo =
+        "class A implements Runnable {" +
+            "private        void foo()       { System.out.println(\" NEW foo called\"); }" +
+            "public         void publicFoo() { System.out.println(\" NEW publicFoo called\"); }" +
+            "private static void staticFoo() { System.out.println(\" NEW staticFoo called\"); }" +
+            "public         void run()       { foo(); publicFoo(); staticFoo(); }" +
+        "}";
+
+    // This redefinition is expected to succeed with option -XX:+AllowRedefinitionToAddDeleteMethods.
+    // With compatibility option redefinition ADeleteFinalFoo already deleted finalFoo method.
+    // So, this redefinition will add it back which is expected to work.
+    public static String ADeleteStaticFoo =
+        "class A implements Runnable {" +
+            "private        void foo()       { System.out.println(\" NEW foo called\"); }" +
+            "public         void publicFoo() { System.out.println(\" NEW publicFoo called\"); }" +
+            "private final  void finalFoo()  { System.out.println(\" NEW finalFoo called\");  }" +
+            "public         void run()       { foo(); publicFoo(); finalFoo(); }" +
         "}";
 
-    public static String newDeleteFoo =
-        "class A {" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
-            "public         void publicFoo() { finalFoo(); }" +
+    // This redefinition is expected to always fail.
+    public static String BAddBar =
+        "class B implements Runnable {" +
+            "private        void bar()       { System.out.println(\" bar called\"); }" +
+            "public         void run()       { bar(); }" +
+        "}";
+
+    // This redefinition is expected to always fail.
+    public static String BAddPublicBar =
+        "class B implements Runnable {" +
+            "public         void publicBar() { System.out.println(\" publicBar called\"); }" +
+            "public         void run()       { publicBar(); }" +
         "}";
 
-    public static String newDeleteFinalFoo =
-        "class A {" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "public         void publicFoo() { foo(); }" +
+    // This redefinition is expected to succeed with option -XX:+AllowRedefinitionToAddDeleteMethods.
+    public static String BAddFinalBar =
+        "class B implements Runnable {" +
+            "private final  void finalBar()  { System.out.println(\" finalBar called\"); }" +
+            "public         void run()       { finalBar(); }" +
         "}";
 
-    public static String newDeletePublicFoo =
-        "class A {" +
-            "private static void foo()       { System.out.println(\"NEW foo called\"); }" +
-            "private final  void finalFoo()  { System.out.println(\"NEW finalFoo called\"); }" +
+    // This redefinition is expected to succeed with option -XX:+AllowRedefinitionToAddDeleteMethods.
+    // With compatibility option redefinition BAddFinalBar added finalBar method.
+    // So, this redefinition will deleate it back which is expected to work.
+    public static String BAddStaticBar =
+        "class B implements Runnable {" +
+            "private static void staticBar() { System.out.println(\" staticBar called\"); }" +
+            "public         void run()       { staticBar(); }" +
         "}";
 
     static private final String ExpMsgPrefix = "attempted to ";
     static private final String ExpMsgPostfix = " a method";
 
-    public static void test(String newBytes, String expSuffix) throws Exception {
+    static private void log(String msg) { System.out.println(msg); }
+
+    public static void test(Runnable obj, String newBytes, String expSuffix, String methodName,
+                            boolean expectedRedefToPass) throws Exception {
         String expectedMessage = ExpMsgPrefix + expSuffix + ExpMsgPostfix;
+        Class klass = obj.getClass();
+        String className = klass.getName();
+        String expResult = expectedRedefToPass ? "PASS" : "FAIL";
+
+        log("");
+        log("## Test " + expSuffix + " method \'" + methodName + "\' in class " + className +
+            "; redefinition expected to " + expResult);
 
         try {
-            RedefineClassHelper.redefineClass(A.class, newBytes);
-            a.publicFoo();
-            throw new RuntimeException("Failed, expected UOE");
+            RedefineClassHelper.redefineClass(klass, newBytes);
+
+            if (expectedRedefToPass) {
+                log(" Did not get UOE at redefinition as expected");
+            } else {
+                throw new RuntimeException("Failed, expected UOE");
+            }
+            obj.run();
+            log("");
         } catch (UnsupportedOperationException uoe) {
             String message = uoe.getMessage();
-            System.out.println("Got expected UOE " + message);
-            if (!message.endsWith(expectedMessage)) {
-                throw new RuntimeException("Expected UOE error message to end with: " + expectedMessage);
+
+            if (expectedRedefToPass) {
+                throw new RuntimeException("Failed, unexpected UOE: " + message);
+            } else {
+                log(" Got expected UOE: " + message);
+                if (!message.endsWith(expectedMessage)) {
+                    throw new RuntimeException("Expected UOE error message to end with: " + expectedMessage);
+                }
             }
         }
     }
 
     static {
         a = new A();
+        b = new B();
     }
 
     public static void main(String[] args) throws Exception {
-
-        a.publicFoo();
+        if (args.length > 0 && args[0].equals("AllowAddDelete=yes")) {
+            allowAddDeleteMethods = true;
+        }
 
-        // Should pass because this only changes bytes of methods.
-        RedefineClassHelper.redefineClass(A.class, newA);
-        a.publicFoo();
+        log("## Test original class A");
+        a.run();
+        log("");
 
-        // Add private static bar
-        test(newAddBar,          "add");
-        test(newAddFinalBar,     "add");
-        test(newAddPublicBar,    "add");
-        test(newDeleteFoo,       "delete");
-        test(newDeleteFinalFoo,  "delete");
-        test(newDeletePublicFoo, "delete");
+        log("## Test with modified method bodies in class A; redefinition expected to pass: true");
+        RedefineClassHelper.redefineClass(A.class, newA);
+        a.run();
+
+        test(a, ADeleteFoo,       "delete", "foo",       false);
+        test(a, ADeletePublicFoo, "delete", "publicFoo", false);
+        test(a, ADeleteFinalFoo,  "delete", "finalFoo",  allowAddDeleteMethods);
+        test(a, ADeleteStaticFoo, "delete", "staticFoo", allowAddDeleteMethods);
+
+        test(b, BAddBar,          "add", "bar",       false);
+        test(b, BAddPublicBar,    "add", "publicBar", false);
+        test(b, BAddFinalBar,     "add", "finalBar",  allowAddDeleteMethods);
+        test(b, BAddStaticBar,    "add", "staticBar", allowAddDeleteMethods);
     }
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java	Fri May 03 14:59:32 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
@@ -59,10 +59,10 @@
  * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD        <BR>
  * within debuggee's special methodForCommunication().                  <BR>
  * <BR>
- * In second phase to check the assetion,                               <BR>
+ * In second phase to check the assertion,                              <BR>
  * the debugger and the debuggee perform the following.                 <BR>
  * - The debugger creates three ThreadStartRequests with                <BR>
- *   addThreadFilter(debuggee's thread2) invoked only on third Request, <BR>
+ *   addThreadFilter(debuggee's thread2) invoked,                       <BR>
  *   resumes the debuggee and waits for the ThreadStartEvent.           <BR>
  * - Debuggee's main thread creates and starts new thread, thread2, and <BR>
  *   invokes the methodForCommunication                                 <BR>
@@ -330,14 +330,14 @@
 
             log2("......setting up ThreadStartRequest");
             ThreadStartRequest tsr1 = eventRManager.createThreadStartRequest();
-//            tsr1.addThreadFilter(testThread);
+            tsr1.addThreadFilter(testThread);
             tsr1.addCountFilter(1);
             tsr1.setSuspendPolicy(EventRequest.SUSPEND_ALL);
             tsr1.putProperty("number", "ThreadStartRequest1");
             tsr1.enable();
 
             ThreadStartRequest tsr2 = eventRManager.createThreadStartRequest();
-//            tsr2.addThreadFilter(testThread);
+            tsr2.addThreadFilter(testThread);
             tsr2.addCountFilter(1);
             tsr2.setSuspendPolicy(EventRequest.SUSPEND_ALL);
             tsr2.putProperty("number", "ThreadStartRequest2");
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp	Fri May 03 14:59:32 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
@@ -27,6 +27,7 @@
 #include <jvmti.h>
 #include <aod.h>
 #include <jvmti_aod.h>
+#include "ExceptionCheckingJniEnv.hpp"
 
 extern "C" {
 
@@ -67,23 +68,15 @@
 
 #define ATTACH002_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach002/attach002Target"
 
-int registerNativeMethods(JNIEnv* jni) {
+void registerNativeMethods(JNIEnv* jni_env) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jclass appClass;
     JNINativeMethod nativeMethods[] = {
             { (char*) "agentGotCapabilities", (char*) "()Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach002_attach002Target_agentGotCapabilities } };
     jint nativeMethodsNumber = 1;
 
-    appClass = jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME);
-    if (!NSK_JNI_VERIFY(jni, appClass != NULL)) {
-        return NSK_FALSE;
-    }
-
-    if (!NSK_JNI_VERIFY(jni,
-            (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) {
-        return NSK_FALSE;
-    }
-
-    return NSK_TRUE;
+    appClass = jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL);
+    jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL);
 }
 
 void JNICALL  classLoadHandler(
@@ -201,9 +194,7 @@
     if (!NSK_VERIFY(jvmti != NULL))
         return JNI_ERR;
 
-    if (!NSK_VERIFY(registerNativeMethods(jni))) {
-        return JNI_ERR;
-    }
+    registerNativeMethods(jni);
 
     memset(&caps, 0, sizeof(caps));
     caps.can_generate_all_class_hook_events = 1;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/libattach002Agent00.cpp	Fri May 03 14:59:32 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
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "ExceptionCheckingJniEnv.cpp"
 #include "native_thread.cpp"
 #include "nsk_tools.cpp"
 #include "jni_tools.cpp"
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp	Fri May 03 14:59:32 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
@@ -27,6 +27,7 @@
 #include <jvmti.h>
 #include <aod.h>
 #include <jvmti_aod.h>
+#include "ExceptionCheckingJniEnv.hpp"
 
 extern "C" {
 
@@ -87,24 +88,16 @@
      */
 }
 
-int registerNativeMethods(JNIEnv* jni) {
+void registerNativeMethods(JNIEnv* jni_env) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jclass appClass;
     JNINativeMethod nativeMethods[] = {
             { (char*) "setTagFor", (char*) "(Ljava/lang/Object;)Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_setTagFor },
             { (char*) "shutdownAgent", (char*) "()V", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_shutdownAgent } };
     jint nativeMethodsNumber = 2;
 
-    appClass = jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME);
-    if (!NSK_JNI_VERIFY(jni, appClass != NULL)) {
-        return NSK_FALSE;
-    }
-
-    if (!NSK_JNI_VERIFY(jni,
-            (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) {
-        return NSK_FALSE;
-    }
-
-    return NSK_TRUE;
+    appClass = jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL);
+    jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL);
 }
 
 #ifdef STATIC_BUILD
@@ -138,9 +131,7 @@
     if (!NSK_VERIFY(jvmti != NULL))
         return JNI_ERR;
 
-    if (!NSK_VERIFY(registerNativeMethods(jni))) {
-        return JNI_ERR;
-    }
+    registerNativeMethods(jni);
 
     memset(&caps, 0, sizeof(caps));
     caps.can_tag_objects = 1;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/libattach021Agent00.cpp	Fri May 03 14:59:32 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
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "ExceptionCheckingJniEnv.cpp"
 #include "native_thread.cpp"
 #include "nsk_tools.cpp"
 #include "jni_tools.cpp"
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp	Fri May 03 14:59:32 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
@@ -27,6 +27,7 @@
 #include <jvmti.h>
 #include <aod.h>
 #include <jvmti_aod.h>
+#include "ExceptionCheckingJniEnv.hpp"
 
 extern "C" {
 
@@ -64,7 +65,6 @@
 JNIEXPORT jboolean JNICALL
 Java_nsk_jvmti_AttachOnDemand_attach022_attach022Target_shutdownAgent(JNIEnv * jni,
         jclass klass, jint expectedTaggedObjectsCounter) {
-
     if (taggedObjectsCounter != expectedTaggedObjectsCounter) {
         success = 0;
         NSK_COMPLAIN2("ERROR: unexpected taggedObjectsCounter: %d (expected value is %d)\n", taggedObjectsCounter, expectedTaggedObjectsCounter);
@@ -97,24 +97,16 @@
 
 #define ATTACH022_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach022/attach022Target"
 
-int registerNativeMethods(JNIEnv* jni) {
+void registerNativeMethods(JNIEnv* jni_env) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jclass appClass;
     JNINativeMethod nativeMethods[] = {
             { (char*)"shutdownAgent", (char*)"(I)Z",
               (void*) Java_nsk_jvmti_AttachOnDemand_attach022_attach022Target_shutdownAgent } };
     jint nativeMethodsNumber = 1;
 
-    appClass = jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME);
-    if (!NSK_JNI_VERIFY(jni, appClass != NULL)) {
-        return NSK_FALSE;
-    }
-
-    if (!NSK_JNI_VERIFY(jni,
-            (jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber) == 0))) {
-        return NSK_FALSE;
-    }
-
-    return NSK_TRUE;
+    appClass = jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL);
+    jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL);
 }
 
 void JNICALL vmObjectAllocHandler(jvmtiEnv * jvmti,
@@ -190,9 +182,7 @@
     if (!NSK_VERIFY(jvmti != NULL))
         return JNI_ERR;
 
-    if (!NSK_VERIFY(registerNativeMethods(jni))) {
-        return JNI_ERR;
-    }
+    registerNativeMethods(jni);
 
     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("ObjectTagMonitor", &objectTagMonitor))) {
         return JNI_ERR;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/libattach022Agent00.cpp	Fri May 03 14:59:32 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
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "ExceptionCheckingJniEnv.cpp"
 #include "native_thread.cpp"
 #include "nsk_tools.cpp"
 #include "jni_tools.cpp"
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp	Fri May 03 14:59:32 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
@@ -25,7 +25,7 @@
 #include <string.h>
 #include <jvmti.h>
 #include "agent_common.h"
-
+#include "ExceptionCheckingJniEnv.hpp"
 #include "nsk_tools.h"
 #include "jni_tools.h"
 #include "JVMTITools.h"
@@ -305,7 +305,7 @@
 
 /***********************************************************************/
 
-static int startThread(JNIEnv* jni, jthread threadObj) {
+static int startThread(jthread threadObj) {
     int success = NSK_TRUE;
 
     /* enter startLock */
@@ -334,46 +334,26 @@
 }
 
 /** Create thread object for new agent thread. */
-static jthread newThreadObj(JNIEnv* jni) {
+static jthread newThreadObj(JNIEnv* jni_env) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jclass thrClass;
     jmethodID cid;
-    jthread result = NULL;
 
-    thrClass = jni->FindClass("java/lang/Thread");
-    if (!NSK_JNI_VERIFY(jni, thrClass != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return result;
-    }
-
-    cid = jni->GetMethodID(thrClass, "<init>", "()V");
-    if (!NSK_JNI_VERIFY(jni, cid != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return result;
-    }
-
-    result = jni->NewObject(thrClass, cid);
-    if (!NSK_JNI_VERIFY(jni, result != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return result;
-    }
-
-    return result;
+    thrClass = jni->FindClass("java/lang/Thread", TRACE_JNI_CALL);
+    cid = jni->GetMethodID(thrClass, "<init>", "()V", TRACE_JNI_CALL);
+    return jni->NewObject(thrClass, cid, TRACE_JNI_CALL);
 }
 
 /***********************************************************************/
 
 /** Clean counters and start new agent thread with agent_start() body. */
-static int prepareToIteration (JNIEnv* jni) {
+static int prepareToIteration(JNIEnv* jni) {
     jthread threadObj = NULL;
 
     setCounter(&iterationCount, 0);
     setCounter(&objectCount, 0);
 
     threadObj = newThreadObj(jni);
-    if (!NSK_VERIFY(threadObj != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return NSK_FALSE;
-    }
 
     /* enter endLock */
     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(endLock))) {
@@ -381,11 +361,11 @@
     }
 
     NSK_DISPLAY0("Starting new agent thread...\n");
-    return startThread(jni, threadObj);
+    return startThread(threadObj);
 }
 
 /** Wait for new agent thread to complete. */
-static void afterIteration (JNIEnv* jni) {
+static void afterIteration() {
 
     /* notify new agent thread (in case if not yet notified) */
     notifyThread();
@@ -433,7 +413,7 @@
     }
     NSK_DISPLAY0("IterateOverHeap finished.\n");
 
-    afterIteration(jni);
+    afterIteration();
 
     found = getCounter(&objectCount);
     NSK_DISPLAY1("Found tagged objects: %d\n", found);
@@ -464,7 +444,7 @@
     }
     NSK_DISPLAY0("IterateOverReachableObjects finished.\n");
 
-    afterIteration(jni);
+    afterIteration();
 
     found = getCounter(&objectCount);
     NSK_DISPLAY1("Found tagged objects: %d\n", found);
@@ -495,7 +475,7 @@
     }
     NSK_DISPLAY0("IterateOverInstancesOfClass finished.\n");
 
-    afterIteration(jni);
+    afterIteration();
 
     found = getCounter(&objectCount);
     NSK_DISPLAY1("Found tagged objects: %d\n", found);
@@ -509,20 +489,16 @@
 }
 
 JNIEXPORT void JNICALL
-Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject(JNIEnv* jni,
+Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject(JNIEnv* jni_env,
                                                                                            jclass  klass) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jobject root = NULL;
     int modified = 0;
     int found = 0;
 
-    root = jni->GetStaticObjectField(debugeeClass, rootFieldID);
-    if (!NSK_JNI_VERIFY(jni, root != NULL)) {
-        NSK_COMPLAIN0("GetStaticObjectField returned NULL for 'root' field value\n\n");
-        nsk_jvmti_setFailStatus();
-        return;
-    }
+    root = jni->GetStaticObjectField(debugeeClass, rootFieldID, TRACE_JNI_CALL);
 
-    if (!prepareToIteration(jni))
+    if (!prepareToIteration(jni_env))
         return;
 
     NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject...\n");
@@ -533,7 +509,7 @@
     }
     NSK_DISPLAY0("IterateOverObjectsReachableFromObject finished.\n");
 
-    afterIteration(jni);
+    afterIteration();
 
     found = getCounter(&objectCount);
     NSK_DISPLAY1("Found tagged objects: %d\n", found);
@@ -547,8 +523,8 @@
 }
 
 static void JNICALL
-agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
-
+agentProc(jvmtiEnv* jvmti, JNIEnv* jni_env, void* arg) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     NSK_DISPLAY0("Wait for debugee start\n\n");
     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
         return;
@@ -560,16 +536,11 @@
         return;
     }
 
-    debugeeClass = (jclass) jni->NewGlobalRef(debugeeClass);
-    if (!NSK_JNI_VERIFY(jni, debugeeClass != NULL))
-        return;
+    debugeeClass = (jclass) jni->NewGlobalRef(debugeeClass, TRACE_JNI_CALL);
 
     NSK_DISPLAY1("Find ID of 'root' field: %s\n", ROOT_SIGNATURE);
-    rootFieldID = jni->GetStaticFieldID(debugeeClass, "root", ROOT_SIGNATURE);
-    if (!NSK_JNI_VERIFY(jni, rootFieldID != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return;
-    }
+    rootFieldID = jni->GetStaticFieldID(debugeeClass, "root",
+                                        ROOT_SIGNATURE, TRACE_JNI_CALL);
 
     NSK_DISPLAY0("Let debugee to run test cases\n");
     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
@@ -579,7 +550,7 @@
     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
         return;
 
-    NSK_TRACE(jni->DeleteGlobalRef(debugeeClass));
+    jni->DeleteGlobalRef(debugeeClass, TRACE_JNI_CALL);
     NSK_TRACE(jvmti->DestroyRawMonitor(counterMonitor_ptr));
     NSK_TRACE(jvmti->DestroyRawMonitor(startLock));
     NSK_TRACE(jvmti->DestroyRawMonitor(runLock));
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/libap04t003.cpp	Fri May 03 14:59:32 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
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "ExceptionCheckingJniEnv.cpp"
 #include "native_thread.cpp"
 #include "nsk_tools.cpp"
 #include "jni_tools.cpp"
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp	Fri May 03 14:59:32 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
@@ -24,6 +24,7 @@
 #include <string.h>
 #include "jvmti.h"
 #include "agent_common.h"
+#include "ExceptionCheckingJniEnv.hpp"
 #include "jni_tools.h"
 #include "jvmti_tools.h"
 
@@ -47,23 +48,20 @@
  */
 JNIEXPORT jboolean JNICALL
 Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setNewByteCode(JNIEnv *jni_env,
-                        jobject o, jbyteArray byteCode) {
-
+                                                              jobject o,
+                                                              jbyteArray byteCode) {
+    ExceptionCheckingJniEnvPtr jni(jni_env);
     jbyte* elements;
     jboolean isCopy;
 
-    newClassSize = jni_env->GetArrayLength(byteCode);
-    if (!NSK_JNI_VERIFY(jni_env, newClassSize > 0)) {
+    newClassSize = jni->GetArrayLength(byteCode, TRACE_JNI_CALL);
+    if (newClassSize <= 0) {
         nsk_jvmti_setFailStatus();
         return NSK_FALSE;
     }
     NSK_DISPLAY1("\t... got array size: %d\n", newClassSize);
 
-    elements = jni_env->GetByteArrayElements(byteCode, &isCopy);
-    if (!NSK_JNI_VERIFY(jni_env, elements != NULL)) {
-        nsk_jvmti_setFailStatus();
-        return NSK_FALSE;
-    }
+    elements = jni->GetByteArrayElements(byteCode, &isCopy, TRACE_JNI_CALL);
     NSK_DISPLAY1("\t... got elements list: 0x%p\n", (void*)elements);
 
     if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize, &newClassBytes))) {
@@ -80,7 +78,7 @@
     NSK_DISPLAY1("\t... copied bytecode: %d bytes\n", (int)newClassSize);
 
     NSK_DISPLAY1("\t... release elements list: 0x%p\n", (void*)elements);
-    NSK_TRACE(jni_env->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT));
+    jni->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT, TRACE_JNI_CALL);
     NSK_DISPLAY0("\t... released\n");
     return NSK_TRUE;
 }
@@ -94,11 +92,8 @@
 JNIEXPORT void JNICALL
 Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setClass(JNIEnv *jni_env,
                         jobject o, jclass cls) {
-
-    oldClassDef.klass = (jclass) jni_env->NewGlobalRef(cls);
-    if (!NSK_JNI_VERIFY(jni_env, oldClassDef.klass != NULL)) {
-        nsk_jvmti_setFailStatus();
-    }
+    ExceptionCheckingJniEnvPtr jni(jni_env);
+    oldClassDef.klass = (jclass) jni->NewGlobalRef(cls, TRACE_JNI_CALL);
 }
 
 /* ============================================================================= */
@@ -154,6 +149,7 @@
 /** Agent algorithm. */
 static void JNICALL
 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
+    ExceptionCheckingJniEnvPtr jni(agentJNI);
 
     /*Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1*/
     NSK_DISPLAY0("Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1\n");
@@ -214,7 +210,7 @@
     if (!nsk_jvmti_waitForSync(timeout))
         return;
 
-    agentJNI->DeleteGlobalRef(oldClassDef.klass);
+    jni->DeleteGlobalRef(oldClassDef.klass, TRACE_JNI_CALL);
 
     NSK_DISPLAY0("Let debuggee to finish\n");
     if (!nsk_jvmti_resumeSync())
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/libbi01t001.cpp	Fri May 03 14:59:32 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
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#include "ExceptionCheckingJniEnv.cpp"
 #include "native_thread.cpp"
 #include "nsk_tools.cpp"
 #include "jni_tools.cpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+package nsk.share.ExceptionCheckingJniEnv;
+
+import java.io.PrintStream;
+
+public class exceptionjni001 {
+    static {
+        try {
+            System.loadLibrary("exceptionjni001");
+        } catch (UnsatisfiedLinkError ule) {
+            System.err.println("Could not load exceptionjni001 library");
+            System.err.println("java.library.path:"
+                + System.getProperty("java.library.path"));
+            throw ule;
+        }
+    }
+
+    // A field the JNI code can try to get.
+    int anInteger;
+
+    // Check the exception checking code.
+    native static boolean check();
+
+    public static void main(String args[]) {
+        if (!check()) {
+          throw new RuntimeException("Problem with ExceptionCheckingJniEnv");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/TestDescription.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+
+/*
+ * @test
+ *
+ * @summary test the ExceptionCheckingJniEnv system.
+ * DESCRIPTION
+ *     The test exercise the ExceptionCheckingJniEnv system.
+ *
+ * @library /vmTestbase
+ *          /test/lib
+ * @run driver jdk.test.lib.FileInstaller . .
+ * @run main/othervm/native -agentlib:exceptionjni001 nsk.share.ExceptionCheckingJniEnv.exceptionjni001
+ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/exceptionjni001.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jvmti.h"
+#include "ExceptionCheckingJniEnv.hpp"
+
+// A few static global variables required due to the callback nature of JNI
+// methods.
+static bool is_error_called;
+static const char* const null_return_expected_message_start =
+    "JNI method GetFieldID : Return is NULL from exceptionjni001.cpp : ";
+static const char* const null_file_expected_message_start =
+    "JNI method GetFieldID : Return is NULL from Unknown File : ";
+
+// Used by the ErrorCheckerMessage and the tests to determine test success.
+static long expected_line_number;
+static bool error_message_ok;
+static const char* expected_message_start;
+
+static bool CheckMessage(JNIEnv* env, const char* message, const char* expected_message,
+                         long expected_line) {
+  if (strstr(message, expected_message) != message) {
+    fprintf(stderr, "Message does not start as expected:\n\t%s\n\t%s\n",
+            message, expected_message);
+    return false;
+  }
+
+  size_t len = strlen(expected_message);
+
+  char* end_ptr = NULL;
+  long actual_line = strtol(message + len, &end_ptr, 0);
+
+  if (end_ptr == NULL || *end_ptr != '\0') {
+    fprintf(stderr, "end_ptr == NULL or *end_ptr terminating from %s\n", message);
+    return false;
+  }
+
+  if (actual_line != expected_line) {
+    fprintf(stderr, "Actual line does not match expected:\n");
+    fprintf(stderr, "\tActual: %ld\n\tExpected: %ld\n\tfrom: %s (%s)\n",
+            actual_line, expected_line, message, message + len);
+    return false;
+  }
+
+  // Clear the exception if everything lines up.
+  env->ExceptionClear();
+  return true;
+}
+
+static void ErrorCheckerMessage(JNIEnv* env, const char* error_message) {
+  is_error_called = true;
+  error_message_ok = CheckMessage(env, error_message, expected_message_start,
+                                  expected_line_number);
+}
+
+static bool checkSuccess(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+  is_error_called = false;
+
+  jni->GetFieldID(cls, "anInteger", "I", TRACE_JNI_CALL);
+  return !is_error_called;
+}
+
+static bool checkFailureMessageReturnNull(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_return_expected_message_start;
+  expected_line_number = __LINE__ + 1;
+  jni->GetFieldID(cls, "whatever", "does not matter", TRACE_JNI_CALL);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool checkFailureMessageEmptyFile(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_file_expected_message_start;
+  expected_line_number = __LINE__ + 1;
+  jni->GetFieldID(cls, "whatever", "does not matter", __LINE__, NULL);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool checkFailureMessageNilLine(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_return_expected_message_start;
+  expected_line_number = 0;
+  jni->GetFieldID(cls, "whatever", "does not matter", 0, __FILE__);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool checkFailureMessageNegativeLine(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_return_expected_message_start;
+  expected_line_number = -1;
+  jni->GetFieldID(cls, "whatever", "does not matter", -1, __FILE__);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool checkFailureMessageMinLine(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_return_expected_message_start;
+  expected_line_number = INT32_MIN;
+  jni->GetFieldID(cls, "whatever", "does not matter", INT32_MIN, __FILE__);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool checkFailureMessageMaxLine(JNIEnv* env, jclass cls) {
+  ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage);
+
+  expected_message_start = null_return_expected_message_start;
+  expected_line_number = INT32_MAX;
+  jni->GetFieldID(cls, "whatever", "does not matter", INT32_MAX, __FILE__);
+
+  return is_error_called && error_message_ok;
+}
+
+static bool CheckExceptionJni(JNIEnv* env, jclass cls) {
+  typedef bool (*TestExceptionJniWrapper)(JNIEnv* env, jclass cls);
+
+  TestExceptionJniWrapper tests[] = {
+    checkSuccess,
+    checkFailureMessageReturnNull,
+    checkFailureMessageEmptyFile,
+    checkFailureMessageNilLine,
+    checkFailureMessageNegativeLine,
+    checkFailureMessageMinLine,
+    checkFailureMessageMaxLine,
+  };
+
+  size_t max_tests = sizeof(tests) / sizeof(tests[0]);
+  for (size_t i = 0; i < max_tests; i++) {
+    is_error_called = false;
+    error_message_ok = false;
+    if (!tests[i](env, cls)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+extern "C" {
+
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+  return JNI_OK;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_nsk_share_ExceptionCheckingJniEnv_exceptionjni001_check(JNIEnv *env, jclass cls) {
+  return CheckExceptionJni(env, cls);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/libexceptionjni001.cpp	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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 "nsk_tools.cpp"
+#include "agent_common.cpp"
+#include "exceptionjni001.cpp"
+#include "ExceptionCheckingJniEnv.cpp"
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jboolean JNICALL Java_nsk_share_gc_lock_jni_BooleanArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jbooleanArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jbooleanArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jbooleanArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jboolean*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jboolean*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = JNI_FALSE;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -36,7 +36,7 @@
  */
 JNIEXPORT jbyte JNICALL Java_nsk_share_gc_lock_jni_ByteArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jbyteArray arr;
@@ -45,18 +45,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jbyteArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jbyteArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jbyte*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jbyte*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -64,11 +64,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_CharArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jcharArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jcharArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jcharArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         current_time = 0;
         enterTime /= 1000;
         while (current_time - start_time < enterTime) {
-                pa = (jchar*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jchar*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jdouble JNICALL Java_nsk_share_gc_lock_jni_DoubleArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jdoubleArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jdoubleArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jdoubleArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jdouble*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jdouble*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash += pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jfloat JNICALL Java_nsk_share_gc_lock_jni_FloatArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jfloatArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jfloatArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jfloatArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jfloat*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jfloat*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash += pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jint JNICALL Java_nsk_share_gc_lock_jni_IntArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jintArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jintArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jintArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jint*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jint*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jlong JNICALL Java_nsk_share_gc_lock_jni_LongArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jlongArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jlongArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jlongArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jlong*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jlong*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jshort JNICALL Java_nsk_share_gc_lock_jni_ShortArrayCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jshortArray arr;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        arr = (jshortArray) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        arr = (jshortArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetArrayLength(arr);
+        size = jni->GetArrayLength(arr, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = (jshort*) env->GetPrimitiveArrayCritical(arr, NULL);
+                pa = (jshort*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = 0;
                 }
                 mssleep((long) sleepTime);
-                env->ReleasePrimitiveArrayCritical(arr, pa, 0);
+                jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, arr);
+        jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp	Fri May 03 14:59:32 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
@@ -37,7 +37,7 @@
  */
 JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_StringCriticalLocker_criticalNative
 (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jsize size, i;
         jstring str;
@@ -46,18 +46,18 @@
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        str = (jstring) env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        str = (jstring) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
-        size = env->GetStringLength(str);
+        size = jni->GetStringLength(str, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                pa = env->GetStringCritical(str, NULL);
+                pa = jni->GetStringCritical(str, NULL, TRACE_JNI_CALL);
                 if (pa != NULL) {
                         for (i = 0; i < size; ++i)
                                 hash ^= pa[i];
@@ -65,11 +65,11 @@
                         hash = JNI_FALSE;
                 }
                 mssleep((long) sleepTime);
-                env->ReleaseStringCritical(str, pa);
+                jni->ReleaseStringCritical(str, pa, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, str);
+        jni->SetObjectField(o, objFieldId, str, TRACE_JNI_CALL);
         return hash;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp	Fri May 03 14:59:32 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
@@ -38,29 +38,29 @@
  */
 JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIGlobalRefLocker_criticalNative
   (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jobject obj;
         jobject gref;
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        obj = env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                gref = env->NewGlobalRef(obj);
+                gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
-                env->DeleteGlobalRef(gref);
+                jni->DeleteGlobalRef(gref, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, obj);
+        jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL);
 }
 
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp	Fri May 03 14:59:32 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
@@ -37,29 +37,29 @@
  */
 JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNILocalRefLocker_criticalNative
   (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jobject obj;
         jobject gref;
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        obj = env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                gref = env->NewLocalRef(obj);
+                gref = jni->NewLocalRef(obj, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
-                env->DeleteLocalRef(gref);
+                jni->DeleteLocalRef(gref, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, obj);
+        jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL);
 }
 
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp	Fri May 03 14:59:32 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
@@ -37,35 +37,35 @@
  */
 JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIRefLocker_criticalNative
   (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jobject obj;
         jobject gref, lref, gwref;
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
 
-        obj = env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                gref = env->NewGlobalRef(obj);
-                lref = env->NewLocalRef(obj);
-                gwref = env->NewWeakGlobalRef(obj);
+                gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL);
+                lref = jni->NewLocalRef(obj, TRACE_JNI_CALL);
+                gwref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
-                env->DeleteGlobalRef(gref);
-                env->DeleteLocalRef(lref);
-                env->DeleteWeakGlobalRef(gwref);
+                jni->DeleteGlobalRef(gref, TRACE_JNI_CALL);
+                jni->DeleteLocalRef(lref, TRACE_JNI_CALL);
+                jni->DeleteWeakGlobalRef(gwref, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, obj);
+        jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL);
 }
 
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp	Fri May 03 14:59:32 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
@@ -37,30 +37,30 @@
  */
 JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIWeakGlobalRefLocker_criticalNative
   (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) {
-        ExceptionCheckingJniEnvPtr env(jni_env);
+        ExceptionCheckingJniEnvPtr jni(jni_env);
 
         jobject obj;
         jobject gref;
         time_t start_time, current_time;
 
         if (objFieldId == NULL) {
-                jclass klass = env->GetObjectClass(o);
-                objFieldId = env->GetFieldID(klass, "obj", "Ljava/lang/Object;");
+                jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL);
+                objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL);
         }
-        obj = env->GetObjectField(o, objFieldId);
-        env->SetObjectField(o, objFieldId, NULL);
+        obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL);
+        jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL);
 
         start_time = time(NULL);
         enterTime /= 1000;
         current_time = 0;
         while (current_time - start_time < enterTime) {
-                gref = env->NewWeakGlobalRef(obj);
+                gref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
-                env->DeleteWeakGlobalRef(gref);
+                jni->DeleteWeakGlobalRef(gref, TRACE_JNI_CALL);
                 mssleep((long) sleepTime);
                 current_time = time(NULL);
         }
-        env->SetObjectField(o, objFieldId, obj);
+        jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL);
 }
 
 }
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -22,66 +22,176 @@
  * questions.
  */
 
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "ExceptionCheckingJniEnv.hpp"
+#include "nsk_tools.h"
 
 namespace {
 
+static const char* get_dirname(const char* fullname) {
+  const char* p;
+  const char* base = fullname;;
+
+  if (fullname == NULL) {
+    return NULL;
+  }
+
+  for (p = fullname; *p != '\0'; p++) {
+    if (*p == '/' || *p == '\\') {
+      base = p + 1;
+    }
+  }
+  return base;
+}
+
 template<class T = void*>
 class JNIVerifier {
  public:
-  JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_msg)
-      : _env(env), _base_msg(base_msg), _return_error(NULL) {
+  JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
+              int line, const char* file)
+      : _env(env), _base_message(base_message), _error_message(NULL),
+        _line(line), _file(get_dirname(file)) {
+  }
+
+  // Until C++11 is supported, we have to write multiple template constructors.
+  template <typename U>
+  JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
+              U parameter,
+              int line, const char* file)
+      : _env(env), _base_message(base_message), _error_message(NULL),
+        _line(line), _file(get_dirname(file)) {
+          PrintPreCall(parameter);
+  }
+
+  template <typename U, typename V>
+  JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
+              U parameter1,
+              V parameter2,
+              int line, const char* file)
+      : _env(env), _base_message(base_message), _error_message(NULL),
+        _line(line), _file(get_dirname(file)) {
+          PrintPreCall(parameter1, parameter2);
+  }
+
+  template <typename U, typename V, typename W>
+  JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
+              U parameter1, V parameter2, W parameter3,
+              int line, const char* file)
+      : _env(env), _base_message(base_message), _error_message(NULL),
+        _line(line), _file(get_dirname(file)) {
+          PrintPreCall(parameter1, parameter2, parameter3);
   }
 
   ~JNIVerifier() {
+    PrintPostCall();
+
     JNIEnv* jni_env = _env->GetJNIEnv();
-    if (jni_env->ExceptionCheck()) {
-      _env->HandleError(_base_msg);
+    if (jni_env->ExceptionCheck() && !_error_message) {
+      _error_message = "internal error";
+    }
+
+    if (_error_message != NULL) {
+      GenerateErrorMessage();
+    }
+  }
+
+  int DecimalToAsciiRec(char *str, int line) {
+    if (line == 0) {
+      return 0;
+    }
+
+    int remainder = line % 10;
+    long quotient = line / 10;
+
+    int pos = DecimalToAsciiRec(str, quotient);
+    str[pos] = '0' + remainder;
+    return pos + 1;
+  }
+
+  // Implementing a simple version of sprintf for "%d"...
+  void DecimalToAscii(char *str, int line) {
+    if (line == 0) {
+      str[0] = '0';
+      str[1] = '\0';
       return;
     }
 
-    if (_return_error != NULL) {
-      ProcessReturnError();
+    // Special case for INT32_MIN because otherwise the *1 below will overflow
+    // and it won't work. Let us just be simple here due to this being for
+    // tests.
+    if (line == INT32_MIN) {
+      strcat(str, "-2147483648");
+      return;
     }
+
+    if (line < 0) {
+      *str = '-';
+      line *= -1;
+      str++;
+    }
+
+    str[DecimalToAsciiRec(str, line)] = '\0';
   }
 
-  void ProcessReturnError() {
+  void GenerateErrorMessage() {
     // This is error prone, but:
     //   - Seems like we cannot use std::string (due to windows/solaris not
     //   building when used, seemingly due to exception libraries not linking).
     //   - Seems like we cannot use sprintf due to VS2013 (JDK-8213622).
     //
     //   We are aiming to do:
-    //     snprintf(full_message, len, "%s : %s", _base_msg, _return_error);
+    //     snprintf(full_message, len, "JNI method %s : %s from %s : %d", _base_message, _error_message,
+    //              _file, _line);
     //   but will use strlen + memcpy instead.
-    size_t base_len = strlen(_base_msg);
+    const char* pre_message = "JNI method ";
     const char* between_msg = " : ";
-    size_t between_len = strlen(between_msg);
-    size_t return_len = strlen(_return_error);
+    const char* from_msg = " from ";
 
-    // +1 for the '\0'
-    size_t len = base_len + between_len + return_len + 1;
+    const char* file_name = _file ? _file : "Unknown File";
+    const char* strs[] = {
+      pre_message,
+      _base_message,
+      between_msg,
+      _error_message,
+      from_msg,
+      file_name,
+      between_msg,
+    };
+
+    size_t msg_number = sizeof(strs) / sizeof(strs[0]);
+    size_t len = 0;
+    for (size_t i = 0; i < msg_number; i++) {
+      len += strlen(strs[i]);
+    }
+
+    // 32-bit signed means 11 characters due to the '-'.
+    const int MAX_INTEGER_DIGITS = 11;
+    // Add for the line number and 1 for the '\0'.
+    len += MAX_INTEGER_DIGITS + 1;
 
     char* full_message = (char*) malloc(len);
     if (full_message == NULL) {
-      _env->HandleError(_return_error);
+      _env->HandleError(_error_message);
       return;
     }
 
-    // Now we construct the string using memcpy to not use sprintf/std::string
+    // Now we construct the string using strcat to not use sprintf/std::string
     // instead of:
-    //     snprintf(full_message, len, "%s : %s", _base_msg, _return_error);
-    memcpy(full_message, _base_msg, base_len);
-    memcpy(full_message + base_len, between_msg, between_len);
-    memcpy(full_message + base_len + between_len, _return_error, return_len);
-    full_message[len - 1] = '\0';
+    //     snprintf(full_message, len, "JNI method %s : %s from %s:%d", _base_message,
+    //         _error_message, _file, _line);
+    full_message[0] = '\0';
+    for (size_t i = 0; i < msg_number; i++) {
+      strcat(full_message, strs[i]);
+    }
 
-    // -1 due to the '\0' not counted by strlen but is counted for the allocation.
-    if (strlen(full_message) != len - 1) {
-      _env->GetJNIEnv()->FatalError("Length of message is not what was expected");
+    // Add line number to end of the string.
+    DecimalToAscii(full_message + strlen(full_message), _line);
+
+    if (strlen(full_message) >= len) {
+      _env->GetJNIEnv()->FatalError("Final length of message is not what was expected");
     }
 
     _env->HandleError(full_message);
@@ -90,95 +200,240 @@
 
   T ResultNotNull(T ptr) {
     if (ptr == NULL) {
-      _return_error = "Return is NULL";
+      _error_message = "Return is NULL";
     }
     return ptr;
   }
 
+  T ResultIsZero(T value) {
+    if (value != 0) {
+      _error_message = "Return is not zero";
+    }
+    return value;
+  }
+
+  void PrintPreCallHeader() {
+    if (!nsk_getVerboseMode()) {
+      return;
+    }
+
+    fprintf(stdout, ">> Calling JNI method %s from %s:%d\n",
+            _base_message, _file, _line);
+    fprintf(stdout, ">> Calling with these parameter(s):\n");
+  }
+
+  // Until we can actually link with C++ more uniformely across architectures,
+  // we have to do this...
+  template<class U>
+  void PrintParameter(U* ptr) {
+    fprintf(stdout, "\t%p\n", ptr);
+  }
+
+  void PrintParameter(int value) {
+    fprintf(stdout, "\t%d\n", value);
+  }
+
+  // Until C++11 is supported, we have to write multiple PrintPreCall.
+  template<class U>
+  void PrintPreCall(U first_parameter) {
+    if (!nsk_getVerboseMode()) {
+      return;
+    }
+
+    PrintPreCallHeader();
+    PrintParameter(first_parameter);
+  }
+
+  template<class U, class V>
+  void PrintPreCall(U parameter1, V parameter2) {
+    if (!nsk_getVerboseMode()) {
+      return;
+    }
+
+    PrintPreCallHeader();
+    PrintParameter(parameter1);
+    PrintParameter(parameter2);
+  }
+
+  template<class U, class V, class W>
+  void PrintPreCall(U parameter1, V parameter2, W parameter3) {
+    if (!nsk_getVerboseMode()) {
+      return;
+    }
+
+    PrintPreCallHeader();
+    PrintParameter(parameter1);
+    PrintParameter(parameter2);
+    PrintParameter(parameter3);
+  }
+
+  void PrintPostCall() {
+    if (!nsk_getVerboseMode()) {
+      return;
+    }
+
+    fprintf(stderr, "<< Called JNI method %s from %s:%d\n",
+            _base_message, _file, _line);
+  }
+
  private:
   ExceptionCheckingJniEnv* _env;
-  const char* const _base_msg;
-  const char* _return_error;
+  const char* const _base_message;
+  const char* _error_message;
+  int _line;
+  const char* const _file;
 };
 
 }
 
-jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj) {
-  JNIVerifier<jclass> marker(this, "GetObjectClass");
+jclass ExceptionCheckingJniEnv::FindClass(const char *class_name,
+                                          int line, const char* file_name) {
+  JNIVerifier<jclass> marker(this, "FindClass", class_name, line, file_name);
+  return marker.ResultNotNull(_jni_env->FindClass(class_name));
+}
+
+jint ExceptionCheckingJniEnv::RegisterNatives(jclass clazz,
+                                              const JNINativeMethod *methods,
+                                              jint nMethods,
+                                              int line,
+                                              const char* file_name) {
+  JNIVerifier<jint> marker(this, "RegisterNatives", methods, nMethods, line, file_name);
+  return marker.ResultIsZero(_jni_env->RegisterNatives(clazz, methods, nMethods));
+}
+
+jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj, int line,
+                                               const char* file_name) {
+  JNIVerifier<jclass> marker(this, "GetObjectClass", obj, line, file_name);
   return marker.ResultNotNull(_jni_env->GetObjectClass(obj));
 }
 
-jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name, const char* type) {
-  JNIVerifier<jfieldID> marker(this, "GetFieldID");
+jfieldID ExceptionCheckingJniEnv::GetStaticFieldID(jclass klass, const char *name,
+                                                   const char* type,
+                                                   int line, const char* file_name) {
+  JNIVerifier<jfieldID> marker(this, "GetStaticFieldID", klass, name, type,
+                               line, file_name);
+  return marker.ResultNotNull(_jni_env->GetStaticFieldID(klass, name, type));
+}
+
+jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name,
+                                             const char* type,
+                                             int line, const char* file_name) {
+  JNIVerifier<jfieldID> marker(this, "GetFieldID", klass, name, type, line, file_name);
   return marker.ResultNotNull(_jni_env->GetFieldID(klass, name, type));
 }
 
-jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field) {
-  JNIVerifier<jobject> marker(this, "GetObjectField");
+jobject ExceptionCheckingJniEnv::GetStaticObjectField(jclass klass, jfieldID field,
+                                                      int line, const char* file_name) {
+  JNIVerifier<jobject> marker(this, "GetStaticObjectField", klass, field,
+                              line, file_name);
+  return marker.ResultNotNull(_jni_env->GetStaticObjectField(klass, field));
+}
+
+jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field,
+                                                int line, const char* file_name) {
+  JNIVerifier<jobject> marker(this, "GetObjectField", obj, field, line, file_name);
   return marker.ResultNotNull(_jni_env->GetObjectField(obj, field));
 }
 
-void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value) {
-  JNIVerifier<> marker(this, "SetObjectField");
+void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value,
+                                             int line, const char* file_name) {
+  JNIVerifier<> marker(this, "SetObjectField", obj, field, value, line, file_name);
   _jni_env->SetObjectField(obj, field, value);
 }
 
-jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj) {
-  JNIVerifier<jobject> marker(this, "NewGlobalRef");
+jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj, int line, const char* file_name) {
+  JNIVerifier<jobject> marker(this, "NewGlobalRef", obj, line, file_name);
   return marker.ResultNotNull(_jni_env->NewGlobalRef(obj));
 }
 
-void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj) {
-  JNIVerifier<> marker(this, "DeleteGlobalRef");
+void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj, int line, const char* file_name) {
+  JNIVerifier<> marker(this, "DeleteGlobalRef", obj, line, file_name);
   _jni_env->DeleteGlobalRef(obj);
 }
 
-jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj) {
-  JNIVerifier<jobject> marker(this, "NewLocalRef");
+jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj, int line, const char* file_name) {
+  JNIVerifier<jobject> marker(this, "NewLocalRef", obj, line, file_name);
   return marker.ResultNotNull(_jni_env->NewLocalRef(obj));
 }
 
-void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj) {
-  JNIVerifier<> marker(this, "DeleteLocalRef");
+void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj, int line, const char* file_name) {
+  JNIVerifier<> marker(this, "DeleteLocalRef", obj, line, file_name);
   _jni_env->DeleteLocalRef(obj);
 }
 
-jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj) {
-  JNIVerifier<jweak> marker(this, "NewWeakGlobalRef");
+jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj, int line, const char* file_name) {
+  JNIVerifier<jweak> marker(this, "NewWeakGlobalRef", obj, line, file_name);
   return marker.ResultNotNull(_jni_env->NewWeakGlobalRef(obj));
 }
 
-void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref) {
-  JNIVerifier<> marker(this, "DeleteWeakGlobalRef");
+void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref, int line, const char* file_name) {
+  JNIVerifier<> marker(this, "DeleteWeakGlobalRef", weak_ref, line, file_name);
   _jni_env->DeleteWeakGlobalRef(weak_ref);
 }
 
-jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array) {
-  JNIVerifier<> marker(this, "GetArrayLength");
+jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array, int line, const char* file_name) {
+  JNIVerifier<> marker(this, "GetArrayLength", array, line, file_name);
   return _jni_env->GetArrayLength(array);
 }
 
-jsize ExceptionCheckingJniEnv::GetStringLength(jstring str) {
-  JNIVerifier<> marker(this, "GetStringLength");
+jsize ExceptionCheckingJniEnv::GetStringLength(jstring str, int line, const char* file_name) {
+  JNIVerifier<> marker(this, "GetStringLength", str, line, file_name);
   return _jni_env->GetStringLength(str);
 }
 
-void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) {
-  JNIVerifier<> marker(this, "GetPrimitiveArrayCritical");
-  return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, isCopy));
+void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* is_copy,
+                                                         int line, const char* file_name) {
+  JNIVerifier<> marker(this, "GetPrimitiveArrayCritical", array, is_copy, line, file_name);
+  return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, is_copy));
 }
 
-void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) {
-  JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical");
+void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode,
+                                                            int line, const char* file_name) {
+  JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical", array, carray, mode,
+                       line, file_name);
   _jni_env->ReleasePrimitiveArrayCritical(array, carray, mode);
 }
 
-const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* isCopy) {
-  JNIVerifier<const jchar*> marker(this, "GetPrimitiveArrayCritical");
-  return marker.ResultNotNull(_jni_env->GetStringCritical(str, isCopy));
+const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* is_copy,
+                                                        int line, const char* file_name) {
+  JNIVerifier<const jchar*> marker(this, "GetPrimitiveArrayCritical", str, is_copy,
+                                   line, file_name);
+  return marker.ResultNotNull(_jni_env->GetStringCritical(str, is_copy));
+}
+
+void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray,
+                                                    int line, const char* file_name) {
+  JNIVerifier<> marker(this, "ReleaseStringCritical", str, carray, line, file_name);
+  _jni_env->ReleaseStringCritical(str, carray);
+}
+
+jbyte* ExceptionCheckingJniEnv::GetByteArrayElements(jbyteArray array, jboolean* is_copy,
+                                                   int line, const char* file_name) {
+  JNIVerifier<jbyte*> marker(this, "GetByteArrayElements", array, is_copy, line, file_name);
+  return marker.ResultNotNull(_jni_env->GetByteArrayElements(array, is_copy));
 }
 
-void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray) {
-  JNIVerifier<> marker(this, "ReleaseStringCritical");
-  _jni_env->ReleaseStringCritical(str, carray);
+void ExceptionCheckingJniEnv::ReleaseByteArrayElements(jbyteArray array, jbyte* byte_array, jint mode,
+                                                       int line, const char* file_name) {
+  JNIVerifier<> marker(this, "ReleaseByteArrayElements", array, byte_array, mode,
+                       line, file_name);
+  _jni_env->ReleaseByteArrayElements(array, byte_array, mode);
+}
+
+jmethodID ExceptionCheckingJniEnv::GetMethodID(jclass klass, const char* name, const char* sig,
+                                               int line, const char* file_name) {
+  JNIVerifier<jmethodID> marker(this, "GetMethodID", klass, name, sig, line, file_name);
+  return marker.ResultNotNull(_jni_env->GetMethodID(klass, name, sig));
 }
+
+jobject ExceptionCheckingJniEnv::NewObject(jclass klass, jmethodID methodID,
+                                           int line, const char* file_name, ...) {
+  // In the case of NewObject, we miss the extra arguments passed to NewObject sadly.
+  JNIVerifier<jobject> marker(this, "NewObject", klass, methodID, line, file_name);
+
+  va_list args;
+  va_start(args, file_name);
+  jobject result = marker.ResultNotNull(_jni_env->NewObjectV(klass, methodID, args));
+  va_end(args);
+  return result;
+}
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp	Fri May 03 14:59:32 2019 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -46,40 +46,65 @@
  *
  *  Can be simplified to:
  * ... ExceptionCheckingJniEnv* env ...
- *  jclass klass = env->GetObjectClass(o);
+ *  jclass klass = env->GetObjectClass(o, TRACE_JNI_CALL);
  *
  *  Where now the JNI Exception checking and the NULL return checking are done
  *  internally and will perform whatever action the ErrorHandler requires.
  *
+ *  Note the TRACE_JNI_CALL parameter that allows to trace where the call is
+ *  happening from for debugging.
+ *
  *  By default, the error handler describes the exception via the JNI
  *  ExceptionDescribe method and calls FatalError.
- *
- *  Note: at a future date, this will also include the tracing mechanism done in
- *  NSK_VERIFY, which will thus embed its logic into the ExceptionCheckingJniEnv
- *  and clearing that up for the code readers and writers.
  */
+
+#define TRACE_JNI_CALL __LINE__, __FILE__
+
 class ExceptionCheckingJniEnv {
  public:
   // JNIEnv API redefinitions.
-  jfieldID GetFieldID(jclass klass, const char *name, const char* type);
-  jclass GetObjectClass(jobject obj);
-  jobject GetObjectField(jobject obj, jfieldID field);
-  void SetObjectField(jobject obj, jfieldID field, jobject value);
+  jclass FindClass(const char *name, int line, const char* file_name);
+
+  jfieldID GetStaticFieldID(jclass klass, const char* name, const char* type,
+                            int line, const char* file_name);
+  jfieldID GetFieldID(jclass klass, const char* name, const char* type,
+                      int line, const char* file_name);
+  jmethodID GetMethodID(jclass klass, const char* name, const char* sig,
+                        int line, const char* file_name);
 
-  jsize GetArrayLength(jarray array);
-  jsize GetStringLength(jstring str);
+  jclass GetObjectClass(jobject obj, int line, const char* file_name);
+  jobject GetObjectField(jobject obj, jfieldID field, int line, const char* file_name);
+  jobject GetStaticObjectField(jclass kls, jfieldID field, int line, const char* file_name);
+  void SetObjectField(jobject obj, jfieldID field, jobject value,
+                      int line, const char* file_name);
+
+  jsize GetArrayLength(jarray array, int line, const char* file_name);
+  jsize GetStringLength(jstring str, int line, const char* file_name);
 
-  void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy);
-  void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode);
-  const jchar* GetStringCritical(jstring str, jboolean* isCopy);
-  void ReleaseStringCritical(jstring str, const jchar* carray);
+  void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy,
+                                  int line, const char* file_name);
+  void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode,
+                                     int line, const char* file_name);
+  const jchar* GetStringCritical(jstring str, jboolean* isCopy,
+                                 int line, const char* file_name);
+  void ReleaseStringCritical(jstring str, const jchar* carray,
+                             int line, const char* file_name);
 
-  jobject NewGlobalRef(jobject obj);
-  void DeleteGlobalRef(jobject obj);
-  jobject NewLocalRef(jobject ref);
-  void DeleteLocalRef(jobject ref);
-  jweak NewWeakGlobalRef(jobject obj);
-  void DeleteWeakGlobalRef(jweak obj);
+  jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy,
+                              int line, const char* file_name);
+  void ReleaseByteArrayElements(jbyteArray array, jbyte* byte_array, jint mode,
+                                int line, const char* file_name);
+  jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods,
+                       int line, const char* file_name);
+
+  jobject NewObject(jclass kls, jmethodID methodID,
+                    int line, const char* file_name, ...);
+  jobject NewGlobalRef(jobject obj, int line, const char* file_name);
+  void DeleteGlobalRef(jobject obj, int line, const char* file_name);
+  jobject NewLocalRef(jobject ref, int line, const char* file_name);
+  void DeleteLocalRef(jobject ref, int line, const char* file_name);
+  jweak NewWeakGlobalRef(jobject obj, int line, const char* file_name);
+  void DeleteWeakGlobalRef(jweak obj, int line, const char* file_name);
 
   // ExceptionCheckingJniEnv methods.
   JNIEnv* GetJNIEnv() {
--- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/stress/parallelLoad/Test.java	Fri May 03 14:59:32 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
@@ -38,7 +38,7 @@
  * @run driver vm.mlvm.share.IndifiedClassesBuilder
  *
  * @run main/othervm
- *      -XX:+BytecodeVerificationLocal
+ *      -Xverify:all
  *      vm.mlvm.anonloader.stress.parallelLoad.Test
  *      -threadsPerCpu 4
  *      -threadsExtra 20
--- a/test/jaxp/javax/xml/jaxp/unittest/dom/DocumentTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jaxp/javax/xml/jaxp/unittest/dom/DocumentTest.java	Fri May 03 14:59:32 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
@@ -22,8 +22,12 @@
  */
 package dom;
 
+import com.sun.org.apache.xerces.internal.dom.AttrImpl;
+import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
+import com.sun.org.apache.xerces.internal.dom.ElementImpl;
+import com.sun.org.apache.xerces.internal.dom.events.MutationEventImpl;
+import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -33,20 +37,24 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
 
 /*
  * @test
- * @bug 8213117
+ * @bug 8213117 8222743
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @modules java.xml
+ * @modules java.xml/com.sun.org.apache.xerces.internal.dom
+ * @modules java.xml/com.sun.org.apache.xerces.internal.dom.events
+ * @modules java.xml/com.sun.org.apache.xerces.internal.jaxp
  * @run testng dom.DocumentTest
  * @summary Tests functionalities for Document.
  */
 @Listeners({jaxp.library.BasePolicy.class})
 public class DocumentTest {
-
-    private static final String XML1 = "<root><oldNode oldAttrib1=\"old value 1\" oldAttrib2=\"old value 2\"></oldNode></root>";
-    private static final String XML2 = "<root><newNode newAttrib=\"new value\"></newNode></root>";
+    static final int DOC1 = 1;
+    static final int DOC2 = 2;
 
     /**
      * Verifies the adoptNode method. Before a node from a deferred DOM can be
@@ -54,12 +62,11 @@
      */
     @Test
     public void testAdoptNode() throws Exception {
+        String xml1 = "<root><oldNode oldAttrib1=\"old value 1\" oldAttrib2=\"old value 2\"></oldNode></root>";
+        String xml2 = "<root><newNode newAttrib=\"new value\"></newNode></root>";
 
-        DocumentBuilder builder = DocumentBuilderFactory.newInstance()
-                .newDocumentBuilder();
-
-        Document doc1 = getDocument(builder, XML1);
-        Document doc2 = getDocument(builder, XML2);
+        Document doc1 = getDocument(xml1);
+        Document doc2 = getDocument(xml2);
 
         Element newNode = (Element) doc2.getFirstChild().getFirstChild();
         Element replacementNode = (Element) doc1.adoptNode(newNode);
@@ -72,10 +79,118 @@
         Assert.assertEquals(attrValue, "new value");
     }
 
-    private static Document getDocument(DocumentBuilder builder, String xml) throws SAXException, IOException {
+    /**
+     * Verifies that the lookupNamespaceURI method returns null (not empty string)
+     * for unbound prefix.
+     *
+     * Specification for lookupNamespaceURI:
+     * Returns the associated namespace URI or null if none is found.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testUnboundNamespaceURI() throws Exception {
+        String xml = "<?xml version='1.1'?>"
+                + "<root><e1 xmlns='' xmlns:p1='' xmlns:p2='uri2'><e2/></e1></root>";
+
+        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        Document doc = getDocument(xml);
+        Element e1 = doc.getDocumentElement();
+        Element e2 = (Element)e1.getFirstChild().getFirstChild();
+
+        Assert.assertEquals(e1.lookupNamespaceURI(null), null);
+        Assert.assertEquals(e2.lookupNamespaceURI(null), null);
+
+        Assert.assertEquals(e1.lookupNamespaceURI("p1"), null);
+        Assert.assertEquals(e2.lookupNamespaceURI("p1"), null);
+
+        Assert.assertEquals(e1.lookupNamespaceURI("p2"), null);
+        Assert.assertEquals(e2.lookupNamespaceURI("p2"), "uri2");
+    }
+
+    /**
+     * Verifies that calling namespace methods on an empty document won't result
+     * in a NPE.
+     * @throws Exception
+     */
+    @Test
+    public void testNamespaceNPE() throws Exception {
+        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        document.lookupNamespaceURI("prefix");
+        document.lookupPrefix("uri");
+        document.isDefaultNamespace("uri");
+    }
+
+    /**
+     * Verifies that manipulating an independent document from within a mutation
+     * listener does not modify the original event object.
+     */
+    @Test
+    public void testMutation() throws Exception {
+        String xml1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                + "<root><a a_attr=\"a_attr_value\"/></root>";
+        String xml2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                + "<root><b b_attr=\"b_attr_value\"/></root>";
+        DocumentBuilder db = DocumentBuilderFactoryImpl.newInstance().newDocumentBuilder();
+        DocumentImpl doc1 = (DocumentImpl)getDocument(xml1);
+        DocumentImpl doc2 = (DocumentImpl)getDocument(xml2);
+        ElementImpl a = (ElementImpl) doc1.getDocumentElement().getFirstChild();
+        AttrImpl attr = (AttrImpl) a.getAttributeNode("a_attr");
+        attr.addEventListener(MutationEventImpl.DOM_NODE_REMOVED, new MyEventListener(DOC1, doc2), false);
+        doc2.addEventListener(MutationEventImpl.DOM_ATTR_MODIFIED, new MyEventListener(DOC2), true);
+
+        // make a change to doc1 to trigger the event
+        Element a1 = (Element) doc1.getDocumentElement().getFirstChild();
+        a1.setAttribute("a_attr", "a_attr_newvalue");
+    }
+
+    private static Document getDocument(String xml) throws Exception {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        DocumentBuilder db = dbf.newDocumentBuilder();
         InputStream a = new ByteArrayInputStream(xml.getBytes());
-        Document out = builder.parse(a);
+        Document out = db.parse(a);
         return out;
     }
 
+    // EventListener that mutates an unrelated document when an event is received.
+    static class MyEventListener implements EventListener {
+
+        private int docId;
+        private Document doc = null;
+
+        public MyEventListener(int docId) {
+            this.docId = docId;
+        }
+
+        public MyEventListener(int docId, Document doc) {
+            this.docId = docId;
+            this.doc = doc;
+        }
+
+        public void handleEvent(Event evt) {
+            if (docId == DOC1) {
+                //check the related node before making changes
+                checkRelatedNode(evt, "a_attr_value");
+                //make a change to doc2
+                Element ele = (Element)doc.getDocumentElement().getFirstChild();
+                ele.setAttribute("b_attr", "value for b_attr in doc2");
+                //check the related node again after the change
+                checkRelatedNode(evt, "a_attr_value");
+            } else { //DOC2
+                checkRelatedNode(evt, "value for b_attr in doc2");
+            }
+        }
+
+    }
+
+    // Utility method to display an event
+    public static void checkRelatedNode(Event evt, String expected) {
+        //System.out.println(" Event: " + evt + ", on " + evt.getTarget());
+        if (evt instanceof MutationEventImpl) {
+            MutationEventImpl mutation = (MutationEventImpl) evt;
+            //System.out.println(" + Related: " + mutation.getRelatedNode());
+            Assert.assertTrue(mutation.getRelatedNode().toString().contains(expected));
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,93 @@
+/*
+ * 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 validation;
+
+
+import java.io.File;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import org.testng.annotations.DataProvider;
+
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXParseException;
+
+/*
+ * @test
+ * @bug 8220818
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm validation.ValidationTest
+ * @summary Runs validations with schemas and sources
+ */
+@Listeners({jaxp.library.FilePolicy.class})
+public class ValidationTest {
+    static final String FILE_PATH = "files/";
+    /*
+     DataProvider: valid xml
+     */
+    @DataProvider(name = "valid")
+    Object[][] getValid() {
+        return new Object[][]{
+            {"JDK8220818a.xsd", "JDK8220818a_Valid.xml"},
+            {"JDK8220818a.xsd", "JDK8220818a_Valid1.xml"},
+            {"JDK8220818b.xsd", "JDK8220818b_Valid.xml"},
+        };
+    }
+
+    /*
+     DataProvider: invalid xml
+     */
+    @DataProvider(name = "invalid")
+    Object[][] getInvalid() {
+        return new Object[][]{
+            {"JDK8220818a.xsd", "JDK8220818a_Invalid.xml"},
+            {"JDK8220818b.xsd", "JDK8220818b_Invalid.xml"},
+        };
+    }
+
+    @Test(dataProvider = "invalid", expectedExceptions = SAXParseException.class)
+    public void testValidateRefType(String xsd, String xml) throws Exception {
+        validate(xsd, xml);
+    }
+
+    @Test(dataProvider = "valid")
+    public void testValidateRefType1(String xsd, String xml) throws Exception {
+        validate(xsd, xml);
+    }
+
+    private void validate(String xsd, String xml) throws Exception {
+        final SchemaFactory schemaFactory = SchemaFactory.newInstance(
+                XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        final Schema schema = schemaFactory.newSchema(
+                new File(getClass().getResource(FILE_PATH + xsd).getFile()));
+        final Validator validator = schema.newValidator();
+        validator.validate(new StreamSource(
+                new File(getClass().getResource(FILE_PATH + xml).getFile())));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818a.xsd	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,23 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="root">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="key" type="xs:string" minOccurs="0">
+                    <xs:key name="key">
+                        <xs:selector xpath="."/>
+                        <xs:field xpath="."/>
+                    </xs:key>
+                </xs:element>
+                <xs:element name="keyref">
+                    <xs:complexType>
+                        <xs:attribute name="att" type="xs:string"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+        <xs:keyref name="keyref" refer="key">
+            <xs:selector xpath="keyref"/>
+            <xs:field xpath="@att"/>
+        </xs:keyref>
+    </xs:element>
+</xs:schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818a_Invalid.xml	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,3 @@
+<root>
+    <keyref att="xyz"/>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818a_Valid.xml	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,4 @@
+<root>
+    <key>xyz</key>
+    <keyref att="xyz"/>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818a_Valid1.xml	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,3 @@
+<root>
+    <keyref/>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818b.xsd	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:example="http://www.example.org/root"
+           xmlns="http://www.example.org/root"
+           targetNamespace="http://www.example.org/root"
+           elementFormDefault="qualified" attributeFormDefault="unqualified">
+    <xs:element name="Root">
+        <xs:complexType>
+            <xs:choice maxOccurs="unbounded">
+                <xs:element ref="Object" />
+            </xs:choice>
+        </xs:complexType>
+        <xs:key name="name_key">
+            <xs:selector xpath=".//example:Object" />
+            <xs:field xpath="@name" />
+        </xs:key>
+        <xs:keyref name="Collectiontype_defined" refer="name_key">
+            <xs:selector xpath=".//example:CollectionMember" />
+            <xs:field xpath="@type" />
+        </xs:keyref>
+    </xs:element>
+    <xs:element name="Members">
+        <xs:complexType>
+            <xs:group ref="example:memberTypes" minOccurs="0"
+                      maxOccurs="unbounded" />
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="Object">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element ref="Members" minOccurs="0" />
+            </xs:sequence>
+            <xs:attributeGroup ref="example:typedMemberAttributes" />
+            <xs:attributeGroup ref="example:namedMemberAttributes" />
+        </xs:complexType>
+        <xs:unique name="ObjectElementNameUniqueness">
+            <xs:selector xpath="example:Members/*" />
+            <xs:field xpath="@name" />
+        </xs:unique>
+    </xs:element>
+    <xs:element name="Collection">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element ref="CollectionMembers" />
+            </xs:sequence>
+            <xs:attributeGroup ref="example:namedMemberAttributes" />
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="CollectionMembers">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element ref="CollectionMember" minOccurs="2"
+                            maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="CollectionMember">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element ref="Members" minOccurs="0"
+                            maxOccurs="unbounded" />
+            </xs:sequence>
+            <xs:attributeGroup ref="example:typedMemberAttributes" />
+            <xs:attributeGroup ref="example:namedMemberAttributes" />
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="String">
+        <xs:complexType>
+            <xs:attributeGroup ref="example:namedMemberAttributes" />
+        </xs:complexType>
+    </xs:element>
+    <xs:group name="memberTypes">
+        <xs:choice>
+            <xs:element ref="String" />
+            <xs:element ref="Collection" />
+        </xs:choice>
+    </xs:group>
+    <xs:attributeGroup name="namedMemberAttributes">
+        <xs:attribute name="name" type="xs:Name" use="required" />
+    </xs:attributeGroup>
+    <xs:attributeGroup name="typedMemberAttributes">
+        <xs:attribute name="type" type="xs:Name" />
+    </xs:attributeGroup>
+</xs:schema> 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818b_Invalid.xml	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<Root xmlns="http://www.example.org/root">
+
+    <Object name="object2">
+        <Members>
+            <Collection name="Collection1">
+                <CollectionMembers>
+                    <CollectionMember name="Collectionmember1" type="object1" />
+                    <CollectionMember name="Collectionmember2" >
+                        <Members>
+                            <String name="string1" />
+                        </Members>
+                    </CollectionMember>
+                </CollectionMembers>
+            </Collection>
+        </Members>
+    </Object>
+</Root> 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8220818b_Valid.xml	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<Root xmlns="http://www.example.org/root">
+
+    <Object name="object1">
+        <Members>
+            <String name="string1" />
+        </Members>
+    </Object>
+
+    <Object name="object2">
+        <Members>
+            <Collection name="Collection1">
+                <CollectionMembers>
+                    <CollectionMember name="Collectionmember1" type="object1" />
+                    <CollectionMember name="Collectionmember2" >
+                        <Members>
+                            <String name="string1" />
+                        </Members>
+                    </CollectionMember>
+                </CollectionMembers>
+            </Collection>
+        </Members>
+    </Object>
+</Root>
--- a/test/jdk/ProblemList.txt	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/ProblemList.txt	Fri May 03 14:59:32 2019 -0400
@@ -240,6 +240,14 @@
 java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java 8013450 macosx-all
 java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8165218 macosx-all,linux-all
 java/awt/Window/ShapedAndTranslucentWindows/TranslucentChoice.java 8221901 linux-all
+java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java 8222323 windows-all
+java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 windows-all,linux-all
+java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8222328 windows-all,linux-all
+java/awt/Window/ShapedAndTranslucentWindows/Shaped.java  8222328 windows-all,linux-all
+java/awt/Window/ShapedAndTranslucentWindows/ShapedByAPI.java 8222328 windows-all,linux-all
+java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucent.java 8222328 windows-all,linux-all
+java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8222328 windows-all
+java/awt/Window/ShapedAndTranslucentWindows/Translucent.java 8222328 windows-all,linux-all,macosx-all
 java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 macosx-all
 java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all
 java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all,solaris-all
@@ -264,7 +272,7 @@
 sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all
 sun/java2d/GdiRendering/InsetClipping.java 8196181 windows-all
 java/awt/Graphics2D/CopyAreaOOB.java 7001973 windows-all,macosx-all
-sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all
+sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all
 sun/java2d/SunGraphics2D/DrawImageBilinear.java 8191406 generic-all
 sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all
 sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all
@@ -657,65 +665,7 @@
 
 sun/security/provider/KeyStore/DKSTest.sh                       8180266 windows-all
 
-sun/security/pkcs11/Cipher/ReinitCipher.java                    8204203 windows-all
-sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java           8204203 windows-all
-sun/security/pkcs11/Cipher/TestRSACipher.java                   8204203 windows-all
-sun/security/pkcs11/Cipher/TestRSACipherWrap.java               8204203 windows-all
-sun/security/pkcs11/Cipher/TestRawRSACipher.java                8204203 windows-all
-sun/security/pkcs11/Cipher/TestSymmCiphers.java                 8204203 windows-all
-sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java            8204203 windows-all
-sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java           8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestDH.java                    8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestInterop.java               8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestShort.java                 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java         8204203 windows-all
-sun/security/pkcs11/KeyGenerator/DESParity.java                 8204203 windows-all
-sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java          8204203 windows-all
-sun/security/pkcs11/KeyPairGenerator/TestDH2048.java            8204203 windows-all
-sun/security/pkcs11/KeyStore/SecretKeysBasic.sh                 8204203,8209398 generic-all
-sun/security/pkcs11/Mac/MacKAT.java                             8204203 windows-all
-sun/security/pkcs11/Mac/MacSameTest.java                        8204203 windows-all
-sun/security/pkcs11/Mac/ReinitMac.java                          8204203 windows-all
-sun/security/pkcs11/MessageDigest/ByteBuffers.java              8204203 windows-all
-sun/security/pkcs11/MessageDigest/DigestKAT.java                8204203 windows-all
-sun/security/pkcs11/MessageDigest/ReinitDigest.java             8204203 windows-all
-sun/security/pkcs11/MessageDigest/TestCloning.java              8204203 windows-all
-sun/security/pkcs11/Provider/ConfigQuotedString.sh              8204203 windows-all
-sun/security/pkcs11/Provider/Login.sh                           8204203 windows-all
-sun/security/pkcs11/SampleTest.java                             8204203 windows-all
-sun/security/pkcs11/Secmod/AddPrivateKey.java                   8204203 windows-all
-sun/security/pkcs11/Secmod/Crypto.java                          8204203 windows-all
-sun/security/pkcs11/Secmod/GetPrivateKey.java                   8204203 windows-all
-sun/security/pkcs11/Secmod/JksSetPrivateKey.java                8204203 windows-all
-sun/security/pkcs11/Secmod/LoadKeystore.java                    8204203 windows-all
-sun/security/pkcs11/Secmod/TestNssDbSqlite.java                 8204203 windows-all
-sun/security/pkcs11/SecureRandom/Basic.java                     8204203 windows-all
-sun/security/pkcs11/SecureRandom/TestDeserialization.java       8204203 windows-all
-sun/security/pkcs11/Serialize/SerializeProvider.java            8204203 windows-all
-sun/security/pkcs11/Signature/ByteBuffers.java                  8204203 windows-all
-sun/security/pkcs11/Signature/ReinitSignature.java              8204203 windows-all
-sun/security/pkcs11/Signature/TestDSA.java                      8204203 windows-all
-sun/security/pkcs11/Signature/TestDSAKeyLength.java             8204203 windows-all
-sun/security/pkcs11/Signature/TestRSAKeyLength.java             8204203 windows-all
-sun/security/pkcs11/ec/ReadCertificates.java                    8204203 windows-all
-sun/security/pkcs11/ec/ReadPKCS12.java                          8204203 windows-all
-sun/security/pkcs11/ec/TestCurves.java                          8204203 windows-all
-sun/security/pkcs11/ec/TestECDH.java                            8204203 windows-all
-sun/security/pkcs11/ec/TestECDH2.java                           8204203 windows-all
-sun/security/pkcs11/ec/TestECDSA.java                           8204203 windows-all
-sun/security/pkcs11/ec/TestECDSA2.java                          8204203 windows-all
-sun/security/pkcs11/ec/TestECGenSpec.java                       8204203 windows-all
-sun/security/pkcs11/rsa/KeyWrap.java                            8204203 windows-all
-sun/security/pkcs11/rsa/TestCACerts.java                        8204203 windows-all
-sun/security/pkcs11/rsa/TestKeyFactory.java                     8204203 windows-all
-sun/security/pkcs11/rsa/TestKeyPairGenerator.java               8204203 windows-all
-sun/security/pkcs11/rsa/TestSignatures.java                     8204203 windows-all
-sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java            8204203 windows-all
-sun/security/pkcs11/tls/TestLeadingZeroesP11.java               8204203 windows-all
-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/tools/keytool/NssTest.java                         8204203 windows-all
+sun/security/pkcs11/KeyStore/SecretKeysBasic.sh                 8209398 generic-all
 
 ############################################################################
 
--- a/test/jdk/com/sun/jdi/ExceptionEvents.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/com/sun/jdi/ExceptionEvents.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, 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
@@ -422,6 +422,7 @@
         request.addClassExclusionFilter("com.oracle.*");
         request.addClassExclusionFilter("oracle.*");
         request.addClassExclusionFilter("jdk.internal.*");
+        request.addClassExclusionFilter("jdk.vm.ci.hotspot.*");
         request.setSuspendPolicy(suspendPolicy);
         request.enable();
 
--- a/test/jdk/com/sun/jndi/ldap/LdapDnsProviderTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/com/sun/jndi/ldap/LdapDnsProviderTest.java	Fri May 03 14:59:32 2019 -0400
@@ -194,8 +194,8 @@
             // no SecurityManager
             runTest("ldap:///dc=example,dc=com", "localhost:389");
             runTest("ldap://localhost/dc=example,dc=com", "localhost:389");
-            runTest("ldap://localhost:111/dc=example,dc=com", "localhost:111");
-            runTest("ldaps://localhost:111/dc=example,dc=com", "localhost:111");
+            runTest("ldap://localhost:1111/dc=example,dc=com", "localhost:1111");
+            runTest("ldaps://localhost:1111/dc=example,dc=com", "localhost:1111");
             runTest("ldaps://localhost/dc=example,dc=com", "localhost:636");
             runTest(null, "localhost:389");
             runTest("", "ConfigurationException");
--- a/test/jdk/com/sun/net/httpserver/bugs/B6361557.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/com/sun/net/httpserver/bugs/B6361557.java	Fri May 03 14:59:32 2019 -0400
@@ -69,7 +69,8 @@
 
     public static void main (String[] args) throws Exception {
         Handler handler = new Handler();
-        InetSocketAddress addr = new InetSocketAddress (0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        InetSocketAddress addr = new InetSocketAddress (loopback, 0);
         HttpServer server = HttpServer.create (addr, 0);
         HttpContext ctx = server.createContext ("/test", handler);
 
@@ -78,7 +79,7 @@
         server.start ();
 
         InetSocketAddress destaddr = new InetSocketAddress (
-                InetAddress.getLoopbackAddress(), server.getAddress().getPort()
+                loopback, server.getAddress().getPort()
         );
         System.out.println ("destaddr " + destaddr);
 
@@ -86,7 +87,10 @@
         int requests = 0;
         int responses = 0;
         while (true) {
-            int selres = selector.select (1);
+            // we need to read responses from time to time: slightly
+            // increase the timeout with the amount of pending responses
+            // to give a chance to the server to reply.
+            int selres = selector.select (requests - responses + 1);
             Set<SelectionKey> selkeys = selector.selectedKeys();
             for (SelectionKey key : selkeys) {
                 if (key.isReadable()) {
@@ -95,14 +99,18 @@
                     try {
                         int x = chan.read(buf);
                         if (x == -1 || responseComplete(buf)) {
+                            System.out.print("_");
                             key.attach(null);
                             chan.close();
                             responses++;
                         }
-                    } catch (IOException e) {}
+                    } catch (IOException e) {
+                        System.out.println(e);
+                    }
                 }
             }
             if (requests < NUM) {
+                System.out.print(".");
                 SocketChannel schan = SocketChannel.open(destaddr);
                 requestBuf.rewind();
                 int c = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/font/TextLayout/FontLayoutStressTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 JetBrains s.r.o.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8220231
+ * @summary Cache HarfBuzz face object for same font's text layout calls
+ * @comment Test layout operations for the same font performed simultaneously
+ *          from multiple threads
+ */
+
+import java.awt.Font;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class FontLayoutStressTest {
+    private static final int NUMBER_OF_THREADS =
+            Runtime.getRuntime().availableProcessors() * 2;
+    private static final long TIME_TO_RUN_NS = 1_000_000_000; // 1 second
+    private static final Font FONT = new Font(Font.SERIF, Font.PLAIN, 12);
+    private static final FontRenderContext FRC = new FontRenderContext(null,
+            false, false);
+    private static final char[] TEXT = "Lorem ipsum dolor sit amet, ..."
+            .toCharArray();
+
+    private static double doLayout() {
+        GlyphVector gv = FONT.layoutGlyphVector(FRC, TEXT, 0, TEXT.length,
+                Font.LAYOUT_LEFT_TO_RIGHT);
+        return gv.getGlyphPosition(gv.getNumGlyphs()).getX();
+    }
+
+    public static void main(String[] args) throws Throwable {
+        double expectedWidth = doLayout();
+        AtomicReference<Throwable> throwableRef = new AtomicReference<>();
+        CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS);
+        List<Thread> threads = new ArrayList<>();
+        for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+            Thread thread = new Thread(() -> {
+                try {
+                    barrier.await();
+                    long timeToStop = System.nanoTime() + TIME_TO_RUN_NS;
+                    while (System.nanoTime() < timeToStop) {
+                        double width = doLayout();
+                        if (width != expectedWidth) {
+                            throw new RuntimeException(
+                                    "Unexpected layout result");
+                        }
+                    }
+                } catch (Throwable e) {
+                    throwableRef.set(e);
+                }
+            });
+            threads.add(thread);
+            thread.start();
+        }
+        for (Thread thread : threads) {
+            thread.join();
+        }
+        Throwable throwable = throwableRef.get();
+        if (throwable != null) {
+            throw throwable;
+        }
+    }
+}
--- a/test/jdk/java/io/DataOutputStream/WriteUTF.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/io/DataOutputStream/WriteUTF.java	Fri May 03 14:59:32 2019 -0400
@@ -22,10 +22,10 @@
  */
 
 /* @test
- * @bug 4260284 8219196
+ * @bug 4260284 8219196 8223254
  * @summary Test if DataOutputStream will overcount written field.
- * @requires (sun.arch.data.model == "64" & os.maxMemory >= 3g)
- * @run testng/othervm -Xmx3g WriteUTF
+ * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g)
+ * @run testng/othervm -Xmx4g WriteUTF
  */
 
 import java.io.ByteArrayOutputStream;
@@ -60,7 +60,7 @@
     }
 
     // Without 8219196 fix, throws ArrayIndexOutOfBoundsException instead of
-    // expected UTFDataFormatException. Requires 3GB of heap (-Xmx3g) to run
+    // expected UTFDataFormatException. Requires 4GB of heap (-Xmx4g) to run
     // without throwing an OutOfMemoryError.
     @Test(expectedExceptions = UTFDataFormatException.class)
     public void arrayIndexOutOfBoundsException() throws IOException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/io/LineNumberReader/MarkSplitCRLF.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,99 @@
+/*
+ * 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 8218280
+ * @summary Make sure marking a line feed within a CRLF sequence works correctly
+ * @run testng MarkSplitCRLF
+ */
+
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class MarkSplitCRLF {
+    @Test
+    public static void testSpecifiedBufferSize() throws IOException {
+        final String string = "foo\r\nbar";
+        try (Reader reader =
+            new LineNumberReader(new StringReader(string), 5)) {
+            reader.read();  // 'f'
+            reader.read();  // 'o'
+            reader.read();  // 'o'
+            reader.read();  // '\r' -> '\n'
+            reader.mark(1); // mark position of '\n'
+            reader.read();  // 'b'
+            reader.reset(); // reset to '\n' position
+            assertEquals(reader.read(), 'b');
+            assertEquals(reader.read(), 'a');
+            assertEquals(reader.read(), 'r');
+        }
+    }
+
+    @Test
+    public static void testCRNotFollowedByLF() throws IOException {
+        final String string = "foo\rbar";
+        try (Reader reader =
+            new LineNumberReader(new StringReader(string), 5)) {
+            reader.read();  // 'f'
+            reader.read();  // 'o'
+            reader.read();  // 'o'
+            reader.read();  // '\r'
+            reader.mark(1); // mark position of next character
+            reader.read();  // 'b'
+            reader.reset(); // reset to position after '\r'
+            assertEquals(reader.read(), 'b');
+            assertEquals(reader.read(), 'a');
+            assertEquals(reader.read(), 'r');
+        }
+    }
+
+    @Test
+    public static void testDefaultBufferSize() throws IOException {
+        StringBuilder sb = new StringBuilder(8195);
+        for (int i = 0; i < 8190; i++) {
+            char c = (char)i;
+            sb.append(c);
+        }
+        sb.append('\r');
+        sb.append('\n');
+        sb.append('X');
+        sb.append('Y');
+        sb.append('Z');
+        final String string = sb.toString();
+        try (Reader reader = new LineNumberReader(new StringReader(string))) {
+            for (int i = 0; i < 8191; i++) reader.read();
+            reader.mark(1);
+            reader.read();
+            reader.reset();
+            assertEquals(reader.read(), 'X');
+            assertEquals(reader.read(), 'Y');
+            assertEquals(reader.read(), 'Z');
+        }
+    }
+}
--- a/test/jdk/java/lang/String/concat/StringConcatFactoryEmptyMethods.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +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.
- */
-
-import java.io.Serializable;
-import java.lang.invoke.*;
-import java.util.concurrent.Callable;
-
-/**
- * @test
- * @summary StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
- * @bug 8148787
- *
- * @compile StringConcatFactoryEmptyMethods.java
- *
- * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryEmptyMethods
- *
-*/
-public class StringConcatFactoryEmptyMethods {
-
-    public static void main(String[] args) throws Throwable {
-        StringConcatFactory.makeConcat(
-            MethodHandles.lookup(),
-            "foo",
-            MethodType.methodType(String.class)
-        );
-
-        StringConcatFactory.makeConcatWithConstants(
-            MethodHandles.lookup(),
-            "foo",
-            MethodType.methodType(String.class),
-            ""
-        );
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/String/concat/StringConcatFactoryRepeatedConstants.java	Fri May 03 14:59:32 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.
+ */
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.StringConcatFactory;
+
+/**
+ * @test
+ * @summary StringConcatFactory allow recipes with repeated constants, but this
+ *          is not expressible with java code and needs an explicit sanity test
+ * @bug 8222852
+ *
+ * @compile StringConcatFactoryRepeatedConstants.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  StringConcatFactoryRepeatedConstants
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            StringConcatFactoryRepeatedConstants
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            StringConcatFactoryRepeatedConstants
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      StringConcatFactoryRepeatedConstants
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      StringConcatFactoryRepeatedConstants
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  StringConcatFactoryRepeatedConstants
+ *
+*/
+public class StringConcatFactoryRepeatedConstants {
+
+    public static void main(String[] args) throws Throwable {
+
+        CallSite site = StringConcatFactory.makeConcatWithConstants(
+            MethodHandles.lookup(),
+            "foo",
+            MethodType.methodType(String.class),
+            "\u0002\u0002",
+            "foo", "bar"
+        );
+        String string = (String)site.dynamicInvoker().invoke();
+        if (!"foobar".equals(string)) {
+            throw new IllegalStateException("Expected: foobar, got: " + string);
+        }
+
+        site = StringConcatFactory.makeConcatWithConstants(
+                MethodHandles.lookup(),
+                "foo",
+                MethodType.methodType(String.class),
+                "\u0002\u0002test\u0002\u0002",
+                "foo", 17.0f, 4711L, "bar"
+        );
+        string = (String)site.dynamicInvoker().invoke();
+        StringBuilder sb = new StringBuilder();
+        sb.append("foo").append(17.0f).append("test").append(4711L).append("bar");
+        if (!sb.toString().equals(string)) {
+            throw new IllegalStateException("Expected: " + sb.toString() + ", got: " + string);
+        }
+    }
+
+}
--- a/test/jdk/java/lang/String/concat/WithSecurityManager.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/lang/String/concat/WithSecurityManager.java	Fri May 03 14:59:32 2019 -0400
@@ -26,7 +26,7 @@
 /**
  * @test
  * @summary String concatenation fails with a custom SecurityManager that uses concatenation
- * @bug 8155090 8158851
+ * @bug 8155090 8158851 8222895
  * @requires !vm.graal.enabled
  *
  * @compile WithSecurityManager.java
@@ -55,12 +55,17 @@
                 @Override
                 public void checkPermission(Permission perm) {
                     String abc = "abc";
-                    String full = abc + "def";
+                    int ival = perm.hashCode();
+                    String full = abc + "abc";
+                    // Contorted to avoid sweeping cases where we've
+                    // pre-generated commonly used species under the rug
+                    full = "abc" + ival + "def" + abc + "def" + abc + "def" +
+                           abc + "def" + ival + "def" + abc + "def" +
+                           abc + "def" + abc + "def" + abc + "def";
                 }
             };
             System.setSecurityManager(sm);
-            ClassLoader cl = new ClassLoader() {
-            };
+            ClassLoader cl = new ClassLoader() {};
         }
 
         // Second time should succeed to run after bootstrapping
@@ -69,12 +74,19 @@
                 @Override
                 public void checkPermission(Permission perm) {
                     String abc = "abc";
-                    String full = abc + "def";
+                    int ival = perm.hashCode();
+                    String full = abc + "abc";
+                    // Contorted variant to avoid sweeping cases where we've
+                    // pre-generated commonly used species under the rug
+                    full = "abc" + ival + "def" + abc + "def" + abc + "def" +
+                            abc + "def" + ival + "def" + abc + "def" +
+                            abc + "def" + abc + "def" + abc + "def";
                 }
             };
+
+            // Provoke checkPermission invocation
             System.setSecurityManager(sm);
-            ClassLoader cl = new ClassLoader() {
-            };
+            ClassLoader cl = new ClassLoader() {};
         }
     }
 }
--- a/test/jdk/java/net/Authenticator/B4722333.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Authenticator/B4722333.java	Fri May 03 14:59:32 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
@@ -121,13 +121,14 @@
         MyAuthenticator auth = new MyAuthenticator ();
         Authenticator.setDefault (auth);
         try {
-            server = new TestHttpServer (new B4722333(), 1, 10, 0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            server = new TestHttpServer (new B4722333(), 1, 10, loopback, 0);
             System.out.println ("Server started: listening on port: " + server.getLocalPort());
-            client ("http://localhost:"+server.getLocalPort()+"/d1/d2/d3/foo.html");
-            client ("http://localhost:"+server.getLocalPort()+"/ASD/d3/x.html");
-            client ("http://localhost:"+server.getLocalPort()+"/biz/d3/x.html");
-            client ("http://localhost:"+server.getLocalPort()+"/bar/d3/x.html");
-            client ("http://localhost:"+server.getLocalPort()+"/fuzz/d3/x.html");
+            client ("http://" + server.getAuthority() + "/d1/d2/d3/foo.html");
+            client ("http://" + server.getAuthority() + "/ASD/d3/x.html");
+            client ("http://" + server.getAuthority() + "/biz/d3/x.html");
+            client ("http://" + server.getAuthority() + "/bar/d3/x.html");
+            client ("http://" + server.getAuthority() + "/fuzz/d3/x.html");
         } catch (Exception e) {
             if (server != null) {
                 server.terminate();
--- a/test/jdk/java/net/HttpURLConnection/UnmodifiableMaps.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/HttpURLConnection/UnmodifiableMaps.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 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
@@ -24,11 +24,13 @@
 /**
  * @test
  * @bug 7128648
+ * @library /test/lib
  * @modules jdk.httpserver
  * @summary HttpURLConnection.getHeaderFields should return an unmodifiable Map
  */
 
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.HttpURLConnection;
@@ -41,6 +43,7 @@
 import com.sun.net.httpserver.HttpServer;
 import com.sun.net.httpserver.Headers;
 import static java.net.Proxy.NO_PROXY;
+import jdk.test.lib.net.URIBuilder;
 
 public class UnmodifiableMaps {
 
@@ -48,7 +51,12 @@
         HttpServer server = startHttpServer();
         try {
             InetSocketAddress address = server.getAddress();
-            URI uri = new URI("http://localhost:" + address.getPort() + "/foo");
+            URI uri = URIBuilder.newBuilder()
+                .scheme("http")
+                .host(address.getAddress())
+                .port(address.getPort())
+                .path("/foo")
+                .build();
             doClient(uri);
         } finally {
             server.stop(0);
@@ -78,7 +86,8 @@
 
     // HTTP Server
     HttpServer startHttpServer() throws IOException {
-        HttpServer httpServer = HttpServer.create(new InetSocketAddress(0), 0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0);
         httpServer.createContext("/foo", new SimpleHandler());
         httpServer.start();
         return httpServer;
@@ -146,4 +155,3 @@
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new AssertionError("Some tests failed");}
 }
-
--- a/test/jdk/java/net/ResponseCache/ResponseCacheTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/ResponseCache/ResponseCacheTest.java	Fri May 03 14:59:32 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
@@ -24,6 +24,7 @@
 /* @test
  * @summary Unit test for java.net.ResponseCache
  * @bug 4837267
+ * @library /test/lib
  * @author Yingxian Wang
  */
 
@@ -31,6 +32,7 @@
 import java.util.*;
 import java.io.*;
 import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
 
 /**
  * Request should get serviced by the cache handler. Response get
@@ -90,14 +92,17 @@
             try { fis.close(); } catch (IOException unused) {}
         }
     }
-static class NameVerifier implements HostnameVerifier {
+    static class NameVerifier implements HostnameVerifier {
         public boolean verify(String hostname, SSLSession session) {
             return true;
         }
     }
     ResponseCacheTest() throws Exception {
         /* start the server */
-        ss = new ServerSocket(0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ss = new ServerSocket();
+        ss.bind(new InetSocketAddress(loopback, 0));
+
         (new Thread(this)).start();
         /* establish http connection to server */
         url1 = new URL("http://localhost/file1.cache");
@@ -126,8 +131,12 @@
         http.disconnect();
 
         // testing ResponseCacheHandler.put()
-        url2 = new URL("http://localhost:" +
-                       Integer.toString(ss.getLocalPort())+"/file2.1");
+        url2 = URIBuilder.newBuilder()
+                   .scheme("http")
+                   .host(ss.getInetAddress())
+                   .port(ss.getLocalPort())
+                   .path("/file2.1")
+                   .toURL();
         http = (HttpURLConnection)url2.openConnection();
         System.out.println("responsecode2 is :"+http.getResponseCode());
         Map<String,List<String>> headers2 = http.getHeaderFields();
--- a/test/jdk/java/net/Socket/GetLocalAddress.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/GetLocalAddress.java	Fri May 03 14:59:32 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
@@ -45,7 +45,8 @@
         int          linger = 65546;
         int          value = 0;
         addr = InetAddress.getLocalHost();
-        ss = new ServerSocket(0);
+        ss = new ServerSocket();
+        ss.bind(new InetSocketAddress(addr, 0));
         port = ss.getLocalPort();
 
         Thread t = new Thread(new GetLocalAddress());
--- a/test/jdk/java/net/Socket/LingerTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/LingerTest.java	Fri May 03 14:59:32 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
@@ -71,11 +71,13 @@
     }
 
     static class Other implements Runnable {
-        int port;
-        long delay;
+        final InetAddress address;
+        final int port;
+        final long delay;
         boolean connected = false;
 
-        public Other(int port, long delay) {
+        public Other(InetAddress address, int port, long delay) {
+            this.address = address;
             this.port = port;
             this.delay = delay;
         }
@@ -85,7 +87,7 @@
             try {
                 Thread.sleep(delay);
                 System.out.println ("Other opening socket");
-                Socket s = new Socket("localhost", port);
+                Socket s = new Socket(address, port);
                 synchronized (this) {
                     connected = true;
                 }
@@ -103,9 +105,10 @@
     }
 
     public static void main(String args[]) throws Exception {
-        ServerSocket ss = new ServerSocket(0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ServerSocket ss = new ServerSocket(0, 50, loopback);
 
-        Socket s1 = new Socket("localhost", ss.getLocalPort());
+        Socket s1 = new Socket(loopback, ss.getLocalPort());
         Socket s2 = ss.accept();
 
         // setup conditions for untransmitted data and lengthy
@@ -119,7 +122,7 @@
         senderThread.start();
 
         // other thread that will connect after 5 seconds.
-        Other other = new Other(ss.getLocalPort(), 5000);
+        Other other = new Other(loopback, ss.getLocalPort(), 5000);
         Thread otherThread = new Thread(other);
         otherThread.start();
 
--- a/test/jdk/java/net/Socket/OldImpl.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.*;
-import java.net.*;
-
-
-/**
- * @test
- * @bug 5089488
- * @summary  java.net.Socket checks for old-style impls
- */
-
-public class OldImpl {
-
-    /**
-     * A no-op SocketImpl descendant.
-     */
-    static class FunkySocketImpl extends SocketImpl {
-        protected void accept(SocketImpl impl) throws IOException {
-        }
-
-        protected int available(){
-            return 0;
-        }
-
-        protected void bind(InetAddress host, int port){
-        }
-
-        protected void close(){
-        }
-
-        protected void connect(InetAddress address, int port){
-        }
-
-        protected void connect(String host, int port){
-        }
-
-        protected void connect(SocketAddress a,int b){
-        }
-
-        protected void create(boolean stream){
-        }
-
-        protected InputStream getInputStream(){
-            return null;
-        }
-
-        protected OutputStream getOutputStream(){
-            return null;
-        }
-
-        protected void listen(int backlog){
-        }
-
-        public Object getOption(int optID){
-            return null;
-        }
-
-        public void setOption(int optID, Object value){
-        }
-
-        protected void sendUrgentData(int i){
-        }
-    }
-
-    static class FunkyWunkySocketImpl extends FunkySocketImpl {}
-
-    /**
-     * A no-op Socket descendant.
-     */
-    static class FunkySocket extends Socket {
-        public FunkySocket(SocketImpl impl) throws IOException {
-            super(impl);
-        }
-    }
-
-    public static void main(String args[]) throws Exception {
-        FunkyWunkySocketImpl socketImpl = new FunkyWunkySocketImpl();
-        FunkySocket socko = new FunkySocket(socketImpl);
-        if (socko.isBound()) {
-            throw new RuntimeException ("socket is not really bound");
-        }
-    }
-}
--- a/test/jdk/java/net/Socket/OldSocketImpl.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.*;
-import java.net.*;
-
-class OldSocketImpl extends SocketImpl  {
-    public static void main(String[] args) throws Exception {
-        Socket.setSocketImplFactory(new SocketImplFactory() {
-                public SocketImpl createSocketImpl() {
-                    return new OldSocketImpl();
-                }
-        });
-        Socket socket = new Socket("localhost", 23);
-    }
-
-    public void setOption(int optID, Object value) throws SocketException { }
-
-    public Object getOption(int optID) throws SocketException {
-        return null;
-    }
-
-    protected void create(boolean stream) throws IOException { }
-
-    protected void connect(String host, int port) throws IOException { }
-
-    protected void connect(InetAddress address, int port) throws IOException { }
-
-    // Not in 1.3...
-    // protected void connect(SocketAddress address, int timeout) throws IOException { }
-
-    protected void bind(InetAddress host, int port) throws IOException { }
-
-    protected void listen(int backlog) throws IOException { }
-
-    protected void accept(SocketImpl s) throws IOException { }
-
-    protected InputStream getInputStream() throws IOException {
-        return null;
-    }
-
-    protected OutputStream getOutputStream() throws IOException {
-        return null;
-    }
-
-    protected int available() throws IOException {
-        return 0;
-    }
-
-    protected void close() throws IOException { }
-
-    protected void sendUrgentData (int data) throws SocketException { }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/OldSocketImplTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,49 @@
+/*
+ * 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 8216978
+ * @summary Drop support for pre JDK 1.4 SocketImpl implementations
+ * @library OldSocketImpl.jar
+ * @run main/othervm OldSocketImplTest
+ */
+
+import java.net.*;
+
+public class OldSocketImplTest {
+    public static void main(String[] args) throws Exception {
+        Socket.setSocketImplFactory(new SocketImplFactory() {
+                public SocketImpl createSocketImpl() {
+                    return new OldSocketImpl();
+                }
+        });
+        try {
+            Socket socket = new Socket("localhost", 23);
+            throw new RuntimeException("error test failed");
+        } catch (AbstractMethodError error) {
+            error.printStackTrace();
+            System.out.println("Old impl no longer accepted: OK");
+        }
+    }
+}
--- a/test/jdk/java/net/Socket/OldSocketImplTestDriver.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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.
- */
-
-import jdk.test.lib.process.ProcessTools;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/**
- * @test
- * @bug 6449565
- * @library /test/lib
- * @build jdk.test.lib.Utils
- *        jdk.test.lib.Asserts
- *        jdk.test.lib.JDKToolFinder
- *        jdk.test.lib.JDKToolLauncher
- *        jdk.test.lib.Platform
- *        jdk.test.lib.process.*
- * @run main OldSocketImplTestDriver
- * @summary Test driver for OdlSocketImpl
- */
-public class OldSocketImplTestDriver {
-    public static void main(String[] args) throws Throwable {
-        Path jar = Paths.get(System.getProperty("test.src"),
-                "OldSocketImpl.jar");
-        ProcessTools.executeTestJava("-cp", jar.toString(), "OldSocketImpl")
-                    .outputTo(System.out)
-                    .errorTo(System.out)
-                    .shouldHaveExitValue(0);
-    }
-}
--- a/test/jdk/java/net/Socket/SetReceiveBufferSize.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/SetReceiveBufferSize.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, 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
@@ -28,6 +28,8 @@
  *
  */
 
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.ServerSocket;
 
@@ -37,8 +39,10 @@
     }
 
     public SetReceiveBufferSize() throws Exception {
-        ServerSocket ss = new ServerSocket(0);
-        Socket s = new Socket("localhost", ss.getLocalPort());
+        ServerSocket ss = new ServerSocket();
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ss.bind(new InetSocketAddress(loopback, 0));
+        Socket s = new Socket(loopback, ss.getLocalPort());
         Socket accepted = ss.accept();
         try {
             s.setReceiveBufferSize(0);
--- a/test/jdk/java/net/Socket/ShutdownBoth.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/ShutdownBoth.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, 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
@@ -32,7 +32,8 @@
 public class ShutdownBoth {
 
     public static void main(String args[]) throws Exception {
-        ServerSocket ss = new ServerSocket(0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ServerSocket ss = new ServerSocket(0, 50, loopback);
         Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
         Socket s2 = ss.accept();
 
--- a/test/jdk/java/net/Socket/SoTimeout.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/SoTimeout.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, 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
@@ -44,7 +44,8 @@
 
     public static void main(String[] args) throws Exception {
         addr = InetAddress.getLocalHost();
-        serverSocket = new ServerSocket(0);
+        serverSocket = new ServerSocket();
+        serverSocket.bind(new InetSocketAddress(addr, 0));
         port = serverSocket.getLocalPort();
 
         byte[] b = new byte[12];
--- a/test/jdk/java/net/Socket/TestAfterClose.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/TestAfterClose.java	Fri May 03 14:59:32 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
@@ -39,8 +39,9 @@
 
     public static void main(String[] args) {
         try {
-            ServerSocket ss = new ServerSocket(0, 0, null);
-            Socket socket = new Socket("localhost", ss.getLocalPort());
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            ServerSocket ss = new ServerSocket(0, 0, loopback);
+            Socket socket = new Socket(loopback, ss.getLocalPort());
             ss.accept();
             ss.close();
             test(socket);
--- a/test/jdk/java/net/Socket/UrgentDataTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socket/UrgentDataTest.java	Fri May 03 14:59:32 2019 -0400
@@ -54,10 +54,12 @@
         try {
             UrgentDataTest test = new UrgentDataTest ();
             if (args.length == 0) {
-                test.listener = new ServerSocket (0);
+                InetAddress loopback = InetAddress.getLoopbackAddress();
+                test.listener = new ServerSocket ();
+                test.listener.bind(new InetSocketAddress(loopback, 0));
                 test.isClient = true;
                 test.isServer = true;
-                test.clHost = InetAddress.getLoopbackAddress().getHostAddress();
+                test.clHost = loopback.getHostAddress();
                 test.clPort = test.listener.getLocalPort();
                 test.run();
             } else if (args[0].equals ("-server")) {
--- a/test/jdk/java/net/SocketOption/OptionsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/SocketOption/OptionsTest.java	Fri May 03 14:59:32 2019 -0400
@@ -99,7 +99,7 @@
 
     static void doSocketTests() throws Exception {
         try (
-            ServerSocket srv = new ServerSocket(0);
+            ServerSocket srv = new ServerSocket(0, 50, InetAddress.getLoopbackAddress());
             Socket c = new Socket(InetAddress.getLoopbackAddress(), srv.getLocalPort());
             Socket s = srv.accept();
         ) {
--- a/test/jdk/java/net/Socks/SocksIPv6Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socks/SocksIPv6Test.java	Fri May 03 14:59:32 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
@@ -30,7 +30,6 @@
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.net.Authenticator;
@@ -43,7 +42,6 @@
 import java.net.ServerSocket;
 import java.net.SocketException;
 import java.net.NetworkInterface;
-import java.net.UnknownHostException;
 import java.util.Collections;
 import java.util.List;
 import com.sun.net.httpserver.*;
@@ -65,7 +63,7 @@
     public void setUp() throws Exception {
         shouldRun = ensureInet6AddressFamily() && ensureIPv6OnLoopback();
 
-        server = HttpServer.create(new InetSocketAddress(0), 0);
+        server = HttpServer.create(new InetSocketAddress("::1", 0), 0);
         server.createContext("/", ex -> {
             ex.sendResponseHeaders(200, response.length());
             try (BufferedWriter writer = new BufferedWriter(
@@ -76,7 +74,7 @@
         });
         server.start();
 
-        socks = new SocksServer(0, false);
+        socks = new SocksServer(InetAddress.getByName("::1"), 0, false);
         socks.addUser("user", "pass");
         socks.start();
 
@@ -140,21 +138,45 @@
     public void testSocksOverIPv6Hostname() throws Exception {
         if (!shouldRun) return;
 
-        String ipv6Hostname = InetAddress.getByName("::1").getHostName();
-        String ipv4Hostname = InetAddress.getByName("127.0.0.1").getHostName();
+        InetAddress ipv6Loopback = InetAddress.getByName("::1");
+        String ipv6Hostname = ipv6Loopback.getHostName();
+        String ipv6HostAddress = ipv6Loopback.getHostAddress();
+        InetAddress ipv4Loopback;
+        String ipv4Hostname;
+        String ipv4HostAddress;
+        try {
+            ipv4Loopback = InetAddress.getByName("127.0.0.1");
+            ipv4Hostname = ipv4Loopback == null ? null : ipv4Loopback.getHostName();
+            ipv4HostAddress = ipv4Loopback == null ? null : ipv4Loopback.getHostAddress();
+        } catch (IOException io) {
+            ipv4Hostname = null;
+            ipv4HostAddress = null;
+        }
 
-        if (ipv6Hostname.equals(InetAddress.getByName("::1").getHostAddress())) {
+        System.out.println("ipv6Hostname: " + ipv6Hostname + " / " + ipv6HostAddress);
+        System.out.println("ipv4Hostname: " + ipv4Hostname + " / " + ipv4HostAddress);
+
+        if (ipv6Hostname.equals(ipv6HostAddress)) {
             System.out.println("Unable to get the hostname of the IPv6 loopback "
                     + "address. Skipping test case.");
             return;
         }
 
-        if (ipv6Hostname.equals(ipv4Hostname)) {
+        if (ipv4Hostname != null && ipv6Hostname.equals(ipv4Hostname)) {
             System.out.println("IPv6 and IPv4 loopback addresses map to the"
                     + " same hostname. Skipping test case.");
             return;
         }
 
+        if (!InetAddress.getByName(ipv6Hostname).getHostAddress()
+                .equals(ipv6HostAddress)) {
+            System.out.println(ipv6Hostname + " resolves to \""
+                    + InetAddress.getByName(ipv6Hostname).getHostAddress()
+                    + "\", not \"" + ipv6HostAddress +
+                    "\". Skipping test case.");
+            return;
+        }
+
         Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(ipv6Hostname,
                 socks.getPort()));
         URL url = new URL("http://" + ipv6Hostname + ":" + server.getAddress().getPort());
--- a/test/jdk/java/net/Socks/SocksServer.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/Socks/SocksServer.java	Fri May 03 14:59:32 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
@@ -491,6 +491,25 @@
         }
     }
 
+    public SocksServer(InetAddress addr, int port, boolean useV4) throws IOException {
+        this.port = port;
+        this.useV4 = useV4;
+        server = new ServerSocket();
+        if (port == 0 && addr == null) {
+            server.bind(null);
+            this.port = server.getLocalPort();
+        } else if (port == 0 && addr != null) {
+            server.bind(new InetSocketAddress(addr, 0));
+            this.port = server.getLocalPort();
+        } else if (addr == null) {
+            assert port != 0;
+            server.bind(new InetSocketAddress(port));
+        } else {
+            assert port != 0;
+            server.bind(new InetSocketAddress(addr, port));
+        }
+    }
+
     public SocksServer() throws IOException {
         this (DEFAULT_PORT);
     }
--- a/test/jdk/java/net/URL/GetContent.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/URL/GetContent.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, 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,11 +24,13 @@
 /**
  * @test
  * @bug 4145315
+ * @library /test/lib
  * @summary Test a read from nonexistant URL
  */
 
 import java.net.*;
 import java.io.*;
+import jdk.test.lib.net.URIBuilder;
 
 public class GetContent implements Runnable {
 
@@ -71,10 +73,12 @@
 
          boolean error = true;
          try {
-             String name = "http://localhost:" + ss.getLocalPort() +
-                           "/no-such-name";
-             java.net.URL url = null;
-             url = new java.net.URL(name);
+             java.net.URL url = URIBuilder.newBuilder()
+                 .scheme("http")
+                 .host(ss.getInetAddress())
+                 .port(ss.getLocalPort())
+                 .path("/no-such-name")
+                 .toURL();
              Object obj = url.getContent();
              InputStream in = (InputStream) obj;
              byte buff[] = new byte[200];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/URL/NonOverridableHandlerFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,64 @@
+/*
+ * 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 8217364
+ * @summary Custom URLStreamHandler for jrt or file protocol can override default handler
+ * @modules java.base/java.net:open
+ * @run main/othervm NonOverridableHandlerFactory
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class NonOverridableHandlerFactory implements URLStreamHandlerFactory {
+    @Override
+    public URLStreamHandler createURLStreamHandler(String protocol) {
+        return new NonOverridableHandler();
+    }
+
+    private static class NonOverridableHandler extends URLStreamHandler {
+        @Override
+        protected URLConnection openConnection(URL u) throws IOException {
+            throw new RuntimeException("CustomURLStreamHandler used for " + u);
+        }
+    }
+
+    public static void main(String[] args) {
+        URL.setURLStreamHandlerFactory(new NonOverridableHandlerFactory());
+        for (String protocol : new String[] {"file", "jrt"}) {
+            String urlString = protocol + ":///test/somefile";
+            try {
+                new URL(urlString).openConnection();
+            } catch(RuntimeException r) {
+                throw r;
+            } catch(Throwable t) {
+                // possible jrt initialization issue on exploded binary image etc.
+                System.out.println("encountered: " + t +
+                    "(testing: " + urlString + ")");
+            }
+            System.out.println("Default URLStreamHandler used for " + urlString);
+        }
+    }
+}
--- a/test/jdk/java/net/URLConnection/B5052093.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/URLConnection/B5052093.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, 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
@@ -64,9 +64,10 @@
     }
 
     public static void main(String[] args) throws Exception {
-        server = new TestHttpServer(new B5052093(), 1, 10, 0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        server = new TestHttpServer(new B5052093(), 1, 10, loopback, 0);
         try {
-            URL url = new URL("http://localhost:"+server.getLocalPort()+"/foo");
+            URL url = new URL("http://" + server.getAuthority() + "/foo");
             URLConnection conn = url.openConnection();
             int i = conn.getContentLength();
             long l = conn.getContentLengthLong();
--- a/test/jdk/java/net/URLPermission/nstest/LookupTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/net/URLPermission/nstest/LookupTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, 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
@@ -36,6 +36,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.NetPermission;
 import java.net.ProxySelector;
 import java.net.ServerSocket;
@@ -104,7 +106,7 @@
         String hostsFileName = CWD + "/LookupTestHosts";
         System.setProperty("jdk.net.hosts.file", hostsFileName);
         addMappingToHostsFile("allowedAndFound.com",
-                              "127.0.0.1",
+                              InetAddress.getLoopbackAddress().getHostAddress(),
                               hostsFileName,
                               false);
         addMappingToHostsFile("notAllowedButFound.com",
@@ -131,7 +133,9 @@
         private volatile boolean done;
 
         public Server() throws IOException {
-            serverSocket = new ServerSocket(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            serverSocket = new ServerSocket();
+            serverSocket.bind(new InetSocketAddress(loopback, 0));
             port = serverSocket.getLocalPort();
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,516 @@
+/*
+ * 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 8222774 4430139
+ * @run testng AdaptorStreams
+ * @summary Exercise socket adaptor input/output streams
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class AdaptorStreams {
+
+    /**
+     * Test read when bytes are available
+     */
+    public void testRead1() throws Exception {
+        withConnection((sc, peer) -> {
+            peer.getOutputStream().write(99);
+            int n = sc.socket().getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test read blocking before bytes are available
+     */
+    public void testRead2() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleWrite(peer.getOutputStream(), 99, 1000);
+            int n = sc.socket().getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test read when peer has closed connection
+     */
+    public void testRead3() throws Exception {
+        withConnection((sc, peer) -> {
+            peer.close();
+            int n = sc.socket().getInputStream().read();
+            assertTrue(n == -1);
+        });
+    }
+
+    /**
+     * Test read blocking before peer closes connection
+     */
+    public void testRead4() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleClose(peer, 1000);
+            int n = sc.socket().getInputStream().read();
+            assertTrue(n == -1);
+        });
+    }
+
+    /**
+     * Test async close of socket when thread blocked in read
+     */
+    public void testRead5() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleClose(sc, 2000);
+            InputStream in = sc.socket().getInputStream();
+            expectThrows(IOException.class, () -> in.read());
+        });
+    }
+
+    /**
+     * Test interrupt status set before read
+     */
+    public void testRead6() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+            Thread.currentThread().interrupt();
+            try {
+                InputStream in = s.getInputStream();
+                expectThrows(IOException.class, () -> in.read());
+            } finally {
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test interrupt of thread blocked in read
+     */
+    public void testRead7() throws Exception {
+        withConnection((sc, peer) -> {
+            Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
+            Socket s = sc.socket();
+            try {
+                InputStream in = s.getInputStream();
+                expectThrows(IOException.class, () -> in.read());
+            } finally {
+                interrupter.cancel(true);
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test read when channel is configured non-blocking
+     */
+    public void testRead8() throws Exception {
+        withConnection((sc, peer) -> {
+            sc.configureBlocking(false);
+            InputStream in = sc.socket().getInputStream();
+            expectThrows(IllegalBlockingModeException.class, () -> in.read());
+        });
+    }
+
+    /**
+     * Test timed read when bytes are available
+     */
+    public void testTimedRead1() throws Exception {
+        withConnection((sc, peer) -> {
+            peer.getOutputStream().write(99);
+            Socket s = sc.socket();
+            s.setSoTimeout(1000);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test timed read blocking before bytes are available
+     */
+    public void testTimedRead2() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleWrite(peer.getOutputStream(), 99, 1000);
+            Socket s = sc.socket();
+            s.setSoTimeout(5000);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test timed read when the read times out
+     */
+    public void testTimedRead3() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+            s.setSoTimeout(1000);
+            InputStream in = s.getInputStream();
+            expectThrows(SocketTimeoutException.class, () -> in.read());
+        });
+    }
+
+    /**
+     * Test async close of socket when thread blocked in timed read
+     */
+    public void testTimedRead4() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleClose(sc, 2000);
+            Socket s = sc.socket();
+            s.setSoTimeout(60*1000);
+            InputStream in = s.getInputStream();
+            expectThrows(IOException.class, () -> in.read());
+        });
+    }
+
+    /**
+     * Test interrupt status set before timed read
+     */
+    public void testTimedRead5() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+            Thread.currentThread().interrupt();
+            try {
+                s.setSoTimeout(60*1000);
+                InputStream in = s.getInputStream();
+                expectThrows(IOException.class, () -> in.read());
+            } finally {
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test interrupt of thread blocked in timed read
+     */
+    public void testTimedRead6() throws Exception {
+        withConnection((sc, peer) -> {
+            Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
+            Socket s = sc.socket();
+            try {
+                s.setSoTimeout(60*1000);
+                InputStream in = s.getInputStream();
+                expectThrows(IOException.class, () -> in.read());
+                assertTrue(s.isClosed());
+            } finally {
+                interrupter.cancel(true);
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test async close of socket when thread blocked in write
+     */
+    public void testWrite1() throws Exception {
+        withConnection((sc, peer) -> {
+            scheduleClose(sc, 2000);
+            expectThrows(IOException.class, () -> {
+                OutputStream out = sc.socket().getOutputStream();
+                byte[] data = new byte[64*1000];
+                while (true) {
+                    out.write(data);
+                }
+            });
+        });
+    }
+
+    /**
+     * Test interrupt status set before write
+     */
+    public void testWrite2() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+            Thread.currentThread().interrupt();
+            try {
+                OutputStream out = s.getOutputStream();
+                expectThrows(IOException.class, () -> out.write(99));
+            } finally {
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test interrupt of thread blocked in write
+     */
+    public void testWrite3() throws Exception {
+        withConnection((sc, peer) -> {
+            Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
+            Socket s = sc.socket();
+            try {
+                expectThrows(IOException.class, () -> {
+                    OutputStream out = sc.socket().getOutputStream();
+                    byte[] data = new byte[64*1000];
+                    while (true) {
+                        out.write(data);
+                    }
+                });
+            } finally {
+                interrupter.cancel(true);
+                Thread.interrupted();  // clear interrupt
+            }
+            assertTrue(s.isClosed());
+        });
+    }
+
+    /**
+     * Test write when channel is configured non-blocking
+     */
+    public void testWrite4() throws Exception {
+        withConnection((sc, peer) -> {
+            sc.configureBlocking(false);
+            OutputStream out = sc.socket().getOutputStream();
+            expectThrows(IllegalBlockingModeException.class, () -> out.write(99));
+        });
+    }
+
+    /**
+     * Test read when there are bytes available and another thread is blocked
+     * in write
+     */
+    public void testConcurrentReadWrite1() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in write
+            execute(() -> {
+                var data = new byte[64*1024];
+                OutputStream out = s.getOutputStream();
+                for (;;) {
+                    out.write(data);
+                }
+            });
+            Thread.sleep(1000); // give writer time to block
+
+            // test read when bytes are available
+            peer.getOutputStream().write(99);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test read blocking when another thread is blocked in write
+     */
+    public void testConcurrentReadWrite2() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in write
+            execute(() -> {
+                var data = new byte[64*1024];
+                OutputStream out = s.getOutputStream();
+                for (;;) {
+                    out.write(data);
+                }
+            });
+            Thread.sleep(1000); // give writer time to block
+
+            // test read blocking until bytes are available
+            scheduleWrite(peer.getOutputStream(), 99, 500);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test writing when another thread is blocked in read
+     */
+    public void testConcurrentReadWrite3() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in read
+            execute(() -> {
+                s.getInputStream().read();
+            });
+            Thread.sleep(100); // give reader time to block
+
+            // test write
+            s.getOutputStream().write(99);
+            int n = peer.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test timed read when there are bytes available and another thread is
+     * blocked in write
+     */
+    public void testConcurrentTimedReadWrite1() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in write
+            execute(() -> {
+                var data = new byte[64*1024];
+                OutputStream out = s.getOutputStream();
+                for (;;) {
+                    out.write(data);
+                }
+            });
+            Thread.sleep(1000); // give writer time to block
+
+            // test read when bytes are available
+            peer.getOutputStream().write(99);
+            s.setSoTimeout(60*1000);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test timed read blocking when another thread is blocked in write
+     */
+    public void testConcurrentTimedReadWrite2() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in write
+            execute(() -> {
+                var data = new byte[64*1024];
+                OutputStream out = s.getOutputStream();
+                for (;;) {
+                    out.write(data);
+                }
+            });
+            Thread.sleep(1000); // give writer time to block
+
+            // test read blocking until bytes are available
+            scheduleWrite(peer.getOutputStream(), 99, 500);
+            s.setSoTimeout(60*1000);
+            int n = s.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    /**
+     * Test writing when another thread is blocked in read
+     */
+    public void testConcurrentTimedReadWrite3() throws Exception {
+        withConnection((sc, peer) -> {
+            Socket s = sc.socket();
+
+            // block thread in read
+            execute(() -> {
+                s.setSoTimeout(60*1000);
+                s.getInputStream().read();
+            });
+            Thread.sleep(100); // give reader time to block
+
+            // test write
+            s.getOutputStream().write(99);
+            int n = peer.getInputStream().read();
+            assertTrue(n == 99);
+        });
+    }
+
+    // -- test infrastructure --
+
+    interface ThrowingTask {
+        void run() throws Exception;
+    }
+
+    interface ThrowingBiConsumer<T, U> {
+        void accept(T t, U u) throws Exception;
+    }
+
+    /**
+     * Invokes the consumer with a connected pair of socket channel and socket
+     */
+    static void withConnection(ThrowingBiConsumer<SocketChannel, Socket> consumer)
+        throws Exception
+    {
+        try (ServerSocket ss = new ServerSocket(0);
+             SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+             Socket peer = ss.accept()) {
+            consumer.accept(sc, peer);
+        }
+    }
+
+    static Future<?> scheduleWrite(OutputStream out, byte[] data, long delay) {
+        return schedule(() -> {
+            try {
+                out.write(data);
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    static Future<?> scheduleWrite(OutputStream out, int b, long delay) {
+        return scheduleWrite(out, new byte[] { (byte)b }, delay);
+    }
+
+    static Future<?> scheduleClose(Closeable c, long delay) {
+        return schedule(() -> {
+            try {
+                c.close();
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    static Future<?> scheduleInterrupt(Thread t, long delay) {
+        return schedule(() -> t.interrupt(), delay);
+    }
+
+    static Future<?> schedule(Runnable task, long delay) {
+        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+        try {
+            return executor.schedule(task, delay, TimeUnit.MILLISECONDS);
+        } finally {
+            executor.shutdown();
+        }
+    }
+
+    static Future<?> execute(ThrowingTask task) {
+        ExecutorService pool = Executors.newFixedThreadPool(1);
+        try {
+            return pool.submit(() -> {
+                task.run();
+                return null;
+            });
+        } finally {
+            pool.shutdown();
+        }
+    }
+}
--- a/test/jdk/java/nio/channels/SocketChannel/Stream.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2001, 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 4430139
- * @summary Test result of read on stream from nonblocking channel
- * @library .. /test/lib
- * @build jdk.test.lib.Utils TestServers
- * @run main Stream
- */
-
-import java.io.*;
-import java.net.*;
-import java.nio.channels.*;
-
-
-public class Stream {
-
-    static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
-        InetSocketAddress isa
-            = new InetSocketAddress(daytimeServer.getAddress(),
-                                    daytimeServer.getPort());
-        SocketChannel sc = SocketChannel.open();
-        sc.connect(isa);
-        sc.configureBlocking(false);
-        InputStream is = sc.socket().getInputStream();
-        byte b[] = new byte[10];
-        try {
-            int n = is.read(b);
-            throw new RuntimeException("Exception expected; none thrown");
-        } catch (IllegalBlockingModeException e) {
-            // expected result
-        }
-        sc.close();
-    }
-
-    public static void main(String[] args) throws Exception {
-        try (TestServers.DayTimeServer dayTimeServer
-                = TestServers.DayTimeServer.startNewServer(100)) {
-            test(dayTimeServer);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/file/Files/SymlinkTime.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,121 @@
+/*
+ * 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 8220793
+ * @summary Unit test for updating access and modification times of symlinks
+ * @requires (os.family == "linux" | os.family == "mac" | os.family == "windows")
+ * @library ..
+ * @build SymlinkTime
+ * @run main/othervm SymlinkTime
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileTime;
+
+public class SymlinkTime {
+    public static void main(String[] args) throws IOException {
+        Path dir = TestUtil.createTemporaryDirectory();
+        if (!TestUtil.supportsLinks(dir)) {
+            System.out.println("Links not supported: skipping test");
+            return;
+        }
+
+        try {
+            // Create file and symbolic link to it
+            final Path file = dir.resolve("file");
+            final Path link = dir.resolve("link");
+            Files.createFile(file);
+            try {
+                // Delay creating the link to get different time attributes
+                Thread.currentThread().sleep(5000);
+            } catch (InterruptedException ignored) {
+            }
+            Files.createSymbolicLink(link, file);
+
+            // Save file modification and access times
+            BasicFileAttributeView view = Files.getFileAttributeView(link,
+                BasicFileAttributeView.class);
+            BasicFileAttributes attr = view.readAttributes();
+            printTimes("Original file times", attr);
+            FileTime fileModTime = attr.lastModifiedTime();
+            FileTime fileAccTime = attr.lastAccessTime();
+
+            // Read link modification and access times
+            view = Files.getFileAttributeView(link,
+                BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
+            attr = view.readAttributes();
+            printTimes("Original link times", attr);
+
+            // Set new base time and offset increment
+            long base = 1000000000000L; // 2001-09-09T01:46:40Z
+            long delta = 1000*60L;
+
+            // Set new link modification and access times
+            FileTime linkModTime = FileTime.fromMillis(base + delta);
+            FileTime linkAccTime = FileTime.fromMillis(base + 2L*delta);
+            view.setTimes(linkModTime, linkAccTime, null);
+
+            // Verify link modification and access times updated correctly
+            view = Files.getFileAttributeView(link,
+                BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
+            attr = view.readAttributes();
+            printTimes("Updated link times", attr);
+            check("Link", attr, linkModTime, linkAccTime);
+
+            // Verify file modification and access times unchanged
+            view = Files.getFileAttributeView(file,
+                BasicFileAttributeView.class);
+            attr = view.readAttributes();
+            printTimes("File times", attr);
+            check("File", attr, fileModTime, fileAccTime);
+        } finally {
+            TestUtil.removeAll(dir);
+        }
+    }
+
+    private static void check(String pathType, BasicFileAttributes attr,
+        FileTime modTimeExpected, FileTime accTimeExpected) {
+        if (!attr.lastModifiedTime().equals(modTimeExpected) ||
+            !attr.lastAccessTime().equals(accTimeExpected)) {
+            String message = String.format(
+                "%s - modification time: expected %s, actual %s;%n" +
+                "access time: expected %s, actual %s.%n", pathType,
+                modTimeExpected, attr.lastModifiedTime(),
+                accTimeExpected, attr.lastAccessTime());
+            throw new RuntimeException(message);
+        }
+    }
+
+    private static void printTimes(String label, BasicFileAttributes attr) {
+        System.out.format
+            ("%s%ncreation:     %s%nmodification: %s%naccess:       %s%n%n",
+            label, attr.creationTime(), attr.lastModifiedTime(),
+            attr.lastAccessTime());
+    }
+}
--- a/test/jdk/java/security/KeyPairGenerator/FinalizeHalf.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/security/KeyPairGenerator/FinalizeHalf.java	Fri May 03 14:59:32 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 8163896
+ * @bug 8163896 8223003
  * @summary Finalizing one key of a KeyPair invalidates the other key
  */
 
--- a/test/jdk/java/util/Locale/Bug8040211.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/Locale/Bug8040211.java	Fri May 03 14:59:32 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
@@ -23,9 +23,9 @@
 
 /*
  * @test
- * @bug 8040211 8191404 8203872
+ * @bug 8040211 8191404 8203872 8222980
  * @summary Checks the IANA language subtag registry data update
- *          (LSR Revision: 2018-04-23) with Locale and Locale.LanguageRange
+ *          (LSR Revision: 2019-04-03) with Locale and Locale.LanguageRange
  *          class methods.
  * @run main Bug8040211
  */
@@ -115,7 +115,6 @@
         expected.add(new LanguageRange("taj", 0.9));
         expected.add(new LanguageRange("tsf", 0.9));
         expected.add(new LanguageRange("ar-hyw", 0.8));
-        expected.add(new LanguageRange("ar-arevmda", 0.8));
         expected.add(new LanguageRange("yug", 0.5));
         expected.add(new LanguageRange("yuu", 0.5));
         expected.add(new LanguageRange("gfx", 0.4));
@@ -188,7 +187,7 @@
         List<Locale> tagList = generateLocales(tags);
         String actualLocales
                 = showLocales(Locale.filter(priorityList, tagList, mode));
-        String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict, nts, pij, ar-arevela";
+        String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict, nts, pij";
 
         if (!expectedLocales.equals(actualLocales)) {
             error = true;
--- a/test/jdk/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Fri May 03 14:59:32 2019 -0400
@@ -167,14 +167,17 @@
         ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
         System.err.println("------ stacktrace dump start ------");
         for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
-            String name = info.getThreadName();
+            final String name = info.getThreadName();
+            String lockName;
             if ("Signal Dispatcher".equals(name))
                 continue;
             if ("Reference Handler".equals(name)
-                && info.getLockName().startsWith("java.lang.ref.Reference$Lock"))
+                && (lockName = info.getLockName()) != null
+                && lockName.startsWith("java.lang.ref.Reference$Lock"))
                 continue;
             if ("Finalizer".equals(name)
-                && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock"))
+                && (lockName = info.getLockName()) != null
+                && lockName.startsWith("java.lang.ref.ReferenceQueue$Lock"))
                 continue;
             System.err.print(info);
         }
--- a/test/jdk/java/util/concurrent/tck/Atomic8Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/Atomic8Test.java	Fri May 03 14:59:32 2019 -0400
@@ -518,7 +518,8 @@
      * null function argument
      */
     public void testGetAndUpdateNPE() {
-        Runnable[] throwingActions = {
+        assertThrows(
+            NullPointerException.class,
             () -> new AtomicLong().getAndUpdate(null),
             () -> new AtomicInteger().getAndUpdate(null),
             () -> new AtomicReference().getAndUpdate(null),
@@ -527,16 +528,15 @@
             () -> new AtomicReferenceArray(1).getAndUpdate(0, null),
             () -> aLongFieldUpdater().getAndUpdate(this, null),
             () -> anIntFieldUpdater().getAndUpdate(this, null),
-            () -> anIntegerFieldUpdater().getAndUpdate(this, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
+            () -> anIntegerFieldUpdater().getAndUpdate(this, null));
     }
 
     /**
      * All Atomic updateAndGet methods throw NullPointerException on null function argument
      */
     public void testUpdateAndGetNPE() {
-        Runnable[] throwingActions = {
+        assertThrows(
+            NullPointerException.class,
             () -> new AtomicLong().updateAndGet(null),
             () -> new AtomicInteger().updateAndGet(null),
             () -> new AtomicReference().updateAndGet(null),
@@ -545,9 +545,7 @@
             () -> new AtomicReferenceArray(1).updateAndGet(0, null),
             () -> aLongFieldUpdater().updateAndGet(this, null),
             () -> anIntFieldUpdater().updateAndGet(this, null),
-            () -> anIntegerFieldUpdater().updateAndGet(this, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
+            () -> anIntegerFieldUpdater().updateAndGet(this, null));
     }
 
     /**
@@ -555,7 +553,8 @@
      * on null function argument
      */
     public void testGetAndAccumulateNPE() {
-        Runnable[] throwingActions = {
+        assertThrows(
+            NullPointerException.class,
             () -> new AtomicLong().getAndAccumulate(1L, null),
             () -> new AtomicInteger().getAndAccumulate(1, null),
             () -> new AtomicReference().getAndAccumulate(one, null),
@@ -564,9 +563,7 @@
             () -> new AtomicReferenceArray(1).getAndAccumulate(0, one, null),
             () -> aLongFieldUpdater().getAndAccumulate(this, 1L, null),
             () -> anIntFieldUpdater().getAndAccumulate(this, 1, null),
-            () -> anIntegerFieldUpdater().getAndAccumulate(this, one, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
+            () -> anIntegerFieldUpdater().getAndAccumulate(this, one, null));
     }
 
     /**
@@ -574,7 +571,8 @@
      * on null function argument
      */
     public void testAccumulateAndGetNPE() {
-        Runnable[] throwingActions = {
+        assertThrows(
+            NullPointerException.class,
             () -> new AtomicLong().accumulateAndGet(1L, null),
             () -> new AtomicInteger().accumulateAndGet(1, null),
             () -> new AtomicReference().accumulateAndGet(one, null),
@@ -583,9 +581,7 @@
             () -> new AtomicReferenceArray(1).accumulateAndGet(0, one, null),
             () -> aLongFieldUpdater().accumulateAndGet(this, 1L, null),
             () -> anIntFieldUpdater().accumulateAndGet(this, 1, null),
-            () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null),
-        };
-        assertThrows(NullPointerException.class, throwingActions);
+            () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null));
     }
 
     /**
@@ -598,9 +594,9 @@
         final AtomicLongFieldUpdater longUpdater = aLongFieldUpdater();
         final AtomicIntegerFieldUpdater intUpdater = anIntFieldUpdater();
         final AtomicReferenceFieldUpdater refUpdater = anIntegerFieldUpdater();
-        final Object obj = new Object();
         for (Object x : new Object[]{ new Object(), null }) {
-            Runnable[] throwingActions = {
+            assertThrows(
+                ClassCastException.class,
                 () -> longUpdater.get(x),
                 () -> intUpdater.get(x),
                 () -> refUpdater.get(x),
@@ -618,9 +614,7 @@
 
                 () -> longUpdater.compareAndSet(x, 17L, 42L),
                 () -> intUpdater.compareAndSet(x, 17, 42),
-                () -> refUpdater.compareAndSet(x, (Integer) 17, (Integer) 42),
-            };
-            assertThrows(ClassCastException.class, throwingActions);
+                () -> refUpdater.compareAndSet(x, (Integer) 17, (Integer) 42));
         }
     }
 
--- a/test/jdk/java/util/concurrent/tck/AtomicIntegerArray9Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/AtomicIntegerArray9Test.java	Fri May 03 14:59:32 2019 -0400
@@ -52,7 +52,9 @@
         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
         for (int index : new int[] { -1, SIZE }) {
             final int j = index;
-            final Runnable[] tasks = {
+
+            assertThrows(
+                IndexOutOfBoundsException.class,
                 () -> aa.getPlain(j),
                 () -> aa.getOpaque(j),
                 () -> aa.getAcquire(j),
@@ -65,10 +67,7 @@
                 () -> aa.weakCompareAndSetPlain(j, 1, 2),
                 () -> aa.weakCompareAndSetVolatile(j, 1, 2),
                 () -> aa.weakCompareAndSetAcquire(j, 1, 2),
-                () -> aa.weakCompareAndSetRelease(j, 1, 2),
-            };
-
-            assertThrows(IndexOutOfBoundsException.class, tasks);
+                () -> aa.weakCompareAndSetRelease(j, 1, 2));
         }
     }
 
--- a/test/jdk/java/util/concurrent/tck/AtomicLongArray9Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/AtomicLongArray9Test.java	Fri May 03 14:59:32 2019 -0400
@@ -51,7 +51,8 @@
         AtomicLongArray aa = new AtomicLongArray(SIZE);
         for (int index : new int[] { -1, SIZE }) {
             final int j = index;
-            final Runnable[] tasks = {
+              assertThrows(
+                IndexOutOfBoundsException.class,
                 () -> aa.getPlain(j),
                 () -> aa.getOpaque(j),
                 () -> aa.getAcquire(j),
@@ -64,10 +65,7 @@
                 () -> aa.weakCompareAndSetPlain(j, 1, 2),
                 () -> aa.weakCompareAndSetVolatile(j, 1, 2),
                 () -> aa.weakCompareAndSetAcquire(j, 1, 2),
-                () -> aa.weakCompareAndSetRelease(j, 1, 2),
-            };
-
-            assertThrows(IndexOutOfBoundsException.class, tasks);
+                () -> aa.weakCompareAndSetRelease(j, 1, 2));
         }
     }
 
--- a/test/jdk/java/util/concurrent/tck/AtomicReferenceArray9Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/AtomicReferenceArray9Test.java	Fri May 03 14:59:32 2019 -0400
@@ -51,7 +51,8 @@
         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
         for (int index : new int[] { -1, SIZE }) {
             final int j = index;
-            final Runnable[] tasks = {
+            assertThrows(
+                IndexOutOfBoundsException.class,
                 () -> aa.getPlain(j),
                 () -> aa.getOpaque(j),
                 () -> aa.getAcquire(j),
@@ -64,10 +65,7 @@
                 () -> aa.weakCompareAndSetPlain(j, null, null),
                 () -> aa.weakCompareAndSetVolatile(j, null, null),
                 () -> aa.weakCompareAndSetAcquire(j, null, null),
-                () -> aa.weakCompareAndSetRelease(j, null, null),
-            };
-
-            assertThrows(IndexOutOfBoundsException.class, tasks);
+                () -> aa.weakCompareAndSetRelease(j, null, null));
         }
     }
 
--- a/test/jdk/java/util/concurrent/tck/Collection8Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/Collection8Test.java	Fri May 03 14:59:32 2019 -0400
@@ -237,41 +237,17 @@
             BlockingQueue q = (BlockingQueue) c;
             assertThrows(
                 NullPointerException.class,
-                () -> {
-                    try { q.offer(null, 1L, HOURS); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }},
-                () -> {
-                    try { q.put(null); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }});
+                () -> q.offer(null, 1L, HOURS),
+                () -> q.put(null));
         }
         if (c instanceof BlockingDeque) {
             BlockingDeque q = (BlockingDeque) c;
             assertThrows(
                 NullPointerException.class,
-                () -> {
-                    try { q.offerFirst(null, 1L, HOURS); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }},
-                () -> {
-                    try { q.offerLast(null, 1L, HOURS); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }},
-                () -> {
-                    try { q.putFirst(null); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }},
-                () -> {
-                    try { q.putLast(null); }
-                    catch (InterruptedException ex) {
-                        throw new AssertionError(ex);
-                    }});
+                () -> q.offerFirst(null, 1L, HOURS),
+                () -> q.offerLast(null, 1L, HOURS),
+                () -> q.putFirst(null),
+                () -> q.putLast(null));
         }
     }
 
@@ -979,6 +955,10 @@
         } catch (java.io.NotSerializableException acceptable) {}
     }
 
+    /**
+     * TODO: move out of limbo
+     * 8203662: remove increment of modCount from ArrayList and Vector replaceAll()
+     */
     public void DISABLED_testReplaceAllIsNotStructuralModification() {
         Collection c = impl.emptyCollection();
         if (!(c instanceof List))
--- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java	Fri May 03 14:59:32 2019 -0400
@@ -3465,7 +3465,9 @@
         CompletableFuture<Integer> nullFuture = (CompletableFuture<Integer>)null;
         ThreadExecutor exec = new ThreadExecutor();
 
-        Runnable[] throwingActions = {
+        assertThrows(
+            NullPointerException.class,
+
             () -> CompletableFuture.supplyAsync(null),
             () -> CompletableFuture.supplyAsync(null, exec),
             () -> CompletableFuture.supplyAsync(new IntegerSupplier(ExecutionMode.SYNC, 42), null),
@@ -3568,10 +3570,8 @@
             () -> f.completeOnTimeout(42, 1L, null),
 
             () -> CompletableFuture.failedFuture(null),
-            () -> CompletableFuture.failedStage(null),
-        };
-
-        assertThrows(NullPointerException.class, throwingActions);
+            () -> CompletableFuture.failedStage(null));
+
         assertEquals(0, exec.count.get());
     }
 
--- a/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java	Fri May 03 14:59:32 2019 -0400
@@ -900,14 +900,13 @@
         RecursiveAction a = new CheckedRecursiveAction() {
             protected void realCompute() {
                 AsyncFib nul = null;
-                Runnable[] throwingActions = {
+                assertThrows(
+                    NullPointerException.class,
                     () -> invokeAll(nul),
                     () -> invokeAll(nul, nul),
                     () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
                     () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
-                    () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)),
-                };
-                assertThrows(NullPointerException.class, throwingActions);
+                    () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)));
             }};
         testInvokeOnPool(pool, a);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/concurrent/tck/HashtableTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,56 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from members
+ * of JCP JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Map;
+import java.util.Hashtable;
+
+import junit.framework.Test;
+
+public class HashtableTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        class Implementation implements MapImplementation {
+            public Class<?> klazz() { return Hashtable.class; }
+            public Map emptyMap() { return new Hashtable(); }
+            public Object makeKey(int i) { return i; }
+            public Object makeValue(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNullKeys() { return false; }
+            public boolean permitsNullValues() { return false; }
+            public boolean supportsSetValue() { return true; }
+        }
+        return newTestSuite(MapTest.testSuite(new Implementation()));
+    }
+}
--- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java	Fri May 03 14:59:32 2019 -0400
@@ -544,6 +544,7 @@
             ExecutorsTest.suite(),
             ExecutorCompletionServiceTest.suite(),
             FutureTaskTest.suite(),
+            HashtableTest.suite(),
             LinkedBlockingDequeTest.suite(),
             LinkedBlockingQueueTest.suite(),
             LinkedListTest.suite(),
@@ -1777,12 +1778,11 @@
         }
     }
 
-    void assertImmutable(final Object o) {
+    void assertImmutable(Object o) {
         if (o instanceof Collection) {
             assertThrows(
                 UnsupportedOperationException.class,
-                new Runnable() { public void run() {
-                        ((Collection) o).add(null);}});
+                () -> ((Collection) o).add(null));
         }
     }
 
@@ -1842,8 +1842,8 @@
     }
 
     public void assertThrows(Class<? extends Throwable> expectedExceptionClass,
-                             Runnable... throwingActions) {
-        for (Runnable throwingAction : throwingActions) {
+                             Action... throwingActions) {
+        for (Action throwingAction : throwingActions) {
             boolean threw = false;
             try { throwingAction.run(); }
             catch (Throwable t) {
--- a/test/jdk/java/util/concurrent/tck/MapTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/MapTest.java	Fri May 03 14:59:32 2019 -0400
@@ -200,6 +200,32 @@
         assertEquals(size1 + size2, m1.size());
     }
 
+    /**
+     * 8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone
+     */
+    public void testClone() {
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        final int size = rnd.nextInt(4);
+        final Map map = impl.emptyMap();
+        for (int i = 0; i < size; i++)
+            map.put(impl.makeKey(i), impl.makeValue(i));
+        final Map clone = cloneableClone(map);
+        if (clone == null) return;      // not cloneable?
+
+        assertEquals(size, map.size());
+        assertEquals(size, clone.size());
+        assertEquals(map.isEmpty(), clone.isEmpty());
+
+        clone.put(impl.makeKey(-1), impl.makeValue(-1));
+        assertEquals(size, map.size());
+        assertEquals(size + 1, clone.size());
+
+        clone.clear();
+        assertEquals(size, map.size());
+        assertEquals(0, clone.size());
+        assertTrue(clone.isEmpty());
+    }
+
 //     public void testFailsIntentionallyForDebugging() {
 //         fail(impl.klazz().getSimpleName());
 //     }
--- a/test/jdk/java/util/concurrent/tck/SplittableRandomTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/SplittableRandomTest.java	Fri May 03 14:59:32 2019 -0400
@@ -165,12 +165,11 @@
      */
     public void testNextIntBoundNonPositive() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextInt(-17),
             () -> sr.nextInt(0),
-            () -> sr.nextInt(Integer.MIN_VALUE),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextInt(Integer.MIN_VALUE));
     }
 
     /**
@@ -178,12 +177,11 @@
      */
     public void testNextIntBadBounds() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextInt(17, 2),
             () -> sr.nextInt(-42, -42),
-            () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE));
     }
 
     /**
@@ -235,12 +233,11 @@
      */
     public void testNextLongBoundNonPositive() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextLong(-17L),
             () -> sr.nextLong(0L),
-            () -> sr.nextLong(Long.MIN_VALUE),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextLong(Long.MIN_VALUE));
     }
 
     /**
@@ -248,12 +245,11 @@
      */
     public void testNextLongBadBounds() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextLong(17L, 2L),
             () -> sr.nextLong(-42L, -42L),
-            () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE));
     }
 
     /**
@@ -304,14 +300,13 @@
      */
     public void testNextDoubleBoundNonPositive() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextDouble(-17.0d),
             () -> sr.nextDouble(0.0d),
             () -> sr.nextDouble(-Double.MIN_VALUE),
             () -> sr.nextDouble(Double.NEGATIVE_INFINITY),
-            () -> sr.nextDouble(Double.NaN),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextDouble(Double.NaN));
     }
 
     /**
@@ -319,14 +314,13 @@
      */
     public void testNextDoubleBadBounds() {
         SplittableRandom sr = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> sr.nextDouble(17.0d, 2.0d),
             () -> sr.nextDouble(-42.0d, -42.0d),
             () -> sr.nextDouble(Double.MAX_VALUE, Double.MIN_VALUE),
             () -> sr.nextDouble(Double.NaN, 0.0d),
-            () -> sr.nextDouble(0.0d, Double.NaN),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> sr.nextDouble(0.0d, Double.NaN));
     }
 
     // TODO: Test infinite bounds!
@@ -361,15 +355,14 @@
      */
     public void testBadStreamSize() {
         SplittableRandom r = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> { java.util.stream.IntStream x = r.ints(-1L); },
             () -> { java.util.stream.IntStream x = r.ints(-1L, 2, 3); },
             () -> { java.util.stream.LongStream x = r.longs(-1L); },
             () -> { java.util.stream.LongStream x = r.longs(-1L, -1L, 1L); },
             () -> { java.util.stream.DoubleStream x = r.doubles(-1L); },
-            () -> { java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6); },
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> { java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6); });
     }
 
     /**
@@ -378,15 +371,14 @@
      */
     public void testBadStreamBounds() {
         SplittableRandom r = new SplittableRandom();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> { java.util.stream.IntStream x = r.ints(2, 1); },
             () -> { java.util.stream.IntStream x = r.ints(10, 42, 42); },
             () -> { java.util.stream.LongStream x = r.longs(-1L, -1L); },
             () -> { java.util.stream.LongStream x = r.longs(10, 1L, -2L); },
             () -> { java.util.stream.DoubleStream x = r.doubles(0.0, 0.0); },
-            () -> { java.util.stream.DoubleStream x = r.doubles(10, .5, .4); },
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> { java.util.stream.DoubleStream x = r.doubles(10, .5, .4); });
     }
 
     /**
--- a/test/jdk/java/util/concurrent/tck/StampedLockTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1009,106 +1009,117 @@
      * IllegalMonitorStateException
      */
     public void testCannotUnlockOptimisticReadStamps() {
-        Runnable[] actions = {
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = assertValid(sl, sl.tryOptimisticRead());
-                sl.unlockRead(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryOptimisticRead();
-                sl.unlock(stamp);
-            },
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = assertValid(sl, sl.tryOptimisticRead());
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockRead(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryOptimisticRead();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
 
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryOptimisticRead();
-                sl.writeLock();
-                sl.unlock(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                sl.readLock();
-                long stamp = assertValid(sl, sl.tryOptimisticRead());
-                sl.unlockRead(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                sl.readLock();
-                long stamp = assertValid(sl, sl.tryOptimisticRead());
-                sl.unlock(stamp);
-            },
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryOptimisticRead();
+            sl.writeLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            sl.readLock();
+            long stamp = assertValid(sl, sl.tryOptimisticRead());
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockRead(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            sl.readLock();
+            long stamp = assertValid(sl, sl.tryOptimisticRead());
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
 
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
-                assertValid(sl, stamp);
-                sl.writeLock();
-                sl.unlockWrite(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
-                sl.writeLock();
-                sl.unlock(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
-                sl.readLock();
-                sl.unlockRead(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
-                sl.readLock();
-                sl.unlock(stamp);
-            },
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+            assertValid(sl, stamp);
+            sl.writeLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockWrite(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+            sl.writeLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockRead(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
 
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                assertValid(sl, stamp);
-                sl.writeLock();
-                sl.unlockWrite(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                sl.writeLock();
-                sl.unlock(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                sl.readLock();
-                sl.unlockRead(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                sl.readLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                assertValid(sl, stamp);
-                sl.readLock();
-                sl.unlockRead(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                sl.readLock();
-                sl.unlock(stamp);
-            },
-            () -> {
-                StampedLock sl = new StampedLock();
-                sl.readLock();
-                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
-                sl.readLock();
-                sl.unlock(stamp);
-            },
-        };
-
-        assertThrows(IllegalMonitorStateException.class, actions);
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            assertValid(sl, stamp);
+            sl.writeLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockWrite(stamp));
+            }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            sl.writeLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockRead(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            sl.readLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            assertValid(sl, stamp);
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlockRead(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
+        {
+            StampedLock sl = new StampedLock();
+            sl.readLock();
+            long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+            sl.readLock();
+            assertThrows(IllegalMonitorStateException.class,
+                () -> sl.unlock(stamp));
+        }
     }
 
     static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
--- a/test/jdk/java/util/concurrent/tck/ThreadLocalRandom8Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/ThreadLocalRandom8Test.java	Fri May 03 14:59:32 2019 -0400
@@ -63,15 +63,14 @@
      */
     public void testBadStreamSize() {
         ThreadLocalRandom r = ThreadLocalRandom.current();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> r.ints(-1L),
             () -> r.ints(-1L, 2, 3),
             () -> r.longs(-1L),
             () -> r.longs(-1L, -1L, 1L),
             () -> r.doubles(-1L),
-            () -> r.doubles(-1L, .5, .6),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> r.doubles(-1L, .5, .6));
     }
 
     /**
@@ -80,15 +79,14 @@
      */
     public void testBadStreamBounds() {
         ThreadLocalRandom r = ThreadLocalRandom.current();
-        Runnable[] throwingActions = {
+        assertThrows(
+            IllegalArgumentException.class,
             () -> r.ints(2, 1),
             () -> r.ints(10, 42, 42),
             () -> r.longs(-1L, -1L),
             () -> r.longs(10, 1L, -2L),
             () -> r.doubles(0.0, 0.0),
-            () -> r.doubles(10, .5, .4),
-        };
-        assertThrows(IllegalArgumentException.class, throwingActions);
+            () -> r.doubles(10, .5, .4));
     }
 
     /**
--- a/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java	Fri May 03 14:59:32 2019 -0400
@@ -2011,4 +2011,49 @@
         assertTrue(p.getQueue().isEmpty());
     }
 
+    public void testThreadFactoryReturnsTerminatedThread_shouldThrow() {
+        if (!testImplementationDetails)
+            return;
+
+        ThreadFactory returnsTerminatedThread = runnableIgnored -> {
+            Thread thread = new Thread(() -> {});
+            thread.start();
+            try { thread.join(); }
+            catch (InterruptedException ex) { throw new Error(ex); }
+            return thread;
+        };
+        ThreadPoolExecutor p =
+            new ThreadPoolExecutor(1, 1, 1, SECONDS,
+                                   new ArrayBlockingQueue<Runnable>(1),
+                                   returnsTerminatedThread);
+        try (PoolCleaner cleaner = cleaner(p)) {
+            assertThrows(IllegalThreadStateException.class,
+                         () -> p.execute(() -> {}));
+        }
+    }
+
+    public void testThreadFactoryReturnsStartedThread_shouldThrow() {
+        if (!testImplementationDetails)
+            return;
+
+        CountDownLatch latch = new CountDownLatch(1);
+        Runnable awaitLatch = () -> {
+            try { latch.await(); }
+            catch (InterruptedException ex) { throw new Error(ex); }};
+        ThreadFactory returnsStartedThread = runnable -> {
+            Thread thread = new Thread(awaitLatch);
+            thread.start();
+            return thread;
+        };
+        ThreadPoolExecutor p =
+            new ThreadPoolExecutor(1, 1, 1, SECONDS,
+                                   new ArrayBlockingQueue<Runnable>(1),
+                                   returnsStartedThread);
+        try (PoolCleaner cleaner = cleaner(p)) {
+            assertThrows(IllegalThreadStateException.class,
+                         () -> p.execute(() -> {}));
+            latch.countDown();
+        }
+    }
+
 }
--- a/test/jdk/java/util/concurrent/tck/VectorTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/java/util/concurrent/tck/VectorTest.java	Fri May 03 14:59:32 2019 -0400
@@ -467,9 +467,8 @@
             assertEquals(n, v.size());
             assertNull(v.get(0));
             assertNull(v.get(n - 1));
-            assertThrows(
-                    ArrayIndexOutOfBoundsException.class,
-                    new Runnable() { public void run() { v.setSize(-1); }});
+            assertThrows(ArrayIndexOutOfBoundsException.class,
+                () -> v.setSize(-1));
             assertEquals(n, v.size());
             assertNull(v.get(0));
             assertNull(v.get(n - 1));
--- a/test/jdk/javax/net/ssl/compatibility/Client.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/Client.java	Fri May 03 14:59:32 2019 -0400
@@ -118,15 +118,15 @@
         String serverName = System.getProperty(Utils.PROP_SERVER_NAME);
         String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
         boolean supportsSNIOnServer
-                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_SERVER);
+                = Boolean.getBoolean(Utils.PROP_SUPPORTS_SNI_ON_SERVER);
         boolean supportsSNIOnClient
-                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_CLIENT);
+                = Boolean.getBoolean(Utils.PROP_SUPPORTS_SNI_ON_CLIENT);
         boolean supportsALPNOnServer
-                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+                = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
         boolean supportsALPNOnClient
-                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT);
+                = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT);
         boolean negativeCase
-                = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_CLIENT);
+                = Boolean.getBoolean(Utils.PROP_NEGATIVE_CASE_ON_CLIENT);
         System.out.println(Utils.join(Utils.PARAM_DELIMITER,
                 "ClientJDK=" + System.getProperty(Utils.PROP_CLIENT_JDK),
                 "Protocol=" + protocol,
--- a/test/jdk/javax/net/ssl/compatibility/Compatibility.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/Compatibility.java	Fri May 03 14:59:32 2019 -0400
@@ -57,20 +57,33 @@
 
 public class Compatibility {
 
-    public static void main(String[] args) throws Throwable {
-        String javaSecurityFile
-                = System.getProperty("test.src") + "/java.security";
-        boolean debug = Utils.getBoolProperty("debug");
+    protected List<UseCase> getUseCases() {
+        return UseCase.getAllUseCases();
+    }
 
-        Set<JdkInfo> jdkInfos = jdkInfoList();
+    protected Set<JdkInfo> getJdkInfos() {
+        return jdkInfoList();
+    }
 
-        System.out.println("Test start");
+    protected List<TestCase> runTest() throws Exception {
+        Set<JdkInfo> jdkInfos = getJdkInfos();
 
         List<TestCase> testCases = new ArrayList<>();
         ExecutorService executor = Executors.newCachedThreadPool();
         PrintStream origStdOut = System.out;
         PrintStream origStdErr = System.err;
 
+        boolean debug = Boolean.getBoolean("debug");
+
+        String securityPropertiesFile = System.getProperty(
+                "test.security.properties",
+                System.getProperty("test.src") + "/java.security");
+        System.out.println("security properties: " + securityPropertiesFile);
+
+        // If true, server and client CANNOT be a same JDK
+        boolean disallowSameEndpoint = Boolean.getBoolean("disallowSameEndpoint");
+        System.out.println("disallowSameEndpoint: " + disallowSameEndpoint);
+
         try (PrintStream printStream = new PrintStream(
                 new FileOutputStream(Utils.TEST_LOG, true))) {
             System.setOut(printStream);
@@ -79,13 +92,13 @@
             System.out.println(Utils.startHtml());
             System.out.println(Utils.startPre());
 
-            for (UseCase useCase : UseCase.getAllUseCases()) {
+            for (UseCase useCase : getUseCases()) {
                 for (JdkInfo serverJdk : jdkInfos) {
                     Map<String, String> props = new LinkedHashMap<>();
                     if (debug) {
                         props.put("javax.net.debug", "all");
                     }
-                    props.put("java.security.properties", javaSecurityFile);
+                    props.put("java.security.properties", securityPropertiesFile);
 
                     props.put(Utils.PROP_PROTOCOL, useCase.protocol.name);
                     props.put(Utils.PROP_CIPHER_SUITE, useCase.cipherSuite.name());
@@ -105,6 +118,10 @@
                             serverJdk.supportsALPN + "");
 
                     for (JdkInfo clientJdk : jdkInfos) {
+                        if (disallowSameEndpoint && clientJdk == serverJdk) {
+                            continue;
+                        }
+
                         TestCase testCase = new TestCase(serverJdk, clientJdk,
                                 useCase);
                         System.out.println(Utils.anchorName(testCase.toString(),
@@ -162,119 +179,11 @@
         System.setErr(origStdErr);
         executor.shutdown();
 
-        System.out.println("Test end");
-        System.out.println("Report is being generated...");
-        boolean failed = generateReport(testCases);
-        System.out.println("Report is generated.");
-        if (failed) {
-            throw new RuntimeException("At least one case failed. "
-                    + "Please check logs for more details.");
-        }
-    }
-
-    private static Status getStatus(String log) {
-        if (log.contains(Status.UNEXPECTED_SUCCESS.name())) {
-            return Status.UNEXPECTED_SUCCESS;
-        } else if (log.contains(Status.SUCCESS.name())) {
-            return Status.SUCCESS;
-        } else if (log.contains(Status.EXPECTED_FAIL.name())) {
-            return Status.EXPECTED_FAIL;
-        } else if (log.contains(Status.TIMEOUT.name())) {
-            return Status.TIMEOUT;
-        } else {
-            return Status.FAIL;
-        }
-    }
-
-    private static Status caseStatus(Status serverStatus, Status clientStatus) {
-        if (clientStatus == null || clientStatus == Status.TIMEOUT) {
-            return serverStatus == Status.EXPECTED_FAIL
-                   ? Status.EXPECTED_FAIL
-                   : Status.FAIL;
-        } else if (serverStatus == Status.TIMEOUT) {
-            return clientStatus == Status.EXPECTED_FAIL
-                   ? Status.EXPECTED_FAIL
-                   : Status.FAIL;
-        } else {
-            return serverStatus == clientStatus
-                   ? serverStatus
-                   : Status.FAIL;
-        }
-    }
-
-    // Retrieves JDK info from the file which is specified by jdkListFile.
-    // If no such file or no JDK is specified by the file, the current testing
-    // JDK will be used.
-    private static Set<JdkInfo> jdkInfoList() throws Throwable {
-        List<String> jdkList = jdkList("jdkListFile");
-        if (jdkList.size() == 0) {
-            jdkList.add(System.getProperty("test.jdk"));
-        }
-
-        Set<JdkInfo> jdkInfoList = new LinkedHashSet<>();
-        for (String jdkPath : jdkList) {
-            JdkInfo jdkInfo = new JdkInfo(jdkPath);
-            // JDK version must be unique.
-            if (!jdkInfoList.add(jdkInfo)) {
-                System.out.println("The JDK version is duplicate: " + jdkPath);
-            }
-        }
-        return jdkInfoList;
-    }
-
-    private static List<String> jdkList(String listFileProp) throws IOException {
-        String listFile = System.getProperty(listFileProp);
-        System.out.println(listFileProp + "=" + listFile);
-        if (listFile != null && Files.exists(Paths.get(listFile))) {
-            try (Stream<String> lines = Files.lines(Paths.get(listFile))) {
-                return lines.filter(line -> {
-                    return !line.trim().isEmpty();
-                }).collect(Collectors.toList());
-            }
-        } else {
-            return new ArrayList<>();
-        }
-    }
-
-    // Checks if server is already launched, and returns server port.
-    private static int waitForServerStarted()
-            throws IOException, InterruptedException {
-        System.out.print("Waiting for server");
-        long deadline = System.currentTimeMillis() + Utils.TIMEOUT;
-        int port;
-        while ((port = getServerPort()) == -1
-                && System.currentTimeMillis() < deadline) {
-            System.out.print(".");
-            TimeUnit.SECONDS.sleep(1);
-        }
-        System.out.println();
-
-        return port;
-    }
-
-    // Retrieves the latest server port from port.log.
-    private static int getServerPort() throws IOException {
-        if (!Files.exists(Paths.get(Utils.PORT_LOG))) {
-            return -1;
-        }
-
-        try (Stream<String> lines = Files.lines(Paths.get(Utils.PORT_LOG))) {
-            return Integer.valueOf(lines.findFirst().get());
-        }
-    }
-
-    private static OutputAnalyzer runServer(String jdkPath,
-            Map<String, String> props) {
-        return ProcessUtils.java(jdkPath, props, Server.class);
-    }
-
-    private static OutputAnalyzer runClient(String jdkPath,
-            Map<String, String> props) {
-        return ProcessUtils.java(jdkPath, props, Client.class);
+        return testCases;
     }
 
     // Generates the test result report.
-    private static boolean generateReport(List<TestCase> testCases)
+    protected boolean generateReport(List<TestCase> testCases)
             throws IOException {
         boolean failed = false;
         StringBuilder report = new StringBuilder();
@@ -321,6 +230,124 @@
         return failed;
     }
 
+    protected void run() throws Exception {
+        System.out.println("Test start");
+        List<TestCase> testCases= runTest();
+        System.out.println("Test end");
+
+        boolean failed = generateReport(testCases);
+        System.out.println("Report was generated.");
+
+        if (failed) {
+            throw new RuntimeException("At least one case failed. "
+                    + "Please check logs for more details.");
+        }
+    }
+
+    public static void main(String[] args) throws Throwable {
+        new Compatibility().run();;
+    }
+
+    private static Status getStatus(String log) {
+        if (log.contains(Status.UNEXPECTED_SUCCESS.name())) {
+            return Status.UNEXPECTED_SUCCESS;
+        } else if (log.contains(Status.SUCCESS.name())) {
+            return Status.SUCCESS;
+        } else if (log.contains(Status.EXPECTED_FAIL.name())) {
+            return Status.EXPECTED_FAIL;
+        } else if (log.contains(Status.TIMEOUT.name())) {
+            return Status.TIMEOUT;
+        } else {
+            return Status.FAIL;
+        }
+    }
+
+    private static Status caseStatus(Status serverStatus, Status clientStatus) {
+        if (clientStatus == null || clientStatus == Status.TIMEOUT) {
+            return serverStatus == Status.EXPECTED_FAIL
+                   ? Status.EXPECTED_FAIL
+                   : Status.FAIL;
+        } else if (serverStatus == Status.TIMEOUT) {
+            return clientStatus == Status.EXPECTED_FAIL
+                   ? Status.EXPECTED_FAIL
+                   : Status.FAIL;
+        } else {
+            return serverStatus == clientStatus
+                   ? serverStatus
+                   : Status.FAIL;
+        }
+    }
+
+    // Retrieves JDK info from the file which is specified by jdkListFile.
+    // And the current testing JDK, which is specified by test.jdk, always be used.
+    private static Set<JdkInfo> jdkInfoList() {
+        List<String> jdkList = jdkList();
+        jdkList.add(System.getProperty("test.jdk"));
+
+        Set<JdkInfo> jdkInfoList = new LinkedHashSet<>();
+        for (String jdkPath : jdkList) {
+            JdkInfo jdkInfo = new JdkInfo(jdkPath);
+            // JDK version must be unique.
+            if (!jdkInfoList.add(jdkInfo)) {
+                System.out.println("The JDK version is duplicate: " + jdkPath);
+            }
+        }
+        return jdkInfoList;
+    }
+
+    private static List<String> jdkList() {
+        String listFile = System.getProperty("jdkListFile");
+        System.out.println("jdk list file: " + listFile);
+        if (listFile != null && Files.exists(Paths.get(listFile))) {
+            try (Stream<String> lines = Files.lines(Paths.get(listFile))) {
+                return lines.filter(line -> {
+                    return !line.trim().isEmpty();
+                }).collect(Collectors.toList());
+            } catch (IOException e) {
+                throw new RuntimeException("Cannot get jdk list", e);
+            }
+        } else {
+            return new ArrayList<>();
+        }
+    }
+
+    // Checks if server is already launched, and returns server port.
+    private static int waitForServerStarted()
+            throws IOException, InterruptedException {
+        System.out.print("Waiting for server");
+        long deadline = System.currentTimeMillis() + Utils.TIMEOUT;
+        int port;
+        while ((port = getServerPort()) == -1
+                && System.currentTimeMillis() < deadline) {
+            System.out.print(".");
+            TimeUnit.SECONDS.sleep(1);
+        }
+        System.out.println();
+
+        return port;
+    }
+
+    // Retrieves the latest server port from port.log.
+    private static int getServerPort() throws IOException {
+        if (!Files.exists(Paths.get(Utils.PORT_LOG))) {
+            return -1;
+        }
+
+        try (Stream<String> lines = Files.lines(Paths.get(Utils.PORT_LOG))) {
+            return Integer.valueOf(lines.findFirst().get());
+        }
+    }
+
+    private static OutputAnalyzer runServer(String jdkPath,
+            Map<String, String> props) {
+        return ProcessUtils.java(jdkPath, props, Server.class);
+    }
+
+    private static OutputAnalyzer runClient(String jdkPath,
+            Map<String, String> props) {
+        return ProcessUtils.java(jdkPath, props, Client.class);
+    }
+
     private static void generateFile(String path, String content)
             throws IOException {
         try(FileWriter writer = new FileWriter(new File(path))) {
--- a/test/jdk/javax/net/ssl/compatibility/JdkInfo.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/JdkInfo.java	Fri May 03 14:59:32 2019 -0400
@@ -36,7 +36,7 @@
     public final boolean supportsSNI;
     public final boolean supportsALPN;
 
-    public JdkInfo(String jdkPath) throws Throwable {
+    public JdkInfo(String jdkPath) {
         this.jdkPath = jdkPath;
 
         String output = jdkAttributes(jdkPath);
@@ -54,7 +54,7 @@
     }
 
     // Determines the specific attributes for the specified JDK.
-    private static String jdkAttributes(String jdkPath) throws Throwable {
+    private static String jdkAttributes(String jdkPath) {
         return ProcessUtils.java(jdkPath, null, JdkUtils.class).getOutput();
     }
 
--- a/test/jdk/javax/net/ssl/compatibility/Server.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/Server.java	Fri May 03 14:59:32 2019 -0400
@@ -103,12 +103,12 @@
         String protocol = System.getProperty(Utils.PROP_PROTOCOL);
         String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
         boolean clientAuth
-                = Utils.getBoolProperty(Utils.PROP_CLIENT_AUTH);
+                = Boolean.getBoolean(Utils.PROP_CLIENT_AUTH);
         String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
         boolean supportsALPN
-                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+                = Boolean.getBoolean(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
         boolean negativeCase
-                = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_SERVER);
+                = Boolean.getBoolean(Utils.PROP_NEGATIVE_CASE_ON_SERVER);
 
         System.out.println(Utils.join(Utils.PARAM_DELIMITER,
                 "ServerJDK=" + System.getProperty(Utils.PROP_SERVER_JDK),
--- a/test/jdk/javax/net/ssl/compatibility/UseCase.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/UseCase.java	Fri May 03 14:59:32 2019 -0400
@@ -30,10 +30,10 @@
 public class UseCase {
 
     private static final boolean FULL_CASES
-            = Utils.getBoolProperty("fullCases");
+            = Boolean.getBoolean("fullCases");
 
     public static final boolean FULL_CIPHER_SUITES
-            = Utils.getBoolProperty("fullCipherSuites");
+            = Boolean.getBoolean("fullCipherSuites");
 
     public static final Protocol[] PROTOCOLS = new Protocol[] {
             Protocol.TLSV1,
@@ -129,7 +129,7 @@
     }
 
     private static final Object[][] PARAMS = new Object[][] {
-            FULL_CASES ? PROTOCOLS : PROTOCOLS,
+            PROTOCOLS,
             FULL_CASES ? CIPHER_SUITES : MANDATORY_CIPHER_SUITES,
             FULL_CASES ? new Boolean[] { false, true } : new Boolean[] { true },
             FULL_CASES
--- a/test/jdk/javax/net/ssl/compatibility/Utils.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/javax/net/ssl/compatibility/Utils.java	Fri May 03 14:59:32 2019 -0400
@@ -166,10 +166,6 @@
         return bool ? "Y" : "N";
     }
 
-    public static boolean getBoolProperty(String prop) {
-        return Boolean.valueOf(System.getProperty(prop));
-    }
-
     public static Status handleException(Exception exception,
             boolean negativeCase) {
         Status status;
--- a/test/jdk/jdk/nio/zipfs/Basic.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/Basic.java	Fri May 03 14:59:32 2019 -0400
@@ -69,7 +69,7 @@
 
         // Test: FileSystems#newFileSystem(Path)
         Map<String,?> env = Collections.emptyMap();
-        FileSystems.newFileSystem(jarFile, null).close();
+        FileSystems.newFileSystem(jarFile).close();
 
         // Test: FileSystems#newFileSystem(URI)
         URI uri = new URI("jar", jarFile.toUri().toString(), null);
--- a/test/jdk/jdk/nio/zipfs/Demo.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/Demo.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, 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
@@ -27,7 +27,6 @@
 import java.nio.file.*;
 import java.nio.file.spi.*;
 import java.nio.file.attribute.*;
-import java.net.*;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -98,8 +97,6 @@
 
         mkdirs,          // <java Demo mkdirs zipfile dir>
 
-        rmdirs,          // <java Demo rmdirs zipfile dir>
-
         list,            // <java Demo list zipfile [dir]>
                          // recursively list all entries of dir
                          // via DirectoryStream
@@ -144,7 +141,7 @@
         }
 
         Action action = Action.valueOf(args[0]);
-        Map<String, Object> env = env = new HashMap<>();
+        Map<String, Object> env = new HashMap<>();
         if (action == Action.create)
             env.put("create", "true");
         try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
@@ -534,10 +531,10 @@
         Files.createDirectory(path);
     }
 
-    @SuppressWarnings("unused")
     /**
      * Not used in demo, but included for demonstrational purposes.
      */
+    @SuppressWarnings("unused")
     private static void rmdirs(Path path) throws IOException {
         while (path != null && path.getNameCount() != 0) {
             Files.delete(path);
@@ -561,11 +558,11 @@
         }
     }
 
-    @SuppressWarnings("unused")
     /**
      * Checks that the content of two paths are equal.
      * Not used in demo, but included for demonstrational purposes.
      */
+    @SuppressWarnings("unused")
     private static void checkEqual(Path src, Path dst) throws IOException
     {
         //System.out.printf("checking <%s> vs <%s>...%n",
@@ -638,8 +635,11 @@
         }
     }
 
-    private static void fchCopy(Path src, Path dst) throws IOException
-    {
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    @SuppressWarnings("unused")
+    private static void fchCopy(Path src, Path dst) throws IOException {
         Set<OpenOption> read = new HashSet<>();
         read.add(READ);
         Set<OpenOption> openwrite = new HashSet<>();
@@ -658,8 +658,11 @@
         }
     }
 
-    private static void chCopy(Path src, Path dst) throws IOException
-    {
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    @SuppressWarnings("unused")
+    private static void chCopy(Path src, Path dst) throws IOException {
         Set<OpenOption> read = new HashSet<>();
         read.add(READ);
         Set<OpenOption> openwrite = new HashSet<>();
@@ -678,8 +681,11 @@
         }
     }
 
-    private static void streamCopy(Path src, Path dst) throws IOException
-    {
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    @SuppressWarnings("unused")
+    private static void streamCopy(Path src, Path dst) throws IOException {
         byte[] buf = new byte[8192];
         try (InputStream isSrc = Files.newInputStream(src);
              OutputStream osDst = Files.newOutputStream(dst))
--- a/test/jdk/jdk/nio/zipfs/MultiReleaseJarTest.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +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 8144355 8144062 8176709 8194070 8193802
- * @summary Test aliasing additions to ZipFileSystem for multi-release jar files
- * @library /lib/testlibrary/java/util/jar
- * @modules jdk.compiler
- *          jdk.jartool
- *          jdk.zipfs
- * @build Compiler JarBuilder CreateMultiReleaseTestJars
- * @run testng MultiReleaseJarTest
- */
-
-import java.io.IOException;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.Runtime.Version;
-import java.net.URI;
-import java.nio.file.*;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.testng.Assert;
-import org.testng.annotations.*;
-
-public class MultiReleaseJarTest {
-    final private int MAJOR_VERSION = Runtime.version().major();
-
-    final private String userdir = System.getProperty("user.dir",".");
-    final private CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
-    final private Map<String,String> stringEnv = new HashMap<>();
-    final private Map<String,Integer> integerEnv = new HashMap<>();
-    final private Map<String,Version> versionEnv = new HashMap<>();
-    final private String className = "version.Version";
-    final private MethodType mt = MethodType.methodType(int.class);
-
-    private String entryName;
-    private URI uvuri;
-    private URI mruri;
-    private URI smruri;
-
-    @BeforeClass
-    public void initialize() throws Exception {
-        creator.compileEntries();
-        creator.buildUnversionedJar();
-        creator.buildMultiReleaseJar();
-        creator.buildShortMultiReleaseJar();
-        String ssp = Paths.get(userdir, "unversioned.jar").toUri().toString();
-        uvuri = new URI("jar", ssp , null);
-        ssp = Paths.get(userdir, "multi-release.jar").toUri().toString();
-        mruri = new URI("jar", ssp, null);
-        ssp = Paths.get(userdir, "short-multi-release.jar").toUri().toString();
-        smruri = new URI("jar", ssp, null);
-        entryName = className.replace('.', '/') + ".class";
-    }
-
-    public void close() throws IOException {
-        Files.delete(Paths.get(userdir, "unversioned.jar"));
-        Files.delete(Paths.get(userdir, "multi-release.jar"));
-        Files.delete(Paths.get(userdir, "short-multi-release.jar"));
-    }
-
-    @DataProvider(name="strings")
-    public Object[][] createStrings() {
-        return new Object[][]{
-                {"runtime", MAJOR_VERSION},
-                {"-20", 8},
-                {"0", 8},
-                {"8", 8},
-                {"9", 9},
-                {Integer.toString(MAJOR_VERSION), MAJOR_VERSION},
-                {Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION},
-                {"50", MAJOR_VERSION}
-        };
-    }
-
-    @DataProvider(name="integers")
-    public Object[][] createIntegers() {
-        return new Object[][] {
-                {new Integer(-5), 8},
-                {new Integer(0), 8},
-                {new Integer(8), 8},
-                {new Integer(9), 9},
-                {new Integer(MAJOR_VERSION), MAJOR_VERSION},
-                {new Integer(MAJOR_VERSION + 1), MAJOR_VERSION},
-                {new Integer(100), MAJOR_VERSION}
-        };
-    }
-
-    @DataProvider(name="versions")
-    public Object[][] createVersions() {
-        return new Object[][] {
-                {Version.parse("8"),    8},
-                {Version.parse("9"),    9},
-                {Version.parse(Integer.toString(MAJOR_VERSION)),  MAJOR_VERSION},
-                {Version.parse(Integer.toString(MAJOR_VERSION) + 1),  MAJOR_VERSION},
-                {Version.parse("100"), MAJOR_VERSION}
-        };
-    }
-
-    // Not the best test but all I can do since ZipFileSystem and JarFileSystem
-    // are not public, so I can't use (fs instanceof ...)
-    @Test
-    public void testNewFileSystem() throws Exception {
-        Map<String,String> env = new HashMap<>();
-        // no configuration, treat multi-release jar as unversioned
-        try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
-            Assert.assertTrue(readAndCompare(fs, 8));
-        }
-        env.put("multi-release", "runtime");
-        // a configuration and jar file is multi-release
-        try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
-            Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
-        }
-        // a configuration but jar file is unversioned
-        try (FileSystem fs = FileSystems.newFileSystem(uvuri, env)) {
-            Assert.assertTrue(readAndCompare(fs, 8));
-        }
-    }
-
-    private boolean readAndCompare(FileSystem fs, int expected) throws IOException {
-        Path path = fs.getPath("version/Version.java");
-        String src = new String(Files.readAllBytes(path));
-        return src.contains("return " + expected);
-    }
-
-    @Test(dataProvider="strings")
-    public void testStrings(String value, int expected) throws Throwable {
-        stringEnv.put("multi-release", value);
-        runTest(stringEnv, expected);
-    }
-
-    @Test(dataProvider="integers")
-    public void testIntegers(Integer value, int expected) throws Throwable {
-        integerEnv.put("multi-release", value);
-        runTest(integerEnv, expected);
-    }
-
-    @Test(dataProvider="versions")
-    public void testVersions(Version value, int expected) throws Throwable {
-        versionEnv.put("multi-release", value);
-        runTest(versionEnv, expected);
-    }
-
-    @Test
-    public void testShortJar() throws Throwable {
-        integerEnv.put("multi-release", Integer.valueOf(MAJOR_VERSION));
-        runTest(smruri, integerEnv, MAJOR_VERSION);
-        integerEnv.put("multi-release", Integer.valueOf(9));
-        runTest(smruri, integerEnv, 8);
-    }
-
-    private void runTest(Map<String,?> env, int expected) throws Throwable {
-        runTest(mruri, env, expected);
-    }
-
-    private void runTest(URI uri, Map<String,?> env, int expected) throws Throwable {
-        try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
-            Path version = fs.getPath(entryName);
-            byte [] bytes = Files.readAllBytes(version);
-            Class<?> vcls = (new ByteArrayClassLoader(fs)).defineClass(className, bytes);
-            MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
-            Assert.assertEquals((int)mh.invoke(vcls.newInstance()), expected);
-        }
-    }
-
-    @Test
-    public void testIsMultiReleaseJar() throws Exception {
-        // Re-examine commented out tests as part of JDK-8176843
-        testCustomMultiReleaseValue("true", true);
-        testCustomMultiReleaseValue("true\r\nOther: value", true);
-        testCustomMultiReleaseValue("true\nOther: value", true);
-        //testCustomMultiReleaseValue("true\rOther: value", true);
-
-        testCustomMultiReleaseValue("false", false);
-        testCustomMultiReleaseValue(" true", false);
-        testCustomMultiReleaseValue("true ", false);
-        //testCustomMultiReleaseValue("true\n ", false);
-        //testCustomMultiReleaseValue("true\r ", false);
-        //testCustomMultiReleaseValue("true\n true", false);
-        //testCustomMultiReleaseValue("true\r\n true", false);
-    }
-
-    @Test
-    public void testMultiReleaseJarWithNonVersionDir() throws Exception {
-        String jfname = "multi-release-non-ver.jar";
-        Path jfpath = Paths.get(jfname);
-        URI uri = new URI("jar", jfpath.toUri().toString() , null);
-        JarBuilder jb = new JarBuilder(jfname);
-        jb.addAttribute("Multi-Release", "true");
-        jb.build();
-        Map<String,String> env = Map.of("multi-release", "runtime");
-        try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
-            Assert.assertTrue(true);
-        }
-        Files.delete(jfpath);
-    }
-
-    private static final AtomicInteger JAR_COUNT = new AtomicInteger(0);
-
-    private void testCustomMultiReleaseValue(String value, boolean expected)
-            throws Exception {
-        String fileName = "custom-mr" + JAR_COUNT.incrementAndGet() + ".jar";
-        creator.buildCustomMultiReleaseJar(fileName, value, Map.of(),
-                /*addEntries*/true);
-
-        Map<String,String> env = Map.of("multi-release", "runtime");
-        Path filePath = Paths.get(userdir, fileName);
-        String ssp = filePath.toUri().toString();
-        URI customJar = new URI("jar", ssp , null);
-        try (FileSystem fs = FileSystems.newFileSystem(customJar, env)) {
-            if (expected) {
-                Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
-            } else {
-                Assert.assertTrue(readAndCompare(fs, 8));
-            }
-        }
-        Files.delete(filePath);
-    }
-
-    private static class ByteArrayClassLoader extends ClassLoader {
-        final private FileSystem fs;
-
-        ByteArrayClassLoader(FileSystem fs) {
-            super(null);
-            this.fs = fs;
-        }
-
-        @Override
-        public Class<?> loadClass(String name) throws ClassNotFoundException {
-            try {
-                return super.loadClass(name);
-            } catch (ClassNotFoundException x) {}
-            Path cls = fs.getPath(name.replace('.', '/') + ".class");
-            try {
-                byte[] bytes = Files.readAllBytes(cls);
-                return defineClass(name, bytes);
-            } catch (IOException x) {
-                throw new ClassNotFoundException(x.getMessage());
-            }
-        }
-
-        public Class<?> defineClass(String name, byte[] bytes) throws ClassNotFoundException {
-            if (bytes == null) throw new ClassNotFoundException("No bytes for " + name);
-            return defineClass(name, bytes, 0, bytes.length);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,203 @@
+/*
+ * 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 org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.Map;
+
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8218875
+ * @summary ZIP File System tests that leverage Files.newFileSystem
+ * @modules jdk.zipfs
+ * @compile NewFileSystemTests.java
+ * @run testng NewFileSystemTests
+ * @run testng/othervm/java.security.policy=test.policy  NewFileSystemTests
+ */
+public class NewFileSystemTests {
+
+    // The Zip file system scheme
+    private static final String ZIPFS_SCHEME = "jar";
+    // Map to used for creating a ZIP archive
+    private static final Map<String, String> ZIPFS_OPTIONS = Map.of("create", "true");
+    // Primary jar file used for testing
+    private static Path jarFile;
+    // URI for jar file used for testing
+    private static URI jarURI;
+
+    /**
+     * Create the JAR file used by the tests
+     */
+    @BeforeClass
+    public void setUp() throws Exception {
+        jarFile = Utils.createJarFile("basic.jar",
+                "README");
+        jarURI = new URI(ZIPFS_SCHEME, jarFile.toUri().toString(), null);
+
+    }
+
+    /**
+     * Remove JAR file used by test as part of clean-up
+     */
+    @AfterClass
+    public void tearDown() throws Exception {
+        Files.deleteIfExists(jarFile);
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemPathMap() throws IOException {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                ZIPFS_OPTIONS)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemPath() throws IOException {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"))) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemPathClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemPathMapClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                ZIPFS_OPTIONS, cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(URI, Map<String, ?>)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemUriMap() throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(jarURI, ZIPFS_OPTIONS)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(URI, Map<String, ?>, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemURIMapClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(jarURI, ZIPFS_OPTIONS,
+                cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>)}
+     * will throw a {@code NullPointerException} when the specified {@code Map}
+     * is null
+     *
+     */
+    @Test
+    public void testNewFileSystemPathNullMap() {
+        Map<String, ?> nullMap = null;
+        assertThrows(NullPointerException.class, () ->
+                FileSystems.newFileSystem(Path.of("basic.jar"), nullMap));
+    }
+
+    /*
+     * DataProvider used to verify that a Zip file system may be returned
+     * when specifying a class loader
+     */
+    @DataProvider(name = "classLoaders")
+    private Object[][] classLoaders() {
+        return new Object[][]{
+                {null},
+                {ClassLoader.getSystemClassLoader()}
+        };
+    }
+
+    /**
+     * Validate that the given FileSystem is a Zip file system.
+     *
+     * @param fs File System to validate
+     */
+    private void checkFileSystem(FileSystem fs) {
+
+        assertNotNull(fs, "Error: FileSystem was not returned");
+        assertTrue(fs.provider().getScheme().equalsIgnoreCase(ZIPFS_SCHEME));
+        assertTrue(fs.isOpen());
+        assertEquals(fs.getSeparator(), "/");
+
+        // one root
+        Iterator<Path> roots = fs.getRootDirectories().iterator();
+        assertTrue(roots.next().toString().equals("/"));
+        assertFalse(roots.hasNext());
+    }
+}
--- a/test/jdk/jdk/nio/zipfs/PathOps.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/PathOps.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, 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
@@ -46,13 +46,11 @@
     static final java.io.PrintStream out = System.out;
     static FileSystem fs;
 
-    private String input;
     private Path path;
     private Exception exc;
 
     private PathOps(String first, String... more) {
         out.println();
-        input = first;
         try {
             path = fs.getPath(first, more);
             out.format("%s -> %s", first, path);
@@ -606,7 +604,7 @@
         // create empty JAR file, test doesn't require any contents
         Path emptyJar = Utils.createJarFile("empty.jar");
 
-        fs = FileSystems.newFileSystem(emptyJar, null);
+        fs = FileSystems.newFileSystem(emptyJar);
         try {
             npes();
             mismatchedProviders();
--- a/test/jdk/jdk/nio/zipfs/ZipFSTester.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java	Fri May 03 14:59:32 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
@@ -81,7 +81,6 @@
  */
 
 public class ZipFSTester {
-
     public static void main(String[] args) throws Exception {
         // create JAR file for test, actual contents don't matter
         Path jarFile = Utils.createJarFile("tester.jar",
@@ -146,7 +145,7 @@
             // copy the test jar itself in
             Files.copy(Paths.get(fs0.toString()), copy.getPath("/foo.jar"));
             Path zpath = copy.getPath("/foo.jar");
-            try (FileSystem zzfs = FileSystems.newFileSystem(zpath, null)) {
+            try (FileSystem zzfs = FileSystems.newFileSystem(zpath)) {
                 Files.copy(src, zzfs.getPath("/srcInjarjar"));
             }
         }
@@ -254,7 +253,7 @@
             // test foo.jar in jar/zipfs #8034802
             Path jpath = fs.getPath("/foo.jar");
             System.out.println("walking: " + jpath);
-            try (FileSystem zzfs = FileSystems.newFileSystem(jpath, null)) {
+            try (FileSystem zzfs = FileSystems.newFileSystem(jpath)) {
                 walk(zzfs.getPath("/"));
                 // foojar:/srcInjarjar
                 checkEqual(src, zzfs.getPath("/srcInjarjar"));
@@ -533,10 +532,7 @@
             try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) {
                 for (Object[] e : entries) {
                     Path path = zfs.getPath((String)e[0]);
-                    int method = (int)e[1];
                     byte[] bytes = (byte[])e[2];
-                    // System.out.printf("checking read [%s, %d, %d]%n",
-                    //                   path.toString(), bytes.length, method);
                     checkRead(path, bytes);
                 }
             }
--- a/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java	Fri May 03 14:59:32 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,15 +23,16 @@
 
 /*
  * @test
- * @bug 8164389
+ * @bug 8164389 8222440
  * @summary walk entries in a jdk.nio.zipfs.JarFileSystem
- * @modules jdk.jartool/sun.tools.jar
+ * @library /lib/testlibrary/java/util/jar
+ * @modules jdk.jartool
  *          jdk.zipfs
+ * @build Compiler JarBuilder
  * @run testng JFSTester
  */
 
 import org.testng.Assert;
-import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -50,57 +51,76 @@
 
 public class JFSTester {
     private URI jarURI;
-    private Path jarfile;
+
+    final private String root_dir1_leaf1_txt = "This is leaf 1." + System.lineSeparator();
+    final private String root_dir1_leaf2_txt = "This is leaf 2." + System.lineSeparator();
+    final private String root_dir2_leaf3_txt = "This is leaf 3." + System.lineSeparator();
+    final private String root_dir2_leaf4_txt = "This is leaf 4." + System.lineSeparator();
+    final private String v9_root_dir2_leaf3_txt = "This is version 9 leaf 3." + System.lineSeparator();
+    final private String v9_root_dir2_leaf4_txt = "This is version 9 leaf 4." + System.lineSeparator();
+    final private String v9_root_dir3_leaf5_txt = "This is version 9 leaf 5." + System.lineSeparator();
+    final private String v9_root_dir3_leaf6_txt = "This is version 9 leaf 6." + System.lineSeparator();
+    final private String v10_root_dir3_leaf5_txt = "This is version 10 leaf 5." + System.lineSeparator();
+    final private String v10_root_dir3_leaf6_txt = "This is version 10 leaf 6." + System.lineSeparator();
 
     @BeforeClass
     public void initialize() throws Exception {
-        String userdir = System.getProperty("user.dir",".");
-        jarfile = Paths.get(userdir, "test.jar");
-        String srcdir = System.getProperty("test.src");
-        String[] args = (
-                        "-cf "
-                        + jarfile.toString()
-                        + " -C "
-                        + srcdir
-                        + " root --release 9 -C "
-                        + srcdir
-                        + System.getProperty("file.separator")
-                        + "v9 root"
-        ).split(" +");
-        new sun.tools.jar.Main(System.out, System.err, "jar").run(args);
-        String ssp = jarfile.toUri().toString();
-        jarURI = new URI("jar", ssp, null);
-    }
-
-    @AfterClass
-    public void close() throws IOException {
-        Files.deleteIfExists(jarfile);
+        Path jarfile = Paths.get("test.jar");
+        JarBuilder jb = new JarBuilder(jarfile.toString());
+        jb.addAttribute("Multi-Release", "true");
+        jb.addEntry("root/dir1/leaf1.txt", root_dir1_leaf1_txt.getBytes());
+        jb.addEntry("root/dir1/leaf2.txt", root_dir1_leaf2_txt.getBytes());
+        jb.addEntry("root/dir2/leaf3.txt", root_dir2_leaf3_txt.getBytes());
+        jb.addEntry("root/dir2/leaf4.txt", root_dir2_leaf4_txt.getBytes());
+        jb.addEntry("META-INF/versions/9/root/dir2/leaf3.txt", v9_root_dir2_leaf3_txt.getBytes());
+        jb.addEntry("META-INF/versions/9/root/dir2/leaf4.txt", v9_root_dir2_leaf4_txt.getBytes());
+        jb.addEntry("META-INF/versions/9/root/dir3/leaf5.txt", v9_root_dir3_leaf5_txt.getBytes());
+        jb.addEntry("META-INF/versions/9/root/dir3/leaf6.txt", v9_root_dir3_leaf6_txt.getBytes());
+        jb.addEntry("META-INF/versions/10/root/dir3/leaf5.txt", v10_root_dir3_leaf5_txt.getBytes());
+        jb.addEntry("META-INF/versions/10/root/dir3/leaf6.txt", v10_root_dir3_leaf6_txt.getBytes());
+        jb.build();
+        System.out.println("Created " + jarfile + ": " + Files.exists(jarfile));
+        jarURI = new URI("jar", jarfile.toUri().toString(), null);
     }
 
     @Test
     public void testWalk() throws IOException {
-
-        // no configuration, treat multi-release jar as unversioned
-        Map<String,String> env = new HashMap<>();
+        // treat multi-release jar as unversioned
+        Map<String, String> env = new HashMap<>();
         Set<String> contents = doTest(env);
-        Set<String> baseContents = Set.of(
-                "This is leaf 1.\n",
-                "This is leaf 2.\n",
-                "This is leaf 3.\n",
-                "This is leaf 4.\n"
+        Set<String> expectedContents = Set.of(
+            root_dir1_leaf1_txt,
+            root_dir1_leaf2_txt,
+            root_dir2_leaf3_txt,
+            root_dir2_leaf4_txt
         );
-        Assert.assertEquals(contents, baseContents);
+        Assert.assertEquals(contents, expectedContents);
 
-        // a configuration and jar file is multi-release
+        // open file as multi-release for version 9
         env.put("multi-release", "9");
         contents = doTest(env);
-        Set<String> versionedContents = Set.of(
-                "This is versioned leaf 1.\n",
-                "This is versioned leaf 2.\n",
-                "This is versioned leaf 3.\n",
-                "This is versioned leaf 4.\n"
+        expectedContents = Set.of(
+            root_dir1_leaf1_txt,
+            root_dir1_leaf2_txt,
+            v9_root_dir2_leaf3_txt,
+            v9_root_dir2_leaf4_txt,
+            v9_root_dir3_leaf5_txt,
+            v9_root_dir3_leaf6_txt
         );
-        Assert.assertEquals(contents, versionedContents);
+        Assert.assertEquals(contents, expectedContents);
+
+        // open file as multi-release for version 10
+        env.put("multi-release", "10");
+        contents = doTest(env);
+        expectedContents = Set.of(
+            root_dir1_leaf1_txt,
+            root_dir1_leaf2_txt,
+            v9_root_dir2_leaf3_txt,
+            v9_root_dir2_leaf4_txt,
+            v10_root_dir3_leaf5_txt,
+            v10_root_dir3_leaf6_txt
+        );
+        Assert.assertEquals(contents, expectedContents);
     }
 
     private Set<String> doTest(Map<String,String> env) throws IOException {
@@ -108,9 +128,10 @@
         try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) {
             Path root = fs.getPath("root");
             contents = Files.walk(root)
-                    .filter(p -> !Files.isDirectory(p))
-                    .map(this::pathToContents)
-                    .collect(Collectors.toSet());
+                .filter(p -> !Files.isDirectory(p))
+                .map(this::pathToContents)
+                .sorted()
+                .collect(Collectors.toSet());
         }
         return contents;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/zipfs/jarfs/MultiReleaseJarTest.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,272 @@
+/*
+ * 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 8144355 8144062 8176709 8194070 8193802
+ * @summary Test aliasing additions to ZipFileSystem for multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @modules jdk.compiler
+ *          jdk.jartool
+ *          jdk.zipfs
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarTest
+ */
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.Runtime.Version;
+import java.net.URI;
+import java.nio.file.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.testng.Assert;
+import org.testng.annotations.*;
+
+public class MultiReleaseJarTest {
+    final private int MAJOR_VERSION = Runtime.version().feature();
+
+    final private String userdir = System.getProperty("user.dir",".");
+    final private CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+    final private Map<String,String> stringEnv = new HashMap<>();
+    final private Map<String,Integer> integerEnv = new HashMap<>();
+    final private Map<String,Version> versionEnv = new HashMap<>();
+    final private String className = "version.Version";
+    final private MethodType mt = MethodType.methodType(int.class);
+
+    private String entryName;
+    private URI uvuri;
+    private URI mruri;
+    private URI smruri;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        creator.compileEntries();
+        creator.buildUnversionedJar();
+        creator.buildMultiReleaseJar();
+        creator.buildShortMultiReleaseJar();
+        String ssp = Paths.get(userdir, "unversioned.jar").toUri().toString();
+        uvuri = new URI("jar", ssp , null);
+        ssp = Paths.get(userdir, "multi-release.jar").toUri().toString();
+        mruri = new URI("jar", ssp, null);
+        ssp = Paths.get(userdir, "short-multi-release.jar").toUri().toString();
+        smruri = new URI("jar", ssp, null);
+        entryName = className.replace('.', '/') + ".class";
+    }
+
+    public void close() throws IOException {
+        Files.delete(Paths.get(userdir, "unversioned.jar"));
+        Files.delete(Paths.get(userdir, "multi-release.jar"));
+        Files.delete(Paths.get(userdir, "short-multi-release.jar"));
+    }
+
+    @DataProvider(name="strings")
+    public Object[][] createStrings() {
+        return new Object[][]{
+                {"runtime", MAJOR_VERSION},
+                {"-20", 8},
+                {"0", 8},
+                {"8", 8},
+                {"9", 9},
+                {Integer.toString(MAJOR_VERSION), MAJOR_VERSION},
+                {Integer.toString(MAJOR_VERSION+1), MAJOR_VERSION},
+                {"50", MAJOR_VERSION}
+        };
+    }
+
+    @DataProvider(name="integers")
+    public Object[][] createIntegers() {
+        return new Object[][] {
+                {Integer.valueOf(-5), 8},
+                {Integer.valueOf(0), 8},
+                {Integer.valueOf(8), 8},
+                {Integer.valueOf(9), 9},
+                {Integer.valueOf(MAJOR_VERSION), MAJOR_VERSION},
+                {Integer.valueOf(MAJOR_VERSION + 1), MAJOR_VERSION},
+                {Integer.valueOf(100), MAJOR_VERSION}
+        };
+    }
+
+    @DataProvider(name="versions")
+    public Object[][] createVersions() {
+        return new Object[][] {
+                {Version.parse("8"),    8},
+                {Version.parse("9"),    9},
+                {Version.parse(Integer.toString(MAJOR_VERSION)),  MAJOR_VERSION},
+                {Version.parse(Integer.toString(MAJOR_VERSION) + 1),  MAJOR_VERSION},
+                {Version.parse("100"), MAJOR_VERSION}
+        };
+    }
+
+    // Not the best test but all I can do since ZipFileSystem and JarFileSystem
+    // are not public, so I can't use (fs instanceof ...)
+    @Test
+    public void testNewFileSystem() throws Exception {
+        Map<String,String> env = new HashMap<>();
+        // no configuration, treat multi-release jar as unversioned
+        try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
+            Assert.assertTrue(readAndCompare(fs, 8));
+        }
+        env.put("multi-release", "runtime");
+        // a configuration and jar file is multi-release
+        try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
+            Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
+        }
+        // a configuration but jar file is unversioned
+        try (FileSystem fs = FileSystems.newFileSystem(uvuri, env)) {
+            Assert.assertTrue(readAndCompare(fs, 8));
+        }
+    }
+
+    private boolean readAndCompare(FileSystem fs, int expected) throws IOException {
+        Path path = fs.getPath("version/Version.java");
+        String src = new String(Files.readAllBytes(path));
+        return src.contains("return " + expected);
+    }
+
+    @Test(dataProvider="strings")
+    public void testStrings(String value, int expected) throws Throwable {
+        stringEnv.put("multi-release", value);
+        runTest(stringEnv, expected);
+    }
+
+    @Test(dataProvider="integers")
+    public void testIntegers(Integer value, int expected) throws Throwable {
+        integerEnv.put("multi-release", value);
+        runTest(integerEnv, expected);
+    }
+
+    @Test(dataProvider="versions")
+    public void testVersions(Version value, int expected) throws Throwable {
+        versionEnv.put("multi-release", value);
+        runTest(versionEnv, expected);
+    }
+
+    @Test
+    public void testShortJar() throws Throwable {
+        integerEnv.put("multi-release", Integer.valueOf(MAJOR_VERSION));
+        runTest(smruri, integerEnv, MAJOR_VERSION);
+        integerEnv.put("multi-release", Integer.valueOf(9));
+        runTest(smruri, integerEnv, 8);
+    }
+
+    private void runTest(Map<String,?> env, int expected) throws Throwable {
+        runTest(mruri, env, expected);
+    }
+
+    private void runTest(URI uri, Map<String,?> env, int expected) throws Throwable {
+        try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
+            Path version = fs.getPath(entryName);
+            byte [] bytes = Files.readAllBytes(version);
+            Class<?> vcls = (new ByteArrayClassLoader(fs)).defineClass(className, bytes);
+            MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+            Assert.assertEquals((int)mh.invoke(vcls.getDeclaredConstructor().newInstance()), expected);
+        }
+    }
+
+    @Test
+    public void testIsMultiReleaseJar() throws Exception {
+        // Re-examine commented out tests as part of JDK-8176843
+        testCustomMultiReleaseValue("true", true);
+        testCustomMultiReleaseValue("true\r\nOther: value", true);
+        testCustomMultiReleaseValue("true\nOther: value", true);
+        //testCustomMultiReleaseValue("true\rOther: value", true);
+
+        testCustomMultiReleaseValue("false", false);
+        testCustomMultiReleaseValue(" true", false);
+        testCustomMultiReleaseValue("true ", false);
+        //testCustomMultiReleaseValue("true\n ", false);
+        //testCustomMultiReleaseValue("true\r ", false);
+        //testCustomMultiReleaseValue("true\n true", false);
+        //testCustomMultiReleaseValue("true\r\n true", false);
+    }
+
+    @Test
+    public void testMultiReleaseJarWithNonVersionDir() throws Exception {
+        String jfname = "multi-release-non-ver.jar";
+        Path jfpath = Paths.get(jfname);
+        URI uri = new URI("jar", jfpath.toUri().toString() , null);
+        JarBuilder jb = new JarBuilder(jfname);
+        jb.addAttribute("Multi-Release", "true");
+        jb.build();
+        Map<String,String> env = Map.of("multi-release", "runtime");
+        try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
+            Assert.assertTrue(true);
+        }
+        Files.delete(jfpath);
+    }
+
+    private static final AtomicInteger JAR_COUNT = new AtomicInteger(0);
+
+    private void testCustomMultiReleaseValue(String value, boolean expected)
+            throws Exception {
+        String fileName = "custom-mr" + JAR_COUNT.incrementAndGet() + ".jar";
+        creator.buildCustomMultiReleaseJar(fileName, value, Map.of(),
+                /*addEntries*/true);
+
+        Map<String,String> env = Map.of("multi-release", "runtime");
+        Path filePath = Paths.get(userdir, fileName);
+        String ssp = filePath.toUri().toString();
+        URI customJar = new URI("jar", ssp , null);
+        try (FileSystem fs = FileSystems.newFileSystem(customJar, env)) {
+            if (expected) {
+                Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION));
+            } else {
+                Assert.assertTrue(readAndCompare(fs, 8));
+            }
+        }
+        Files.delete(filePath);
+    }
+
+    private static class ByteArrayClassLoader extends ClassLoader {
+        final private FileSystem fs;
+
+        ByteArrayClassLoader(FileSystem fs) {
+            super(null);
+            this.fs = fs;
+        }
+
+        @Override
+        public Class<?> loadClass(String name) throws ClassNotFoundException {
+            try {
+                return super.loadClass(name);
+            } catch (ClassNotFoundException x) {}
+            Path cls = fs.getPath(name.replace('.', '/') + ".class");
+            try {
+                byte[] bytes = Files.readAllBytes(cls);
+                return defineClass(name, bytes);
+            } catch (IOException x) {
+                throw new ClassNotFoundException(x.getMessage());
+            }
+        }
+
+        public Class<?> defineClass(String name, byte[] bytes) throws ClassNotFoundException {
+            if (bytes == null) throw new ClassNotFoundException("No bytes for " + name);
+            return defineClass(name, bytes, 0, bytes.length);
+        }
+    }
+}
--- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is leaf 1.
--- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is leaf 2.
--- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is leaf 3.
--- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is leaf 4.
--- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is versioned leaf 1.
--- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is versioned leaf 2.
--- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is versioned leaf 3.
--- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is versioned leaf 4.
--- a/test/jdk/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java	Fri May 03 14:59:32 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
@@ -69,7 +69,7 @@
             + "        return 9;\n"
             + "    }\n"
             + "}\n";
-    final int currentVersion = Runtime.version().major();
+    final int currentVersion = Runtime.version().feature();
     final String currentVersionStr = Integer.toString(currentVersion);
     final private String javaCurrent = java8.replace("8", currentVersionStr);
     final String readme8 = "This is the root readme file";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,202 @@
+/*
+ * 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 8216577
+ * @summary Interoperability tests with GlobalSign R6 CA
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath GlobalSignR6CA OCSP
+ * @run main/othervm -Djava.security.debug=certpath GlobalSignR6CA CRL
+ */
+
+ /*
+ *
+ * Obtain TLS test artifacts for GlobalSign R6 CA from:
+ *
+ * Valid TLS Certificates:
+ * https://valid.r6.roots.globalsign.com/
+ *
+ * Revoked TLS Certificates:
+ * https://revoked.r6.roots.globalsign.com/
+ */
+public class GlobalSignR6CA {
+
+    // Owner: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+    // Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R6
+    // Serial number: 48a402ddb5defd50accfc0fcf13f
+    // Valid from: Tue Sep 20 17:00:00 PDT 2016 until: Mon Sep 20 17:00:00 PDT 2021
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIFmjCCA4KgAwIBAgIOSKQC3bXe/VCsz8D88T8wDQYJKoZIhvcNAQELBQAwTDEg\n" +
+            "MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh\n" +
+            "bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTYwOTIxMDAwMDAwWhcNMjEw\n" +
+            "OTIxMDAwMDAwWjBXMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBu\n" +
+            "di1zYTEtMCsGA1UEAxMkR2xvYmFsU2lnbiBSNiBBZG1pbiBDQSAtIFNIQTI1NiAt\n" +
+            "IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmyyfJA4reymawDG1\n" +
+            "FNDCSFBqst/+Jih2Zg1ThovSfkxVWcviBhIZfu0t/Hv9hmolN2dxPibKCHhjyfMp\n" +
+            "WaGj+S8VPPaR3xoeOvHtuf/2uOyBZa/3mgiWWRF50fLy0fzyWNJL9lbTH459oUci\n" +
+            "QN2H0nFEuD1tGGzFdjtXCRVjWy9dZW8Vv2831buzuPLTtOPSKhqOiigpXFTo6SL9\n" +
+            "n/NHQ4HI7WV+DMB7yOPEERqQzfi28v1B2j4GOT4wqXncbw5uFZdYobBfRNv3VNdk\n" +
+            "p/2Frtm15ePBIAAb4o28du+orJUuVVpxreeEyVBGJuaP0RWksjSnqkSbPm9MEY0k\n" +
+            "dS7tgwIDAQABo4IBbTCCAWkwDgYDVR0PAQH/BAQDAgEGMCcGA1UdJQQgMB4GCCsG\n" +
+            "AQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwkwEgYDVR0TAQH/BAgwBgEB/wIBADAd\n" +
+            "BgNVHQ4EFgQUgUlc6QW/DIigOJayXUEDWun/14cwHwYDVR0jBBgwFoAUrmwFo5MT\n" +
+            "4qLn4tcc1sfwf8hnU6AwPgYIKwYBBQUHAQEEMjAwMC4GCCsGAQUFBzABhiJodHRw\n" +
+            "Oi8vb2NzcDIuZ2xvYmFsc2lnbi5jb20vcm9vdHI2MDYGA1UdHwQvMC0wK6ApoCeG\n" +
+            "JWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yNi5jcmwwYgYDVR0gBFsw\n" +
+            "WTAHBgVngQwBATALBgkrBgEEAaAyAQEwQQYJKwYBBAGgMgFfMDQwMgYIKwYBBQUH\n" +
+            "AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqG\n" +
+            "SIb3DQEBCwUAA4ICAQBovPHk0rWZ5tGQ3NiYORqZNfSh2KH0RxweRE+ZTpnGOZjE\n" +
+            "vRQYLYm/vf2q+v2IcESmpVCjq1eN0k75wc/4475Y9RH6xK7ai1+O8HHDgj8GK4iZ\n" +
+            "0ILbKtJQ2/ih19TMO7M3Y/tZByLPcdy8cuDMoCWoQJqUFtM8l784S5lEjefrcwkZ\n" +
+            "uNOdTrZbsqXY71Xfa61DNuW3lIt/w34myrKG0xRyGicI9P9VpcWYdWCKpwVe10MP\n" +
+            "d4WQ/lclJZLrLljmn76bc+q/L2Sw+tpadsD2qP3l05FhRqcF5iI9lIw77KIU15Jt\n" +
+            "QysmI7xTjByjny/OiIYP/7PKQjh+KEe/17GOg0AamdI9dbaOHRcyHFht01ymaphf\n" +
+            "kU3hjWb2bdtVLuDsIKfGN/QDXSmv0ThKsgkj3OOiLUpllApr5SU2tY40rpZ210iD\n" +
+            "/jA18LYwBmR64t3e7ud/tDz4c/YLY8p6vPLdASbbwyptj93n0c0HXpjdcrx/XOQa\n" +
+            "ogw6JzJ2v3Kok94frBKKdoxg4SnMvZoakM1SbY6Q3XlC24qVnVuWJ142rVkCFixZ\n" +
+            "Sb5ZEB7fxk/2YfaWkSW3uejwh2qN7qXji0S1ALNbASJATYqMgdJVz+25yOBfxFN6\n" +
+            "KzNbvmVmEM/hnKaQxePhwForQjDFaep1RO5Yg4wnIcLRC3atKgkIIA6YDNUcog==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=valid.r6.roots.globalsign.com, O=GMO GlobalSign Inc., STREET="Two International Drive, Suite 150",
+    // L=Portsmouth, ST=New Hampshire, C=US, OID.1.3.6.1.4.1.311.60.2.1.2=New Hampshire, OID.1.3.6.1.4.1.311.60.2.1.3=US,
+    // SERIALNUMBER=578611, OID.2.5.4.15=Private Organization
+    // Issuer: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+    // Serial number: 1355071ec648a599cea67b3b
+    // Valid from: Wed Jun 13 21:31:05 PDT 2018 until: Sat Jun 13 21:31:05 PDT 2020
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIHUjCCBjqgAwIBAgIME1UHHsZIpZnOpns7MA0GCSqGSIb3DQEBCwUAMFcxCzAJ\n" +
+            "BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRH\n" +
+            "bG9iYWxTaWduIFI2IEFkbWluIENBIC0gU0hBMjU2IC0gRzMwHhcNMTgwNjE0MDQz\n" +
+            "MTA1WhcNMjAwNjE0MDQzMTA1WjCCARIxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5p\n" +
+            "emF0aW9uMQ8wDQYDVQQFEwY1Nzg2MTExEzARBgsrBgEEAYI3PAIBAxMCVVMxHjAc\n" +
+            "BgsrBgEEAYI3PAIBAhMNTmV3IEhhbXBzaGlyZTELMAkGA1UEBhMCVVMxFjAUBgNV\n" +
+            "BAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxKzApBgNVBAkT\n" +
+            "IlR3byBJbnRlcm5hdGlvbmFsIERyaXZlLCBTdWl0ZSAxNTAxHDAaBgNVBAoTE0dN\n" +
+            "TyBHbG9iYWxTaWduIEluYy4xJjAkBgNVBAMTHXZhbGlkLnI2LnJvb3RzLmdsb2Jh\n" +
+            "bHNpZ24uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArh1lHcNS\n" +
+            "cfvFI/vGrfu3sC561NL6VTm9WQpq0UcdQpVlOjnmlScZaUhTlcJ2aWz4tqNnT/SF\n" +
+            "EO48kgIy0c07n0z1igBGOvM6shPtdIT3Yik2KwKdnt2Oaw/RqyXQxZhMvvGGyXLP\n" +
+            "hEyRdUrcNEXzOh+/AFzV2Ayo2OfZB/SEJW2BMhYEvZ89ziniab7vaNfVVUwsR6yD\n" +
+            "JX/3bdgRpG3gvKpdawAXMkhX5yAJaLInp5gHfCKNsW7l5gSrW/IYmPZvmEovLLmF\n" +
+            "lJfEDltnaNrO3jFzCjzEVRsurBrn1lMgKuCCkCZhzUgy5w8fR7OiGDpI/DmprRxn\n" +
+            "WQomtZBRd9VG1wIDAQABo4IDXzCCA1swDgYDVR0PAQH/BAQDAgWgMIGWBggrBgEF\n" +
+            "BQcBAQSBiTCBhjBHBggrBgEFBQcwAoY7aHR0cDovL3NlY3VyZS5nbG9iYWxzaWdu\n" +
+            "LmNvbS9jYWNlcnQvZ3NyNmFkbWluY2FzaGEyNTZnMy5jcnQwOwYIKwYBBQUHMAGG\n" +
+            "L2h0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9nc3I2YWRtaW5jYXNoYTI1Nmcz\n" +
+            "MFUGA1UdIAROMEwwQQYJKwYBBAGgMgEBMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v\n" +
+            "d3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAcGBWeBDAEBMAkGA1UdEwQC\n" +
+            "MAAwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9n\n" +
+            "c3I2YWRtaW5jYXNoYTI1NmczLmNybDAoBgNVHREEITAfgh12YWxpZC5yNi5yb290\n" +
+            "cy5nbG9iYWxzaWduLmNvbTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n" +
+            "HQYDVR0OBBYEFPTkCvZs787YEtziawL5ju/rC8XwMB8GA1UdIwQYMBaAFIFJXOkF\n" +
+            "vwyIoDiWsl1BA1rp/9eHMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdwBVgdTC\n" +
+            "FpA2AUrqC5tXPFPwwOQ4eHAlCBcvo6odBxPTDAAAAWP8j7bvAAAEAwBIMEYCIQDH\n" +
+            "FRH+VkQ4RgVRYaO47rC83fQrzEO9Pb45BD5ZEHfrRwIhALY75BbrPhtAZSXWfpVN\n" +
+            "MoDQzA6X0DQFSf29dlnCMYCmAHcApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fN\n" +
+            "DsgN3BAAAAFj/I+4QgAABAMASDBGAiEA3kcOlf4Az7R+/MkV5GurWnpUmIhCUB3v\n" +
+            "a/tNz+Dd8HgCIQC22RG+EW4OYdaoWN/B3MeI95OlNofD/OqJB/med+quWwB1AG9T\n" +
+            "dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABY/yPt6kAAAQDAEYwRAIg\n" +
+            "THH7eeWpo5vDtjDNKzpkkrR/McYDgmQIRRnLKXkKMsoCIC9cY4xj9LlXPVRF9bLH\n" +
+            "1DvP9qmONga9pO7kxuyYtd8YMA0GCSqGSIb3DQEBCwUAA4IBAQA0Ufq4QDCiWxm4\n" +
+            "5D3MrfbQnC9apSMpzRT2udD/gFDbtqTJ7Rx4CJjNWa9ANkKWNlJ6zVASpVzV7KB7\n" +
+            "otvqO4iR5V0EE4+9fitJ3zRe9nl76uDf2upCHLcWsYurq/eIxIuXnIByLJvTS3jS\n" +
+            "42i07D6JsgNg9SR8rIKyYiz4KX2975GlMSue/SOMFcf/AC7amYzs6U+FA68y8GBV\n" +
+            "yDGpYvQW9zfnQ2Z/XVcLE1tVERrEs3Ba08g+uk1dICyibSz83yrX3Eas/bq6kZEy\n" +
+            "kRvhD1fnk3wAlgiuUED65Rn3ezm2AjsFJBIitdDyHFzgZiu/DKccakuuk8NwDZjJ\n" +
+            "NrTZIL32\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=revoked.r6.roots.globalsign.com, O=GMO GlobalSign Inc., STREET="Two International Drive, Suite 150",
+    // L=Portsmouth, ST=New Hampshire, C=US, OID.1.3.6.1.4.1.311.60.2.1.2=New Hampshire, OID.1.3.6.1.4.1.311.60.2.1.3=US,
+    // SERIALNUMBER=578611, OID.2.5.4.15=Private Organization
+    // Issuer: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+    // Serial number: 535589c9d767cf1cd892f1dc
+    // Valid from: Wed Jun 13 21:36:04 PDT 2018 until: Sat Jun 13 21:36:04 PDT 2020
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIHVTCCBj2gAwIBAgIMU1WJyddnzxzYkvHcMA0GCSqGSIb3DQEBCwUAMFcxCzAJ\n" +
+            "BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRH\n" +
+            "bG9iYWxTaWduIFI2IEFkbWluIENBIC0gU0hBMjU2IC0gRzMwHhcNMTgwNjE0MDQz\n" +
+            "NjA0WhcNMjAwNjE0MDQzNjA0WjCCARQxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5p\n" +
+            "emF0aW9uMQ8wDQYDVQQFEwY1Nzg2MTExEzARBgsrBgEEAYI3PAIBAxMCVVMxHjAc\n" +
+            "BgsrBgEEAYI3PAIBAhMNTmV3IEhhbXBzaGlyZTELMAkGA1UEBhMCVVMxFjAUBgNV\n" +
+            "BAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxKzApBgNVBAkT\n" +
+            "IlR3byBJbnRlcm5hdGlvbmFsIERyaXZlLCBTdWl0ZSAxNTAxHDAaBgNVBAoTE0dN\n" +
+            "TyBHbG9iYWxTaWduIEluYy4xKDAmBgNVBAMTH3Jldm9rZWQucjYucm9vdHMuZ2xv\n" +
+            "YmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6SJ+O\n" +
+            "PX5/ECfblZpVByiogO5sUCS23Sry3Ucn1fxFO3b6tOKppUtgZjJUxUOHj9jRIsmS\n" +
+            "8Tvbn+Iu35Cjj2vTsJNoFzxiMj/FBl3IqfF7w4ghLNZ+wE91cMwG0LUtDeAKTlJa\n" +
+            "j4Q2Gj1ZOGLPyr4flSig2bOvcIBWYjbXqwBMZek9EC58D34HF+h2fdzXPrqHHWqg\n" +
+            "NQpj7lxkr4XA1jXSgZJZnRfoVW+BCVidbNw9LEteF+WGcg3P9sd8XUWJtG/pb4w1\n" +
+            "GsCMf/ig8gkrsQvrMYPsYgQJMdypXm9eAqZmVcE94E0Uz1dbJL9zCa8y4ue9yDnp\n" +
+            "+gzXxToJvNzrlmUPAgMBAAGjggNgMIIDXDAOBgNVHQ8BAf8EBAMCBaAwgZYGCCsG\n" +
+            "AQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\n" +
+            "Z24uY29tL2NhY2VydC9nc3I2YWRtaW5jYXNoYTI1NmczLmNydDA7BggrBgEFBQcw\n" +
+            "AYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzcjZhZG1pbmNhc2hhMjU2\n" +
+            "ZzMwVQYDVR0gBE4wTDBBBgkrBgEEAaAyAQEwNDAyBggrBgEFBQcCARYmaHR0cHM6\n" +
+            "Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wBwYFZ4EMAQEwCQYDVR0T\n" +
+            "BAIwADBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29t\n" +
+            "L2dzcjZhZG1pbmNhc2hhMjU2ZzMuY3JsMCoGA1UdEQQjMCGCH3Jldm9rZWQucjYu\n" +
+            "cm9vdHMuZ2xvYmFsc2lnbi5jb20wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n" +
+            "BwMCMB0GA1UdDgQWBBR66TcwHJ5KRJZqtNB3Cqj8rWUAYzAfBgNVHSMEGDAWgBSB\n" +
+            "SVzpBb8MiKA4lrJdQQNa6f/XhzCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA\n" +
+            "VYHUwhaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAFj/JRH/gAABAMARzBF\n" +
+            "AiBtxn2bgwXrjx2zX3RPP3L4iFEZ1bK71oZ67RvNpI/pWQIhAK1Wg3wEdSqUUa9I\n" +
+            "VKSNaDaMqtI7s5yQvIV3YdDDxl+hAHcAu9nfvB+KcbWTlCOXqpJ7RzhXlQqrUuga\n" +
+            "kJZkNo4e0YUAAAFj/JRJMQAABAMASDBGAiEAkwpftFhujb0p9wNDywVgZPPxGdLy\n" +
+            "7c7WnpBLkViuvVgCIQCtWUK5pfYn+FWPKX82XmG0Hw1VgeQRPZZNAy0HQu/V0QB1\n" +
+            "AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABY/yUSPUAAAQDAEYw\n" +
+            "RAIgEN2Y70rpA+zoK1C5bKEOYUDy6Km5pgymDEPcMBgmh5ECIEAWEPdNA9FeCwqW\n" +
+            "S1Mi3uOhB4dmJKNbToFWtL2lBeDrMA0GCSqGSIb3DQEBCwUAA4IBAQCDoIyqZlvt\n" +
+            "YeqjVCR2rvb1ZHyB5UI5rfYuoNstjaxLKP2tIDByeGwllT0vSb2otM6XjXGVuTTO\n" +
+            "sbVUf4aQQb82pkKXYtB6L7cfPkqrnZXJrmPYb+3xzAsr+HXyyPOu0FIVrtB/WTvd\n" +
+            "Qo/JyVMm7Duke/e5gudw9Lv6sb2P5B3BVcNzbv1f7589wydNvrTgdVeldyPNfuZ4\n" +
+            "gMT/ICoNaX+U6O3EiqYB+gLDBKVAIDsQV1k/fYq5uZr1FsTzOMesaCT4me/4I4tR\n" +
+            "2H7WrVajYEJ73gWUclDLxy7hoDNwR/ZuLcilAaqdwIdmVD0aFiw8RFsyZkXO5J0R\n" +
+            "BuecWspICLIw\n" +
+            "-----END CERTIFICATE-----";
+
+    public static void main(String[] args) throws Exception {
+
+        ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+        if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+            pathValidator.enableCRLCheck();
+        } else {
+            // OCSP check by default
+            pathValidator.enableOCSPCheck();
+        }
+
+        // Validate valid
+        pathValidator.validate(new String[]{VALID, INT},
+                ValidatePathWithParams.Status.GOOD, null, System.out);
+
+        // Validate Revoked
+        pathValidator.validate(new String[]{REVOKED, INT},
+                ValidatePathWithParams.Status.REVOKED,
+                "Wed Jun 13 23:36:02 PDT 2018", System.out);
+
+    }
+}
+
--- a/test/jdk/sun/net/ftp/TestFtpClientNameListWithNull.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/ftp/TestFtpClientNameListWithNull.java	Fri May 03 14:59:32 2019 -0400
@@ -37,6 +37,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
@@ -52,7 +53,8 @@
              FtpClient client = FtpClient.create()) {
             (new Thread(server)).start();
             int port = server.getPort();
-            client.connect(new InetSocketAddress("localhost", port));
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            client.connect(new InetSocketAddress(loopback, port));
             client.nameList(null);
         } finally {
             if (commandHasArgs) {
@@ -66,7 +68,9 @@
         private final ServerSocket serverSocket;
 
         FtpServer() throws IOException {
-            serverSocket = new ServerSocket(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            serverSocket = new ServerSocket();
+            serverSocket.bind(new InetSocketAddress(loopback, 0));
         }
 
         public void handleClient(Socket client) throws IOException {
--- a/test/jdk/sun/net/www/http/HttpClient/ProxyTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/http/HttpClient/ProxyTest.java	Fri May 03 14:59:32 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
@@ -126,7 +126,9 @@
         }
 
         public HttpProxyServer() throws IOException {
-            server = new ServerSocket(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            server = new ServerSocket();
+            server.bind(new InetSocketAddress(loopback, 0));
         }
 
         public int getPort() {
@@ -183,7 +185,8 @@
             server.start();
             int port = server.getPort();
 
-            Proxy ftpProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", port));
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            Proxy ftpProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(loopback, port));
             URL url = new URL(testURL);
             InputStream ins = (url.openConnection(ftpProxy)).getInputStream();
             in = new BufferedReader(new InputStreamReader(ins));
--- a/test/jdk/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, 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
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.Authenticator;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.PasswordAuthentication;
 import java.net.URL;
@@ -62,8 +63,8 @@
             // set authenticator
             Authenticator.setDefault(new AuthenticatorImpl());
 
-            String url = String.format("http://localhost:%d/test/",
-                    server.getPort());
+            String url = String.format("http://%s/test/",
+                    server.getAuthority());
 
             // load a document which is protected with NTML authentication
             System.out.println("load() called: " + url);
@@ -107,8 +108,9 @@
         }
 
         static LocalHttpServer startServer() throws IOException {
+            InetAddress loopback = InetAddress.getLoopbackAddress();
             HttpServer httpServer = HttpServer.create(
-                    new InetSocketAddress(0), 0);
+                    new InetSocketAddress(loopback, 0), 0);
             LocalHttpServer localHttpServer = new LocalHttpServer(httpServer);
             localHttpServer.start();
 
@@ -126,6 +128,14 @@
             System.out.println("HttpServer: stopped");
         }
 
+        String getAuthority() {
+            InetAddress address = server.getAddress().getAddress();
+            String hostaddr = address.isAnyLocalAddress()
+                   ? "localhost" : address.getHostAddress();
+            if (hostaddr.indexOf(':') > -1) hostaddr = "[" + hostaddr + "]";
+            return hostaddr + ":" + getPort();
+        }
+
         int getPort() {
             return server.getAddress().getPort();
         }
--- a/test/jdk/sun/net/www/http/HttpURLConnection/PostOnDelete.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/http/HttpURLConnection/PostOnDelete.java	Fri May 03 14:59:32 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
@@ -49,7 +49,7 @@
         try {
             s = new Server();
             s.startServer();
-            URL url = new URL("http://localhost:" + s.getPort());
+            URL url = new URL("http://" + s.getAuthority());
             HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
             urlConnection.setRequestMethod("DELETE");
             urlConnection.setDoOutput(true);
@@ -70,7 +70,8 @@
         HttpServer server;
 
         public void startServer() {
-            InetSocketAddress addr = new InetSocketAddress(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            InetSocketAddress addr = new InetSocketAddress(loopback,0);
             try {
                 server = HttpServer.create(addr, 0);
             } catch (IOException ioe) {
@@ -81,6 +82,13 @@
             server.start();
         }
 
+        public String getAuthority() {
+            InetAddress address = server.getAddress().getAddress();
+            String hostaddr = address.isAnyLocalAddress() ? "localhost" : address.getHostAddress();
+            hostaddr =  (hostaddr.indexOf(':') >= 0) ? ("[" + hostaddr + "]") : hostaddr;
+            return hostaddr + ":" + getPort();
+        }
+
         public int getPort() {
             return server.getAddress().getPort();
         }
--- a/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamClose.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamClose.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, 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,11 +25,13 @@
  * @test
  * @bug 4392195
  * @summary Infinite loop in sun.net.www.http.KeepAliveStream [due to skip()]
+ * @library /test/lib
  * @run main/othervm/timeout=30 KeepAliveStreamClose
  */
 
 import java.net.*;
 import java.io.*;
+import jdk.test.lib.net.URIBuilder;
 
 public class KeepAliveStreamClose {
     static class XServer extends Thread {
@@ -78,11 +80,16 @@
 
     public static void main (String[] args) {
         try {
-            ServerSocket serversocket = new ServerSocket (0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            ServerSocket serversocket = new ServerSocket (0, 50, loopback);
             int port = serversocket.getLocalPort ();
             XServer server = new XServer (serversocket);
             server.start ();
-            URL url = new URL ("http://localhost:"+port);
+            URL url = URIBuilder.newBuilder()
+                .scheme("http")
+                .loopback()
+                .port(port)
+                .toURL();
             URLConnection urlc = url.openConnection ();
             InputStream is = urlc.getInputStream ();
             int i=0, c;
--- a/test/jdk/sun/net/www/httptest/TestHttpServer.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/httptest/TestHttpServer.java	Fri May 03 14:59:32 2019 -0400
@@ -69,6 +69,22 @@
     }
 
     /**
+     * Create a <code>TestHttpServer<code> instance with the specified callback object
+     * for handling requests. One thread is created to handle requests,
+     * and up to ten TCP connections will be handled simultaneously.
+     * @param cb the callback object which is invoked to handle each
+     *  incoming request
+     * @param address the address to bind the server to. <code>Null</code>
+     *  means bind to the wildcard address.
+     * @param port the port number to bind the server to. <code>Zero</code>
+     *  means choose any free port.
+     */
+
+    public TestHttpServer (HttpCallback cb, InetAddress address, int port) throws IOException {
+        this (cb, 1, 10, address, 0);
+    }
+
+    /**
      * Create a <code>TestHttpServer<code> instance with the specified number of
      * threads and maximum number of connections per thread. This functions
      * the same as the 4 arg constructor, where the port argument is set to zero.
@@ -102,9 +118,33 @@
      */
 
     public TestHttpServer (HttpCallback cb, int threads, int cperthread, int port)
+            throws IOException {
+        this(cb, threads, cperthread, null, port);
+    }
+
+    /**
+     * Create a <code>TestHttpServer<code> instance with the specified number
+     * of threads and maximum number of connections per thread and running on
+     * the specified port. The specified number of threads are created to
+     * handle incoming requests, and each thread is allowed
+     * to handle a number of simultaneous TCP connections.
+     * @param cb the callback object which is invoked to handle
+     *  each incoming request
+     * @param threads the number of threads to create to handle
+     *  requests in parallel
+     * @param cperthread the number of simultaneous TCP connections
+     *  to handle per thread
+     * @param address the address to bind the server to. <code>Null</code>
+     *  means bind to the wildcard address.
+     * @param port the port number to bind the server to. <code>Zero</code>
+     *  means choose any free port.
+     */
+
+    public TestHttpServer (HttpCallback cb, int threads, int cperthread,
+                           InetAddress address, int port)
         throws IOException {
         schan = ServerSocketChannel.open ();
-        InetSocketAddress addr = new InetSocketAddress (port);
+        InetSocketAddress addr = new InetSocketAddress (address, port);
         schan.socket().bind (addr);
         this.threads = threads;
         this.cb = cb;
@@ -147,6 +187,14 @@
         return schan.socket().getLocalPort ();
     }
 
+    public String getAuthority() {
+        InetAddress address = schan.socket().getInetAddress();
+        String hostaddr = address.getHostAddress();
+        if (address.isAnyLocalAddress()) hostaddr = "localhost";
+        if (hostaddr.indexOf(':') > -1) hostaddr = "[" + hostaddr + "]";
+        return hostaddr + ":" + getLocalPort();
+    }
+
     static class Server extends Thread {
 
         ServerSocketChannel schan;
@@ -746,4 +794,3 @@
         }
     }
 }
-
--- a/test/jdk/sun/net/www/protocol/http/B8012625.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/protocol/http/B8012625.java	Fri May 03 14:59:32 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
@@ -82,7 +82,8 @@
     ExecutorService ex;
 
     public B8012625 () throws Exception {
-        server = HttpServer.create(new InetSocketAddress(0), 10);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        server = HttpServer.create(new InetSocketAddress(loopback, 0), 10);
         HttpContext ctx = server.createContext("/", this);
         ex = Executors.newFixedThreadPool(5);
         server.setExecutor(ex);
--- a/test/jdk/sun/net/www/protocol/http/Finalizer.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/protocol/http/Finalizer.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, 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
@@ -80,8 +80,11 @@
 
 public class Finalizer {
     public static void main (String args[]) {
+        ServerSocket serversocket = null;
         try {
-            ServerSocket serversocket = new ServerSocket (0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            serversocket = new ServerSocket();
+            serversocket.bind(new InetSocketAddress(loopback, 0));
             int port = serversocket.getLocalPort ();
             XServer server = new XServer (serversocket);
             server.start ();
@@ -107,6 +110,10 @@
         } catch (IOException e) {
             throw new RuntimeException("finalize method failure."+e);
         } catch (InterruptedException ie) {
+        } finally {
+            if (serversocket != null) {
+                try {serversocket.close();} catch (IOException io) {}
+            }
         }
     }
 
--- a/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, 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
@@ -99,8 +99,9 @@
     public static void main(String[] args) throws Exception {
         MyResponseCache cache = new MyResponseCache();
         try {
+            InetAddress loopback = InetAddress.getLoopbackAddress();
             ResponseCache.setDefault(cache);
-            server = new TestHttpServer (new ResponseCacheStream());
+            server = new TestHttpServer (new ResponseCacheStream(), loopback, 0);
             System.out.println ("Server: listening on port: " + server.getLocalPort());
             URL url = URIBuilder.newBuilder()
                 .scheme("http")
--- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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,6 +24,7 @@
 /* @test
  * @bug 4696506 4942650
  * @summary Unit test for java.net.CookieHandler
+ * @library /test/lib
  * @run main/othervm CookieHandlerTest
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
@@ -35,6 +36,7 @@
 import java.util.*;
 import java.io.*;
 import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
 
 public class CookieHandlerTest {
     static Map<String,String> cookies;
@@ -78,10 +80,12 @@
      * to avoid infinite hangs.
      */
     void doServerSide() throws Exception {
+        InetAddress loopback = InetAddress.getLoopbackAddress();
         SSLServerSocketFactory sslssf =
             (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
         SSLServerSocket sslServerSocket =
-            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+            (SSLServerSocket) sslssf.createServerSocket();
+        sslServerSocket.bind(new InetSocketAddress(loopback, serverPort));
         serverPort = sslServerSocket.getLocalPort();
 
         /*
@@ -151,8 +155,11 @@
         }
         HttpsURLConnection http = null;
         /* establish http connection to server */
-        String uri = "https://localhost:" + +serverPort ;
-        URL url = new URL(uri);
+        URL url = URIBuilder.newBuilder()
+                  .scheme("https")
+                  .loopback()
+                  .port(serverPort)
+                  .toURL();
         HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
         http = (HttpsURLConnection)url.openConnection();
 
--- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	Fri May 03 14:59:32 2019 -0400
@@ -25,7 +25,7 @@
 /**
  * @test
  * @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
- *      8209452 8209506 8210432 8195793 8222089 8222133
+ *      8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137
  * @summary Check root CA entries in cacerts file
  */
 import java.io.File;
@@ -212,8 +212,6 @@
                     "03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7");
             put("affirmtrustpremiumeccca [jdk]",
                     "BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23");
-            put("deutschetelekomrootca2 [jdk]",
-                    "B6:19:1A:50:D0:C3:97:7F:7D:A9:9B:CD:AA:C8:6A:22:7D:AE:B9:67:9E:C7:0B:A3:B0:C9:D9:22:71:C1:70:D3");
             put("ttelesecglobalrootclass3ca [jdk]",
                     "FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD");
             put("ttelesecglobalrootclass2ca [jdk]",
@@ -232,6 +230,8 @@
                     "CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E");
             put("teliasonerarootcav1 [jdk]",
                     "DD:69:36:FE:21:F8:F0:77:C1:23:A1:A5:21:C1:22:24:F7:22:55:B7:3E:03:A7:26:06:93:E8:A2:4B:0F:A3:89");
+            put("globalsignrootcar6 [jdk]",
+                    "2C:AB:EA:FE:37:D0:6C:A2:2A:BA:73:91:C0:03:3D:25:98:29:52:C4:53:64:73:49:76:3A:3A:B5:AD:6C:CF:69");
         }
     };
 
@@ -245,8 +245,6 @@
             add("certplusclass3pprimaryca [jdk]");
             // Valid until: Tue Jul 09 14:40:36 EDT 2019
             add("utnuserfirstobjectca [jdk]");
-            // Valid until: Tue Jul 09 19:59:00 EDT 2019
-            add("deutschetelekomrootca2 [jdk]");
             // Valid until: Tue Jul 09 13:36:58 EDT 2019
             add("utnuserfirstclientauthemailca [jdk]");
             // Valid until: Tue Jul 09 14:19:22 EDT 2019
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java	Fri May 03 14:59:32 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
@@ -384,11 +384,14 @@
 
     static boolean loadNSPR(String libdir) throws Exception {
         // load NSS softoken dependencies in advance to avoid resolver issues
-        safeReload(libdir + System.mapLibraryName("nspr4"));
-        safeReload(libdir + System.mapLibraryName("plc4"));
-        safeReload(libdir + System.mapLibraryName("plds4"));
-        safeReload(libdir + System.mapLibraryName("sqlite3"));
-        safeReload(libdir + System.mapLibraryName("nssutil3"));
+        String dir = libdir.endsWith(File.separator)
+                     ? libdir
+                     : libdir + File.separator;
+        safeReload(dir + System.mapLibraryName("nspr4"));
+        safeReload(dir + System.mapLibraryName("plc4"));
+        safeReload(dir + System.mapLibraryName("plds4"));
+        safeReload(dir + System.mapLibraryName("sqlite3"));
+        safeReload(dir + System.mapLibraryName("nssutil3"));
         return true;
     }
 
@@ -903,21 +906,21 @@
     @Artifact(
             organization = "jpg.tests.jdk.nsslib",
             name = "nsslib-windows_x64",
-            revision = "3.35",
+            revision = "3.41-VS2017",
             extension = "zip")
     private static class WINDOWS_X64 { }
 
     @Artifact(
             organization = "jpg.tests.jdk.nsslib",
             name = "nsslib-windows_x86",
-            revision = "3.35",
+            revision = "3.41-VS2017",
             extension = "zip")
     private static class WINDOWS_X86 { }
 
     @Artifact(
             organization = "jpg.tests.jdk.nsslib",
             name = "nsslib-macosx_x64",
-            revision = "3.35",
+            revision = "3.41",
             extension = "zip")
     private static class MACOSX_X64 { }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,491 @@
+/*
+ * 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 -Djdk.tls.useExtendedMasterSecret=false FipsModeTLS12
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+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 FipsModeTLS12 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 PrivateKey privateKey;
+    private static PublicKey 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 {
+        //
+        // For a successful FIPS-mode TLS connection, the following
+        // cryptographic providers will be installed:
+        //
+        //  1. SunPKCS11 (with an NSS FIPS mode backend)
+        //  2. SUN (to handle X.509 certificates)
+        //  3. SunJSSE (for a TLS engine)
+        //
+        // RSASSA-PSS algorithm is not currently supported in SunPKCS11
+        // but in SUN provider. As a result, it can be negotiated by the
+        // TLS engine. The problem is that SunPKCS11 keys are sensitive
+        // in FIPS mode and cannot be used in a SUN algorithm (conversion
+        // fails as plain values cannot be extracted).
+        //
+        // To workaround this issue, we disable RSASSA-PSS algorithm for
+        // TLS connections. Once JDK-8222937 is fixed, this workaround can
+        // (and should) be removed.
+        //
+        // On a final note, the list of disabled TLS algorithms
+        // (jdk.tls.disabledAlgorithms) has to be updated at this point,
+        // before it is read in sun.security.ssl.SSLAlgorithmConstraints
+        // class initialization.
+        String disabledAlgorithms =
+                Security.getProperty("jdk.tls.disabledAlgorithms");
+        if (disabledAlgorithms.length() > 0) {
+            disabledAlgorithms += ", ";
+        }
+        disabledAlgorithms += "RSASSA-PSS";
+        Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms);
+
+        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 = (PrivateKey)ksPlain.getKey("rh_rsa_sha256",
+                passphrase);
+        publicKey = (PublicKey)ksPlain.getCertificate(
+                "rh_rsa_sha256").getPublicKey();
+    }
+
+    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;
+    }
+}
--- a/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java	Fri May 03 11:28:14 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,471 +0,0 @@
-/*
- * 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 -Djdk.tls.useExtendedMasterSecret=false TestTLS12
- */
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-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 PrivateKey privateKey;
-    private static PublicKey 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 = (PrivateKey)ksPlain.getKey("rh_rsa_sha256",
-                passphrase);
-        publicKey = (PublicKey)ksPlain.getCertificate(
-                "rh_rsa_sha256").getPublicKey();
-
-        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;
-    }
-}
--- a/test/jdk/sun/security/tools/keytool/NssTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/jdk/sun/security/tools/keytool/NssTest.java	Fri May 03 14:59:32 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
@@ -47,6 +47,8 @@
         copyFiles();
         System.setProperty("nss", "");
         System.setProperty("nss.lib", String.valueOf(libPath));
+
+        PKCS11Test.loadNSPR(libPath.getParent().toString());
         KeyToolTest.main(args);
     }
 
--- a/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java	Fri May 03 14:59:32 2019 -0400
@@ -50,10 +50,10 @@
 
         checkOutput("p1/subpkg/SSC.html", true,
                 // Test the top line of the class tree
-                "<li><a href=\"../C.html\" title=\"class in p1\">p1.C</a></li>",
+                "<div class=\"inheritance\"><a href=\"../C.html\" title=\"class in p1\">p1.C</a>",
                 // Test the second line of the class tree
-                "<li><a href=\"../SC.html\" title=\"class in p1\">p1.SC</a></li>",
+                "<div class=\"inheritance\"><a href=\"../SC.html\" title=\"class in p1\">p1.SC</a>",
                 // Test the third line of the class tree
-                "<li>p1.subpkg.SSC</li>");
+                "<div class=\"inheritance\">p1.subpkg.SSC</div>\n</div>\n</div>");
     }
 }
--- a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java	Fri May 03 14:59:32 2019 -0400
@@ -62,6 +62,9 @@
                 + "</code></th>",
                 "<!-- ============ ANNOTATION TYPE FIELD DETAIL =========== -->",
                 "<h3>DEFAULT_NAME</h3>\n"
+                + "<a id=\"DEFAULT_NAME\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre>static final&nbsp;java."
                 + "lang.String&nbsp;DEFAULT_NAME</pre>");
 
@@ -74,17 +77,20 @@
         checkOutput("pkg/AnnotationType.html", true,
                     "<!-- ============ ANNOTATION TYPE MEMBER DETAIL =========== -->",
                     "<ul class=\"blockList\">",
-                    "<li class=\"blockList\"><a id=\"annotation.type.element.detail\">",
+                    "<li class=\"blockList\">",
+                    "<section class=\"memberDetails\">",
+                    "<h2>Element Detail</h2>",
+                    "<a id=\"annotation.type.element.detail\">",
                     "<!--   -->",
                     "</a>",
-                    "<h2>Element Detail</h2>",
+                    "<ul class=\"blockList\">",
+                    "<li class=\"blockListLast\">",
+                    "<section class=\"detail\">",
+                    "<h3>value</h3>",
                     "<a id=\"value()\">",
                     "<!--   -->",
                     "</a>",
-                    "<ul class=\"blockListLast\">",
-                    "<li class=\"blockList\">",
-                    "<h3>value</h3>",
-                    "<pre>int&nbsp;value</pre>" );
+                    "<pre>int&nbsp;value</pre>");
 
         checkOutput("pkg/AnnotationType.html", false,
                 "<HR>\n\n"
--- a/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testHiddenTag/TestHiddenTag.java	Fri May 03 14:59:32 2019 -0400
@@ -68,10 +68,11 @@
                 "<code><a href=\"A.html#visibleMethod()\">visibleMethod</a></code>",
                 "<h2>Nested classes/interfaces inherited from class&nbsp;pkg1." +
                 "<a href=\"A.html\" title=\"class in pkg1\">A</a></h2>\n" +
-                "<code><a href=\"A.VisibleInner.html\" title=\"class in pkg1\">" +
+                "<a id=\"nested.classes.inherited.from.class.pkg1.A\">\n" +
+                "<!--   -->\n" +
+                "</a><code><a href=\"A.VisibleInner.html\" title=\"class in pkg1\">" +
                 "A.VisibleInner</a>, <a href=\"A.VisibleInnerExtendsInvisibleInner.html\" " +
-                "title=\"class in pkg1\">A.VisibleInnerExtendsInvisibleInner</a></code></li>\n" +
-                "</ul>");
+                "title=\"class in pkg1\">A.VisibleInnerExtendsInvisibleInner</a></code></div>\n");
 
         checkOutput("pkg1/A.VisibleInner.html", false,
                 "../pkg1/A.VisibleInner.html#VisibleInner()",
@@ -82,7 +83,7 @@
                 "<pre>public static class <span class=\"typeNameLabel\">" +
                 "A.VisibleInnerExtendsInvisibleInner</span>\n" +
                 "extends <a href=\"A.html\" title=\"class in pkg1\">A</a></pre>",
-                "<code><a href=\"A.html#visibleField\">visibleField</a></code></li>",
+                "<code><a href=\"A.html#visibleField\">visibleField</a></code>",
                 "<code><a href=\"A.html#visibleMethod()\">visibleMethod</a></code>");
 
         checkOutput("pkg1/A.VisibleInnerExtendsInvisibleInner.html", false,
--- a/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java	Fri May 03 14:59:32 2019 -0400
@@ -375,10 +375,12 @@
         checkOutput("pkg1/C1.html", expectFound,
                 "<pre class=\"methodSignature\">public&nbsp;void&nbsp;readObject()\n" +
                 "                throws java.io.IOException</pre>\n" +
+                "</section>\n" +
                 "</li>");
 
         checkOutput("pkg1/C2.html", expectFound,
                 "<pre>public&nbsp;C2()</pre>\n" +
+                "</section>\n" +
                 "</li>");
 
         checkOutput("pkg1/C1.ModalExclusionType.html", expectFound,
@@ -386,6 +388,7 @@
                 "static final&nbsp;<a href=\"C1.ModalExclusionType.html\" " +
                 "title=\"enum in pkg1\">C1.ModalExclusionType</a> " +
                 "APPLICATION_EXCLUDE</pre>\n" +
+                "</section>\n" +
                 "</li>");
 
         checkOutput("serialized-form.html", expectFound,
--- a/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java	Fri May 03 14:59:32 2019 -0400
@@ -109,7 +109,7 @@
 
         checkOutput("pkg3/package-summary.html", true,
                 "<div class=\"contentContainer\">\n"
-                + "<section><a id=\"package.description\">\n"
+                + "<section class=\"packageDescription\"><a id=\"package.description\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<div class=\"block\"><p>This is the first line. Note the newlines before the &lt;p&gt; is relevant.</div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Fri May 03 14:59:32 2019 -0400
@@ -100,7 +100,7 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section><a id=\"package.description\">\n"
+                "<section class=\"packageDescription\"><a id=\"package.description\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<div class=\"block\">Test package.</div>",
@@ -110,6 +110,7 @@
         // No package description
         checkOutput("pkg1/package-summary.html", true,
                 "<div class=\"contentContainer\">\n"
+                + "<section class=\"summary\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
                 + "<div class=\"typeSummary\">\n<table>\n"
@@ -129,13 +130,13 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Interface Hierarchy\">Interface Hierarchy</h2>",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Annotation Type Hierarchy\">Annotation Type Hierarchy</h2>",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Enum Hierarchy\">Enum Hierarchy</h2>",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -173,9 +174,9 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
+                "<section class=\"packages\">\n"
                 + "<h2 title=\"Contents\">Contents</h2>\n",
-                "<section>\n"
+                "<section class=\"constantsSummary\">\n"
                 + "<h2 title=\"pkg\">pkg.*</h2>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -212,7 +213,7 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
+                "<section class=\"serializedPackageContainer\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -232,13 +233,13 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>\n",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Interface Hierarchy\">Interface Hierarchy</h2>\n",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Annotation Type Hierarchy\">Annotation Type Hierarchy</h2>\n",
-                "<section>\n"
+                "<section class=\"hierarchy\">\n"
                 + "<h2 title=\"Enum Hierarchy\">Enum Hierarchy</h2>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -280,11 +281,11 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
+                "<section class=\"helpSection\">\n"
                 + "<h2>Overview</h2>\n",
-                "<section>\n"
+                "<section class=\"helpSection\">\n"
                 + "<h2>Package</h2>\n",
-                "<section>\n"
+                "<section class=\"helpSection\">\n"
                 + "<h2>Class or Interface</h2>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -303,51 +304,40 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"nested.class.summary\">\n"
+                "<section class=\"nestedClassSummary\"><a id=\"nested.class.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Nested Class Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"field.summary\">\n"
+                "<section class=\"fieldSummary\"><a id=\"field.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Field Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+                "<section class=\"constructorSummary\"><a id=\"constructor.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Constructor Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.summary\">\n"
+                "<section class=\"methodSummary\"><a id=\"method.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Method Summary</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"field.detail\">\n"
+                "<section class=\"fieldDetails\">\n"
+                + "<h2>Field Detail</h2>\n"
+                + "<a id=\"field.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Field Detail</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+                + "</a>",
+                "<section class=\"constructorDetails\">\n"
+                + "<h2>Constructor Detail</h2>\n"
+                + "<a id=\"constructor.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Constructor Detail</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.detail\">\n"
+                + "</a>",
+                "<section class=\"methodDetails\">\n"
+                + "<h2>Method Detail</h2>\n"
+                + "<a id=\"method.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Method Detail</h2>",
+                + "</a>",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -365,34 +355,28 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"enum.constant.summary\">\n"
+                "<section class=\"constantsSummary\"><a id=\"enum.constant.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Enum Constant Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n",
                 "<table aria-labelledby=\"t0\">\n",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.summary\">\n"
+                "<section class=\"methodSummary\"><a id=\"method.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Method Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n",
                 "<table aria-labelledby=\"t0\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"enum.constant.detail\">\n"
+                "<section class=\"constantDetails\">\n"
+                + "<h2>Enum Constant Detail</h2>\n"
+                + "<a id=\"enum.constant.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Enum Constant Detail</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.detail\">\n"
+                + "</a>\n",
+                "<section class=\"methodDetails\">\n"
+                + "<h2>Method Detail</h2>\n"
+                + "<a id=\"method.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Method Detail</h2>",
+                + "</a>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -410,20 +394,17 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.summary\">\n"
+                "<section class=\"methodSummary\"><a id=\"method.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Method Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n",
                 "<table aria-labelledby=\"t0\">\n",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"method.detail\">\n"
+                "<section class=\"methodDetails\">\n"
+                + "<h2>Method Detail</h2>\n"
+                + "<a id=\"method.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Method Detail</h2>",
+                + "</a>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -441,18 +422,15 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+                "<section class=\"constructorSummary\"><a id=\"constructor.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Constructor Summary</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+                "<section class=\"constructorDetails\">\n"
+                + "<h2>Constructor Detail</h2>\n"
+                + "<a id=\"constructor.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Constructor Detail</h2>",
+                + "</a>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -470,18 +448,15 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.summary\">\n"
+                "<section class=\"constructorSummary\"><a id=\"constructor.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Constructor Summary</h2>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"constructor.detail\">\n"
+                "<section class=\"constructorDetails\">\n"
+                + "<h2>Constructor Detail</h2>\n"
+                + "<a id=\"constructor.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Constructor Detail</h2>",
+                + "</a>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -499,26 +474,21 @@
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"annotation.type.required.element.summary\">\n"
+                "<section class=\"memberSummary\"><a id=\"annotation.type.required.element.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Required Element Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"annotation.type.optional.element.summary\">\n"
+                "<section class=\"memberSummary\"><a id=\"annotation.type.optional.element.summary\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Optional Element Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>",
-                "<section>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\"><a id=\"annotation.type.element.detail\">\n"
+                "<section class=\"memberDetails\">\n"
+                + "<h2>Element Detail</h2>\n"
+                + "<a id=\"annotation.type.element.detail\">\n"
                 + "<!--   -->\n"
-                + "</a>\n"
-                + "<h2>Element Detail</h2>",
+                + "</a>\n",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -537,7 +507,7 @@
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
                 "<div class=\"useSummary\">\n<table>",
-                "<section><a id=\"pkg\">\n"
+                "<section class=\"detail\"><a id=\"pkg\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<h2>Uses of <a href=\"../RegClass.html\" title=\"class in pkg1\">RegClass</a> in <a href=\"../../pkg/package-summary.html\">pkg</a></h2>\n"
@@ -569,7 +539,7 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<section>\n"
-                + "<h2 title=\"Package pkg Description\">Package pkg Description</h2>\n",
+                + "<h2 title=\"PackagAnotherClass.ModalExclusionType.htmle pkg Description\">Package pkg Description</h2>\n",
                 "<div class=\"typeSummary\">\n<table summary=\"Interface Summary table, listing interfaces, and an explanation\">",
                 "<div class=\"typeSummary\">\n<table summary=\"Class Summary table, listing classes, and an explanation\">",
                 "<div class=\"typeSummary\">\n<table summary=\"Enum Summary table, listing enums, and an explanation\">",
--- a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java	Fri May 03 14:59:32 2019 -0400
@@ -85,20 +85,11 @@
                 + "Interface</a>&lt;CE&gt;</code></dd>\n"
                 + "</dl>",
                 //Make sure Class Tree has substituted type parameters.
-                "<ul class=\"inheritance\">\n"
-                + "<li>java.lang.Object</li>\n"
-                + "<li>\n"
-                + "<ul class=\"inheritance\">\n"
-                + "<li><a href=\"Parent.html\" title=\"class in pkg\">"
-                + "pkg.Parent</a>&lt;CE&gt;</li>\n"
-                + "<li>\n"
-                + "<ul class=\"inheritance\">\n"
-                + "<li>pkg.Child&lt;CE&gt;</li>\n"
-                + "</ul>\n"
-                + "</li>\n"
-                + "</ul>\n"
-                + "</li>\n"
-                + "</ul>",
+                "<div class=\"inheritance\" title=\"Inheritance Tree\">java.lang.Object\n"
+                + "<div class=\"inheritance\"><a href=\"Parent.html\""
+                + " title=\"class in pkg\">pkg.Parent</a>&lt;CE&gt;\n"
+                + "<div class=\"inheritance\">pkg.Child&lt;CE&gt;</div>\n"
+                + "</div>\n</div>",
                 //Make sure "Specified By" has substituted type parameters.
                 "<dt><span class=\"overrideSpecifyLabel\">Specified by:</span></dt>\n"
                 + "<dd><code><a href=\"Interface.html#method()\">method</a>"
@@ -132,6 +123,9 @@
 
         checkOutput("pkg/ClassWithStaticMembers.html", true,
                 "<h3>f</h3>\n"
+                + "<a id=\"f\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre>public static&nbsp;int f</pre>\n"
                 + "<div class=\"block\">A hider field</div>",
 
@@ -143,6 +137,9 @@
                 + "</td>\n",
 
                 "<h3>staticMethod</h3>\n"
+                + "<a id=\"staticMethod()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public static&nbsp;void&nbsp;staticMethod()</pre>\n"
                 + "<div class=\"block\"><span class=\"descfrmTypeLabel\">"
                 + "Description copied from interface:&nbsp;<code>"
@@ -185,7 +182,9 @@
             // Ensure the correct type parameters are displayed correctly
             "<h2>Nested classes/interfaces inherited from interface&nbsp;pkg2."
             + "<a href=\"Spliterator.html\" title=\"interface in pkg2\">Spliterator</a></h2>\n"
-            + "<code><a href=\"Spliterator.OfDouble.html\" title=\"interface in pkg2\">"
+            + "<a id=\"nested.classes.inherited.from.class.pkg2.Spliterator\">\n"
+            + "<!--   -->\n"
+            + "</a><code><a href=\"Spliterator.OfDouble.html\" title=\"interface in pkg2\">"
             + "Spliterator.OfDouble</a>, <a href=\"Spliterator.OfInt.html\" "
             + "title=\"interface in pkg2\">Spliterator.OfInt</a>&lt;"
             + "<a href=\"Spliterator.OfInt.html\" title=\"type parameter in Spliterator.OfInt\">"
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Fri May 03 14:59:32 2019 -0400
@@ -87,13 +87,22 @@
                 + "<td class=\"colLast\">\n"
                 + "<div class=\"block\">Defines if paused.</div>",
                 "<h3>paused</h3>\n"
+                + "<a id=\"pausedProperty\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre>public final&nbsp;<a href=\"C.BooleanProperty.html\" "
                 + "title=\"class in pkg1\">C.BooleanProperty</a> pausedProperty</pre>\n"
                 + "<div class=\"block\">Defines if paused. The second line.</div>",
                 "<h3>isPaused</h3>\n"
+                + "<a id=\"isPaused()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public final&nbsp;double&nbsp;isPaused()</pre>\n"
                 + "<div class=\"block\">Gets the value of the property paused.</div>",
                 "<h3>setPaused</h3>\n"
+                + "<a id=\"setPaused(boolean)\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public final&nbsp;void&nbsp;setPaused&#8203;(boolean&nbsp;value)</pre>\n"
                 + "<div class=\"block\">Sets the value of the property paused.</div>\n"
                 + "<dl>\n"
@@ -102,6 +111,9 @@
                 + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
                 + "<dd>false</dd>",
                 "<h3>isPaused</h3>\n"
+                + "<a id=\"isPaused()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public final&nbsp;double&nbsp;isPaused()</pre>\n"
                 + "<div class=\"block\">Gets the value of the property paused.</div>\n"
                 + "<dl>\n"
@@ -110,12 +122,18 @@
                 + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
                 + "<dd>false</dd>",
                 "<h3>rate</h3>\n"
+                + "<a id=\"rateProperty\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre>public final&nbsp;<a href=\"C.DoubleProperty.html\" "
                 + "title=\"class in pkg1\">C.DoubleProperty</a> rateProperty</pre>\n"
                 + "<div class=\"block\">Defines the direction/speed at which the "
                 + "<code>Timeline</code> is expected to\n"
                 + " be played. This is the second line.</div>",
                 "<h3>setRate</h3>\n"
+                + "<a id=\"setRate(double)\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public final&nbsp;void&nbsp;setRate&#8203;(double&nbsp;value)</pre>\n"
                 + "<div class=\"block\">Sets the value of the property rate.</div>\n"
                 + "<dl>\n"
@@ -127,6 +145,9 @@
                 + "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
                 + "<dd>JavaFX 8.0</dd>",
                 "<h3>getRate</h3>\n"
+                + "<a id=\"getRate()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public final&nbsp;double&nbsp;getRate()</pre>\n"
                 + "<div class=\"block\">Gets the value of the property rate.</div>\n"
                 + "<dl>\n"
@@ -170,8 +191,10 @@
         checkOutput("pkg1/D.html", true,
                 "<h3>Properties inherited from class&nbsp;pkg1."
                     + "<a href=\"C.html\" title=\"class in pkg1\">C</a></h3>\n"
-                    + "<code><a href=\"C.html#pausedProperty\">"
-                    + "paused</a>, <a href=\"C.html#rateProperty\">rate</a></code></li>");
+                    + "<a id=\"properties.inherited.from.class.pkg1.C\">\n"
+                    + "<!--   -->\n"
+                    + "</a><code><a href=\"C.html#pausedProperty\">"
+                    + "paused</a>, <a href=\"C.html#rateProperty\">rate</a></code></div>");
 
         checkOutput("pkg1/D.html", false, "shouldNotAppear");
     }
@@ -191,36 +214,40 @@
         checkExit(Exit.OK);
         checkOutput("pkg2/Test.html", true,
                 "<h2>Property Detail</h2>\n"
-                + "<a id=\"betaProperty\">\n"
-                + "<!--   -->\n"
-                + "</a>\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<h3>beta</h3>\n"
-                + "<pre>public&nbsp;java.lang.Object betaProperty</pre>\n"
-                + "</li>\n"
-                + "</ul>\n"
-                + "<a id=\"gammaProperty\">\n"
+                + "<a id=\"property.detail\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
+                + "<section class=\"detail\">\n"
+                + "<h3>beta</h3>\n"
+                + "<a id=\"betaProperty\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<pre>public&nbsp;java.lang.Object betaProperty</pre>\n"
+                + "</section>\n"
+                + "</li>\n"
+                + "<li class=\"blockList\">\n"
+                + "<section class=\"detail\">\n"
                 + "<h3>gamma</h3>\n"
+                + "<a id=\"gammaProperty\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre>public final&nbsp;java.util.List&lt;java.lang.String&gt; gammaProperty</pre>\n"
+                + "</section>\n"
                 + "</li>\n"
-                + "</ul>\n"
+                + "<li class=\"blockListLast\">\n"
+                + "<section class=\"detail\">\n"
+                + "<h3>delta</h3>\n"
                 + "<a id=\"deltaProperty\">\n"
                 + "<!--   -->\n"
                 + "</a>\n"
-                + "<ul class=\"blockListLast\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<h3>delta</h3>\n"
                 + "<pre>public final&nbsp;java.util.List&lt;"
                 + "java.util.Set&lt;? super java.lang.Object&gt;&gt; deltaProperty</pre>\n"
+                + "</section>\n"
                 + "</li>\n"
                 + "</ul>\n"
-                + "</li>\n"
-                + "</ul>",
+                + "</section>",
                 "<h2>Property Summary</h2>\n"
                 + "<div class=\"memberSummary\">\n<table>\n"
                 + "<caption><span>Properties</span><span class=\"tabEnd\">&nbsp;</span></caption>");
--- a/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testModuleDirs/TestModuleDirs.java	Fri May 03 14:59:32 2019 -0400
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8195795 8201396 8196202
+ * @bug 8195795 8201396 8196202 8215582
  * @summary test the use of module directories in output,
  *          and the --no-module-directories option
  * @modules jdk.javadoc/jdk.javadoc.internal.api
@@ -76,32 +76,12 @@
                 .classes("package pa; public class A {}")
                 .exports("pa")
                 .write(src);
-        new ModuleBuilder(tb, "mb")
-                .classes("package pb; public class B {}")
-                .exports("pb")
-                .write(src);
 
         javadoc("-d", base.resolve("api").toString(),
-                "-quiet",
                 "--module-source-path", src.toString(),
                 "--no-module-directories",
                 "--module", "ma,mb");
-
-        checkExit(Exit.OK);
-        checkFiles(true,
-                "ma-summary.html",
-                "pa/package-summary.html");
-        checkFiles(false,
-                "ma/module-summary.html",
-                "ma/pa/package-summary.html");
-        checkOutput("ma-summary.html", false,
-                "<ul class=\"navList\" id=\"allclasses_navbar_top\">\n"
-                + "<li><a href=\"allclasses-noframe.html\">All&nbsp;Classes</a></li>\n"
-                + "</ul>\n");
-        checkOutput("pa/package-summary.html", true,
-                "<li><a href=\"../deprecated-list.html\">Deprecated</a></li>\n"
-                + "<li><a href=\"../index-all.html\">Index</a></li>");
-
+        checkExit(Exit.ERROR);
     }
 
     @Test
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Fri May 03 14:59:32 2019 -0400
@@ -478,7 +478,7 @@
 
     void checkHtml5Description(boolean found) {
         checkOutput("moduleA/module-summary.html", found,
-                "<section>\n"
+                "<section class=\"moduleDescription\">\n"
                 + "<div class=\"deprecationBlock\"><span class=\"deprecatedLabel\">Deprecated, for removal:"
                 + " This API element is subject to removal in a future version.</span>\n"
                 + "<div class=\"deprecationComment\">This module is deprecated.</div>\n"
@@ -490,7 +490,7 @@
                 + "<div class=\"block\">This is a test description for the moduleA module with a Search "
                 + "phrase <a id=\"searchphrase\" class=\"searchTagResult\">search phrase</a>.</div>");
         checkOutput("moduleB/module-summary.html", found,
-                "<section>\n"
+                "<section class=\"moduleDescription\">\n"
                 + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
                 + "<a id=\"module.description\">\n"
                 + "<!--   -->\n"
@@ -523,17 +523,17 @@
     void checkHtml5NoDescription(boolean found) {
         checkOutput("moduleA/module-summary.html", found,
                 "<div class=\"contentContainer\">\n"
+                + "<section class=\"summary\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
+                + "<section class=\"packagesSummary\">\n"
                 + "<!-- ============ PACKAGES SUMMARY =========== -->");
         checkOutput("moduleB/module-summary.html", found,
                 "<div class=\"contentContainer\">\n"
+                + "<section class=\"summary\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
+                + "<section class=\"packagesSummary\">\n"
                 + "<!-- ============ PACKAGES SUMMARY =========== -->");
     }
 
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Fri May 03 14:59:32 2019 -0400
@@ -193,10 +193,18 @@
                 "<pre>@Documented\npublic @interface <a href="
                 + "\"../src-html/linksource/AnnotationTypeField.html#line.31\">"
                 + "AnnotationTypeField</a></pre>",
-                "<h3>DEFAULT_NAME</h3>\n<pre>static final&nbsp;java.lang.String&nbsp;"
+                "<h3>DEFAULT_NAME</h3>\n"
+                + "<a id=\"DEFAULT_NAME\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<pre>static final&nbsp;java.lang.String&nbsp;"
                 + "<a href=\"../src-html/linksource/AnnotationTypeField.html#line.32\">"
                 + "DEFAULT_NAME</a></pre>",
-                "<h3>name</h3>\n<pre>java.lang.String&nbsp;<a href="
+                "<h3>name</h3>\n"
+                + "<a id=\"name()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<pre>java.lang.String&nbsp;<a href="
                 + "\"../src-html/linksource/AnnotationTypeField.html#line.34\">name</a></pre>");
 
         checkOutput("src-html/linksource/AnnotationTypeField.html", true,
@@ -260,9 +268,9 @@
         checkExit(Exit.OK);
 
         checkOutput("pkg/Foo.html", true,
-                "<li>Foo</li>");
+                "<div class=\"inheritance\">Foo</div>");
         checkOutput("deprecated/Foo.html", true,
-                "<li>deprecated.Foo</li>");
+                "<div class=\"inheritance\">deprecated.Foo</div>");
 
         javadoc("-d", "out-10a",
                 "-noqualifier", "all",
@@ -271,8 +279,8 @@
         checkExit(Exit.OK);
 
         checkOutput("pkg/Foo.html", true,
-                "<li>Foo</li>");
+                "<div class=\"inheritance\">Foo</div>");
         checkOutput("deprecated/Foo.html", true,
-                "<li>Foo</li>");
+                "<div class=\"inheritance\">Foo</div>");
     }
 }
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestBadOverride.java	Fri May 03 14:59:32 2019 -0400
@@ -52,10 +52,13 @@
         checkExit(Exit.OK);
 
         checkOutput("pkg4/Foo.html", true,
-                "<li class=\"blockList\">\n"
+                "<section class=\"detail\">\n"
                 + "<h3>toString</h3>\n"
+                + "<a id=\"toString()\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
                 + "<pre class=\"methodSignature\">public&nbsp;void&nbsp;toString()</pre>\n"
                 + "<div class=\"block\">Why can't I do this ?</div>\n"
-                + "</li>");
+                + "</section>");
     }
 }
--- a/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java	Fri May 03 14:59:32 2019 -0400
@@ -66,14 +66,9 @@
                 "<a href=\"#methodInheritedFromParent(int)\">"
                 + "methodInheritedFromParent</a>",
                 // private class does not show up in tree
-                "<ul class=\"inheritance\">\n"
-                + "<li>java.lang.Object</li>\n"
-                + "<li>\n"
-                + "<ul class=\"inheritance\">\n"
-                + "<li>pkg.PublicChild</li>\n"
-                + "</ul>\n"
-                + "</li>\n"
-                + "</ul>",
+                "<div class=\"inheritance\" title=\"Inheritance Tree\">java.lang.Object\n"
+                + "<div class=\"inheritance\">pkg.PublicChild</div>\n"
+                + "</div>",
                 // Method is documented as though it is declared in the inheriting method.
                 "<pre class=\"methodSignature\">public&nbsp;void&nbsp;methodInheritedFromParent&#8203;(int&nbsp;p1)",
                 "<dl>\n"
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Fri May 03 14:59:32 2019 -0400
@@ -291,22 +291,8 @@
     }
 
     @Test
-    public void testNoModuleDirectories() {
-        javadoc("-d", "out-noMdlDir",
-                "--no-module-directories",
-                "-Xdoclint:none",
-                "-sourcepath", testSrc,
-                "-use",
-                "pkg", "pkg1", "pkg2", "pkg3");
-        checkExit(Exit.OK);
-        checkSearchOutput(true, false);
-        checkSearchJS();
-    }
-
-    @Test
     public void testURLEncoding() {
         javadoc("-d", "out-encode-html5",
-                "--no-module-directories",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-use",
@@ -320,7 +306,6 @@
     public void testJapaneseLocale() {
         javadoc("-locale", "ja_JP",
                 "-d", "out-jp",
-                "--no-module-directories",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-use",
@@ -339,7 +324,6 @@
     public void testChineseLocale() {
         javadoc("-locale", "zh_CN",
                 "-d", "out-cn",
-                "--no-module-directories",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-use",
@@ -396,10 +380,9 @@
                 "<script type=\"text/javascript\" src=\"script-dir/jquery-migrate-3.0.1.js\"></script>\n",
                 "<script type=\"text/javascript\" src=\"script-dir/jquery-ui.js\"></script>",
                 "var pathtoroot = \"./\";\n"
-                + "var useModuleDirectories = " + moduleDirectoriesVar + ";\n"
                 + "loadScripts(document, 'script');",
-                "<ul class=\"navListSearch\">\n",
-                "<li><label for=\"search\">SEARCH:</label>\n"
+                "<div class=\"navListSearch\">",
+                "<label for=\"search\">SEARCH:</label>\n"
                 + "<input type=\"text\" id=\"search\" value=\"search\" disabled=\"disabled\">\n"
                 + "<input type=\"reset\" id=\"reset\" value=\"reset\" disabled=\"disabled\">\n");
         checkOutput(fileName, true,
@@ -617,14 +600,7 @@
 
     void checkSearchJS() {
         checkOutput("search.js", true,
-                "camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join(\"([a-z0-9_$]*?)\");",
-                "var camelCaseMatcher = new RegExp(\"^\" + camelCaseRegexp);",
-                "camelCaseMatcher.test(item.l)",
-                "var secondaryresult = new Array();",
-                "function nestedName(e) {",
                 "function concatResults(a1, a2) {",
-                "if (exactMatcher.test(item.l)) {\n"
-                + "                        presult.push(item);",
                 "$(\"#search\").on('click keydown paste', function() {\n"
                 + "        if ($(this).val() == watermark) {\n"
                 + "            $(this).val('').removeClass('watermark');\n"
@@ -632,22 +608,20 @@
                 + "    });",
                 "function getURLPrefix(ui) {\n"
                 + "    var urlPrefix=\"\";\n"
-                + "    if (useModuleDirectories) {\n"
-                + "        var slash = \"/\";\n"
-                + "        if (ui.item.category === catModules) {\n"
-                + "            return ui.item.l + slash;\n"
-                + "        } else if (ui.item.category === catPackages && ui.item.m) {\n"
-                + "            return ui.item.m + slash;\n"
-                + "        } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {\n"
-                + "            $.each(packageSearchIndex, function(index, item) {\n"
-                + "                if (item.m && ui.item.p == item.l) {\n"
-                + "                    urlPrefix = item.m + slash;\n"
-                + "                }\n"
-                + "            });\n"
-                + "            return urlPrefix;\n"
-                + "        } else {\n"
-                + "            return urlPrefix;\n"
-                + "        }\n"
+                + "    var slash = \"/\";\n"
+                + "    if (ui.item.category === catModules) {\n"
+                + "        return ui.item.l + slash;\n"
+                + "    } else if (ui.item.category === catPackages && ui.item.m) {\n"
+                + "        return ui.item.m + slash;\n"
+                + "    } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) {\n"
+                + "        $.each(packageSearchIndex, function(index, item) {\n"
+                + "            if (item.m && ui.item.p == item.l) {\n"
+                + "                urlPrefix = item.m + slash;\n"
+                + "            }\n"
+                + "        });\n"
+                + "        return urlPrefix;\n"
+                + "    } else {\n"
+                + "        return urlPrefix;\n"
                 + "    }\n"
                 + "    return urlPrefix;\n"
                 + "}",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/TestSearchScript.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,312 @@
+/*
+ * 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 8178982 8220497 8210683
+ * @summary Test the search feature of javadoc.
+ * @library ../../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build javadoc.tester.*
+ * @run main TestSearchScript
+ */
+
+import javadoc.tester.JavadocTester;
+
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.List;
+
+/*
+ * Tests for the search feature using Nashorn JavaScript engine.
+ */
+public class TestSearchScript extends JavadocTester {
+
+    public static void main(String... args) throws Exception {
+        TestSearchScript tester = new TestSearchScript();
+        tester.runTests();
+    }
+
+    private Invocable getEngine() throws ScriptException, IOException, NoSuchMethodException {
+        ScriptEngineManager engineManager = new ScriptEngineManager();
+        ScriptEngine engine = engineManager.getEngineByName("nashorn");
+        engine.eval(new BufferedReader(new FileReader(new File(testSrc, "javadoc-search.js"))));
+        Invocable inv = (Invocable) engine;
+        inv.invokeFunction("loadIndexFiles", outputDir.getAbsolutePath());
+        return inv;
+    }
+
+    @Test
+    public void testModuleSearch() throws ScriptException, IOException, NoSuchMethodException {
+        javadoc("-d", "out-full",
+                "-Xdoclint:none",
+                "-use",
+                "--module-source-path", testSrc,
+                "--module", "mapmodule",
+                "mappkg", "mappkg.impl");
+        checkExit(Exit.OK);
+
+        Invocable inv = getEngine();
+
+        // exact match, case sensitivity
+        checkSearch(inv, "mapmodule", List.of("mapmodule"));
+        checkSearch(inv, "mappkg", List.of("mapmodule/mappkg", "mapmodule/mappkg.impl", "mappkg.system.property"));
+        checkSearch(inv, "Mapmodule", List.of());
+        checkSearch(inv, "Mappkg", List.of());
+        checkSearch(inv, "mymap", List.of("mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "MyMap", List.of("mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "mymap(", List.of("mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "MyMap(", List.of("mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "mymap()", List.of("mappkg.impl.MyMap.MyMap()"));
+        checkSearch(inv, "MyMap()", List.of("mappkg.impl.MyMap.MyMap()"));
+        checkSearch(inv, "Mymap", List.of());
+        checkSearch(inv, "Mymap()", List.of());
+
+        // left boundaries, ranking
+        checkSearch(inv, "map", List.of("mapmodule", "mapmodule/mappkg", "mapmodule/mappkg.impl", "mappkg.Map", "mappkg.impl.MyMap",
+                                        "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)", "mappkg.system.property"));
+        checkSearch(inv, "Map", List.of("mappkg.Map", "mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()",
+                                        "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "MAP", List.of());
+        checkSearch(inv, "value", List.of("mappkg.impl.MyMap.OTHER_VALUE", "mappkg.impl.MyMap.some_value"));
+        checkSearch(inv, "VALUE", List.of("mappkg.impl.MyMap.OTHER_VALUE"));
+        checkSearch(inv, "map.other", List.of("mappkg.impl.MyMap.OTHER_VALUE"));
+        checkSearch(inv, "Map.some_", List.of("mappkg.impl.MyMap.some_value"));
+
+        checkSearch(inv, "Mm", List.of());
+        checkSearch(inv, "mym", List.of("mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "imp.mym.mym(", List.of("mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "imp.mym.mym(m", List.of("mappkg.impl.MyMap.MyMap(Map)"));
+
+        // camel case
+        checkSearch(inv, "MM", List.of("mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "MyM", List.of("mappkg.impl.MyMap", "mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "Mym", List.of());
+        checkSearch(inv, "i.MyM.MyM(", List.of("mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "i.MMa.MMa(", List.of("mappkg.impl.MyMap.MyMap()", "mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "i.MyM.MyM(Ma", List.of("mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "i.MMa.MMa(M", List.of("mappkg.impl.MyMap.MyMap(Map)"));
+        checkSearch(inv, "i.Mym.MyM(", List.of());
+        checkSearch(inv, "i.Mym.Ma(", List.of());
+
+        checkSearch(inv, "mapm", List.of("mapmodule"));
+
+        // child entity listing
+        checkSearch(inv, "mapmodule/", List.of("mapmodule/mappkg", "mapmodule/mappkg.impl"));
+        checkSearch(inv, "mapmod/", List.of("mapmodule/mappkg", "mapmodule/mappkg.impl"));
+        checkSearch(inv, "module/", List.of());
+        checkSearch(inv, "le/", List.of());
+        checkSearch(inv, "mapmodule.", List.of());
+        checkSearch(inv, "mapmod.", List.of());
+        checkSearch(inv, "mappkg.", List.of("mapmodule/mappkg.impl", "mappkg.Map", "mappkg.system.property"));
+        checkSearch(inv, "mappkg.", List.of("mapmodule/mappkg.impl", "mappkg.Map", "mappkg.system.property"));
+        checkSearch(inv, "Map.", List.of("mappkg.Map.contains(Object)", "mappkg.Map.get(Object)", "mappkg.Map.iterate()",
+                                         "mappkg.Map.put(Object, Object)", "mappkg.Map.remove(Object)",
+                                         "mappkg.impl.MyMap.contains(Object)", "mappkg.impl.MyMap.get(Object)",
+                                         "mappkg.impl.MyMap.iterate()", "mappkg.impl.MyMap.MyMap()",
+                                         "mappkg.impl.MyMap.MyMap(Map)", "mappkg.impl.MyMap.OTHER_VALUE",
+                                         "mappkg.impl.MyMap.put(Object, Object)", "mappkg.impl.MyMap.remove(Object)",
+                                         "mappkg.impl.MyMap.some_value"));
+        checkSearch(inv, "mym.", List.of("mappkg.impl.MyMap.contains(Object)", "mappkg.impl.MyMap.get(Object)",
+                                         "mappkg.impl.MyMap.iterate()", "mappkg.impl.MyMap.MyMap()",
+                                         "mappkg.impl.MyMap.MyMap(Map)", "mappkg.impl.MyMap.OTHER_VALUE",
+                                         "mappkg.impl.MyMap.put(Object, Object)", "mappkg.impl.MyMap.remove(Object)",
+                                         "mappkg.impl.MyMap.some_value"));
+        checkSearch(inv, "MyMap.i", List.of("mappkg.impl.MyMap.iterate()"));
+
+        // system properties
+        checkSearch(inv, "mappkg.system.property", List.of("mappkg.system.property"));
+        checkSearch(inv, "system.property", List.of("mappkg.system.property"));
+        checkSearch(inv, "property", List.of("mappkg.system.property"));
+        checkSearch(inv, "sys.prop", List.of("mappkg.system.property"));
+        checkSearch(inv, "m.s.p", List.of("mappkg.system.property"));
+        checkSearch(inv, "operty", List.of());
+
+        // search tag
+        checkSearch(inv, "search tag", List.of("search tag"));
+        checkSearch(inv, "search   tag", List.of("search tag"));
+        checkSearch(inv, "search ", List.of("search tag"));
+        checkSearch(inv, "tag", List.of("search tag"));
+        checkSearch(inv, "sea", List.of("search tag"));
+        checkSearch(inv, "ear", List.of());
+    }
+
+
+    @Test
+    public void testPackageSource() throws ScriptException, IOException, NoSuchMethodException {
+        javadoc("-d", "out-overload",
+                "-Xdoclint:none",
+                "-use",
+                "-sourcepath", testSrc,
+                "listpkg");
+        checkExit(Exit.OK);
+
+        Invocable inv = getEngine();
+
+        // exact match, case sensitvity, left boundaries
+        checkSearch(inv, "list", List.of("listpkg", "listpkg.List", "listpkg.ListProvider", "listpkg.MyList",
+                                         "listpkg.MyListFactory", "listpkg.ListProvider.ListProvider()",
+                                         "listpkg.MyListFactory.createList(ListProvider, MyListFactory)",
+                                         "listpkg.ListProvider.makeNewList()",
+                                         "listpkg.MyList.MyList()", "listpkg.MyListFactory.MyListFactory()"));
+        checkSearch(inv, "List", List.of("listpkg.List", "listpkg.ListProvider", "listpkg.MyList",
+                                         "listpkg.MyListFactory", "listpkg.ListProvider.ListProvider()",
+                                         "listpkg.MyListFactory.createList(ListProvider, MyListFactory)",
+                                         "listpkg.ListProvider.makeNewList()",
+                                         "listpkg.MyList.MyList()", "listpkg.MyListFactory.MyListFactory()"));
+
+        // partial match
+        checkSearch(inv, "fact", List.of("listpkg.MyListFactory", "listpkg.MyListFactory.MyListFactory()"));
+        checkSearch(inv, "pro", List.of("listpkg.ListProvider", "listpkg.ListProvider.ListProvider()"));
+        checkSearch(inv, "listpro", List.of("listpkg.ListProvider", "listpkg.ListProvider.ListProvider()"));
+
+        // camel case
+        checkSearch(inv, "l.MLF.cL(LP, MLF)", List.of("listpkg.MyListFactory.createList(ListProvider, MyListFactory)"));
+        checkSearch(inv, "Fact.creaLi(LiPro,MLiFact)", List.of("listpkg.MyListFactory.createList(ListProvider, MyListFactory)"));
+        checkSearch(inv, "(LP,ML", List.of("listpkg.MyListFactory.createList(ListProvider, MyListFactory)"));
+
+        // ranking of overloaded methods JDK-8210683
+        checkSearch(inv, "list.of",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "Li.of",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "li.Li.o",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "l.l.o",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "L.l.o", List.of());
+
+        // whitespace
+        checkSearch(inv, "(e,e,e",
+                List.of("listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "(e, e,e",
+                List.of("listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "(e, e, e",
+                List.of("listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "(e,   e,  e",
+                List.of("listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "(e, e, e ,",
+                List.of("listpkg.List.of(E, E, E, E)", "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "(e   ,   e,  e,",
+                List.of("listpkg.List.of(E, E, E, E)", "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "  listpkg  .list .of ",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, " l. l. o",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "list . of",
+                List.of("listpkg.List.of()", "listpkg.List.of(E)", "listpkg.List.of(E, E)",
+                        "listpkg.List.of(E, E, E)", "listpkg.List.of(E, E, E, E)",
+                        "listpkg.List.of(E, E, E, E, E)", "listpkg.List.of(E...)"));
+        checkSearch(inv, "lis t.of", List.of());
+        checkSearch(inv, "list . of(e,e,e,",
+                List.of("listpkg.List.of(E, E, E, E)", "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "l . o (e,e,e,",
+                List.of("listpkg.List.of(E, E, E, E)", "listpkg.List.of(E, E, E, E, E)"));
+        checkSearch(inv, "search    \tt", List.of("search tag"));
+        checkSearch(inv, "sear ch", List.of());
+        checkSearch(inv, "( e ..", List.of("listpkg.List.of(E...)"));
+        checkSearch(inv, "( i [ ]", List.of("listpkg.Nolist.withArrayArg(int[])"));
+
+        // empty/white space search should not trigger results
+        checkNullSearch(inv, "");
+        checkNullSearch(inv, " ");
+        checkNullSearch(inv, "    ");
+        checkNullSearch(inv, " \t\t ");
+
+
+        // _ word boundaries and case sensitivity
+        checkSearch(inv, "some", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "SOME", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "Some", List.of());
+        checkSearch(inv, "int", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "INT", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "Int", List.of());
+        checkSearch(inv, "int_con", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "INT_CON", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "NT", List.of());
+        checkSearch(inv, "NT_", List.of());
+        checkSearch(inv, "_const", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+        checkSearch(inv, "_CONST", List.of("listpkg.Nolist.SOME_INT_CONSTANT"));
+
+        // Test for all packages, all classes links
+        checkSearch(inv, "all", List.of("All Packages", "All Classes"));
+        checkSearch(inv, "All", List.of("All Packages", "All Classes"));
+        checkSearch(inv, "ALL", List.of());
+
+        // test for generic types, var-arg and array args
+        checkSearch(inv, "(map<string, ? ext collection>)",
+                List.of("listpkg.Nolist.withTypeParams(Map<String, ? extends Collection>)"));
+        checkSearch(inv, "(m<str,? ext coll>",
+                List.of("listpkg.Nolist.withTypeParams(Map<String, ? extends Collection>)"));
+        checkSearch(inv, "(object...", List.of("listpkg.Nolist.withVarArgs(Object...)"));
+        checkSearch(inv, "(obj...", List.of("listpkg.Nolist.withVarArgs(Object...)"));
+        checkSearch(inv, "(e..", List.of("listpkg.List.of(E...)"));
+        checkSearch(inv, "(int[]", List.of("listpkg.Nolist.withArrayArg(int[])"));
+        checkSearch(inv, "(i[]", List.of("listpkg.Nolist.withArrayArg(int[])"));
+    }
+
+    void checkSearch(Invocable inv, String query, List<String> results) throws ScriptException, NoSuchMethodException {
+        checkList((List) inv.invokeFunction("search", query), results);
+    }
+
+    void checkList(List<?> result, List<?> expected) {
+        checking("Checking list: " + result);
+        if (!expected.equals(result)) {
+            failed("Expected: " + expected + ", got: " + result);
+        } else {
+            passed("List matches expected result");
+        }
+    }
+
+    void checkNullSearch(Invocable inv, String query) throws ScriptException, NoSuchMethodException {
+        Object result = inv.invokeFunction("search", query);
+        checking("Checking null result");
+        if (result == null) {
+            passed("Result is null as expected");
+        } else {
+            failed("Expected: null, got: " + result);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/javadoc-search.js	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+var moduleSearchIndex;
+var packageSearchIndex;
+var typeSearchIndex;
+var memberSearchIndex;
+var tagSearchIndex;
+
+var clargs = arguments;
+var search;
+
+function loadIndexFiles(docsPath) {
+    tryLoad(docsPath, "module-search-index.js");
+    tryLoad(docsPath, "package-search-index.js");
+    tryLoad(docsPath, "type-search-index.js");
+    tryLoad(docsPath, "member-search-index.js");
+    tryLoad(docsPath, "tag-search-index.js");
+    load(docsPath + "/search.js");
+}
+
+function tryLoad(docsPath, file) {
+    try {
+        load(docsPath + "/" + file);
+    } catch (e) {
+        print(e);
+    }
+}
+
+var $ = function(f) {
+    if (typeof f === "function") {
+        f();
+    } else {
+        return {
+            val: function() { 
+                return this; 
+            },
+            prop: function() { 
+                return this; 
+            },
+            addClass: function() { 
+                return this; 
+            },    
+            removeClass: function() { 
+                return this; 
+            },
+            on: function() { 
+                return this; 
+            },
+            focus: function() { 
+                return this; 
+            },
+            blur: function() { 
+                return this; 
+            },
+            click: function() { 
+                return this; 
+            },
+            catcomplete: function(o) {
+                o.close = function() {};
+                search = function(term) {
+                    var resultList = null;
+                    o.source({
+                            term: term
+                        },
+                        function(result) {
+                            resultList = renderMenu(result);
+                        }
+                    );
+                    return resultList;
+                };
+                for (var i = 0; i < clargs.length; i++) {
+                    search(clargs[i]);  
+                }
+            },
+            "0": {
+                setSelectionRange: function() { 
+                    return this;
+                }
+            }
+        }
+    }
+};
+
+$.each = function(arr, f) {
+    for (var i = 0; i < arr.length; i++) {
+        f(i, arr[i]);
+    }
+};
+
+$.widget = function(a, b, c) {
+};
+
+$.ui = {
+    autocomplete: {
+        escapeRegex: function(re) {
+            return re.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+        }
+    }
+};
+
+var console = {
+    log: function() {
+        print.apply(this, arguments);
+    }
+};
+
+var renderMenu = function(items) {
+    var result = new java.util.ArrayList();
+    var currentCategory = "";
+    $.each(items, function(index, item) {
+        var li;
+        if (item.l !== noResult.l && item.category !== currentCategory) {
+            // print(item.category);
+            currentCategory = item.category;
+        }
+        result.add(renderItem(item));
+    });
+    return result;
+};
+
+var renderItem = function(item) {
+    var label;
+    if (item.category === catModules) {
+        label = item.l;
+    } else if (item.category === catPackages) {
+        label = (item.m)
+                ? item.m + "/" + item.l
+                : item.l;
+    } else if (item.category === catTypes) {
+        label = (item.p)
+                ? item.p + "." + item.l
+                : item.l;
+    } else if (item.category === catMembers) {
+        label = item.p + "." + item.c + "." + item.l;
+    } else if (item.category === catSearchTags) {
+        label = item.l;
+    } else {
+        label = item.l;
+    }
+    return label;
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/listpkg/List.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,59 @@
+/*
+ * 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 listpkg;
+
+
+/**
+ * Example class containing "list" matching full name.
+ */
+public interface List<E> {
+
+    List add(E e);
+
+    void remove(int i);
+
+    int size();
+
+    static <E> List<E> of() {
+        return null;
+    }
+    static <E> List<E> of(E e1) {
+        return null;
+    }
+    static <E> List<E> of(E e1, E e2) {
+        return null;
+    }
+    static <E> List<E> of(E e1, E e2, E e3) {
+        return null;
+    }
+    static <E> List<E> of(E e1, E e2, E e3, E e4) {
+        return null;
+    }
+    static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
+        return null;
+    }
+    static <E> List<E> of(E... elements) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/listpkg/ListProvider.java	Fri May 03 14:59:32 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 listpkg;
+
+/**
+ * Example class containing "list" matching at beginning of name.
+ */
+public class ListProvider {
+    public ListProvider() {}
+
+    public List makeNewList() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/listpkg/MyList.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,27 @@
+/*
+ * 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 listpkg;
+
+public class MyList implements List {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/listpkg/MyListFactory.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,34 @@
+/*
+ * 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 listpkg;
+
+
+/**
+ * Example class containing "list" matching at camel case word boundaries.
+ */
+public class MyListFactory {
+    public static List createList(ListProvider provider, MyListFactory factory) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/listpkg/Nolist.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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 listpkg;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Example class containing "list" but not matching at any word boundary.
+ *
+ * {@index "search tag"}.
+ */
+public class Nolist {
+
+    public final int SOME_INT_CONSTANT = 0;
+
+    public Nolist() {}
+
+    public void nolist() {}
+
+
+    public static List withTypeParams(Map<String, ? extends Collection> map) {
+        return null;
+    }
+
+    public static List withVarArgs(Object... args) {
+        return null;
+    }
+
+    public static List withArrayArg(int[] args) {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/mapmodule/mappkg/Map.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,34 @@
+/*
+ * 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 mappkg;
+
+import java.util.Iterator;
+
+public interface Map {
+    public void put(Object key, Object value);
+    public boolean contains(Object key);
+    public Object get(Object key);
+    public void remove(Object key);
+    public Iterator<Object> iterate();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/mapmodule/mappkg/impl/MyMap.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,62 @@
+/*
+ * 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 mappkg.impl;
+
+import mappkg.Map;
+import java.util.Iterator;
+
+/**
+ * {@index "search tag"}
+ */
+public class MyMap implements Map {
+
+    /** {@systemProperty mappkg.system.property} */
+    public int some_value;
+    public int OTHER_VALUE;
+
+    public MyMap() {}
+
+    public MyMap(Map map) {}
+
+    @Override
+    public void put(Object key, Object value) {}
+
+    @Override
+    public boolean contains(Object key) {
+        return false;
+    }
+
+    @Override
+    public Object get(Object key) {
+        return null;
+    }
+
+    @Override
+    public void remove(Object key) {}
+
+    @Override
+    public Iterator<Object> iterate() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/mapmodule/module-info.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+module mapmodule {
+    exports mappkg;
+    exports mappkg.impl;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,314 @@
+/*
+ * 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 8219998 8221991
+ * @summary Eliminate inherently singleton lists
+ * @library /tools/lib ../../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.javadoc/jdk.javadoc.internal.api
+ *          jdk.javadoc/jdk.javadoc.internal.tool
+ * @build toolbox.ToolBox toolbox.JavacTask javadoc.tester.*
+ * @run main TestSingletonLists
+ */
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.TreeMap;
+import java.util.function.Function;
+
+import javadoc.tester.HtmlChecker;
+import javadoc.tester.JavadocTester;
+import toolbox.ModuleBuilder;
+import toolbox.ToolBox;
+
+
+public class TestSingletonLists extends JavadocTester {
+    public static void main(String... args) throws Exception {
+        TestSingletonLists tester = new TestSingletonLists();
+        tester.runTests();
+    }
+
+    enum Index  { SINGLE, SPLIT };
+    enum Source { PACKAGES, MODULES };
+
+    final ToolBox tb = new ToolBox();
+
+    public void runTests() throws Exception {
+        for (Source s : Source.values()) {
+            Path src = genSource(s);
+                for (Index i : Index.values()) {
+                    List<String> args = new ArrayList<>();
+                    args.add("-d");
+                    args.add(String.format("out-%s-%s", s, i));
+                    args.add("-use");
+                    if (s != Source.MODULES) {
+                        args.add("-linksource"); // broken, with modules: JDK-8219060
+                    }
+                    if (i == Index.SPLIT) {
+                        args.add("-splitIndex");
+                    }
+                    if (s == Source.PACKAGES) {
+                        args.add("-sourcepath");
+                        args.add(src.toString());
+                        args.add("p1");
+                        args.add("p2");
+                        args.add("p3");
+                    } else {
+                        args.add("--module-source-path");
+                        args.add(src.toString());
+                        args.add("--module");
+                        args.add("mA,mB,mC");
+                    }
+                    javadoc(args.toArray(new String[args.size()]));
+                    checkExit(Exit.OK);
+                    checkLists();
+                }
+        }
+
+        printSummary();
+    }
+
+    Path genSource(Source s) throws IOException {
+        Path src = Path.of("src-" + s);
+        switch (s) {
+            case PACKAGES:
+                for (String p : new String[] { "1", "2", "3" }) {
+                    tb.writeJavaFiles(src, genClasses("p" + p));
+                }
+                break;
+
+            case MODULES:
+                for (String m : new String[] { "A", "B", "C"}) {
+                    ModuleBuilder mb = new ModuleBuilder(tb, "m" + m);
+                    for (String p : new String[] { "1", "2", "3" } ) {
+                        mb.exports("p" + m + p);
+                        mb.classes(genClasses("p" + m + p));
+                    }
+                    mb.write(src);
+                }
+                break;
+        }
+
+        return src;
+    }
+
+
+    String[] genClasses(String pkg) {
+        List<String> list = new ArrayList<>();
+        list.add("package " + pkg + ";");
+        for (int i = 0; i < 3; i++) {
+            list.add(genClass(pkg, i));
+            list.add(genAnno(pkg, i));
+            list.add(genEnum(pkg, i));
+        }
+        return list.toArray(new String[list.size()]);
+    }
+
+    String genClass(String pkg, int index) {
+        String cn = (pkg + "c" + index).toUpperCase();
+        StringBuilder sb = new StringBuilder();
+        int pkgIndex = Character.getNumericValue(pkg.charAt(pkg.length()-1));
+        String pkgdependency = pkg.substring(0, pkg.length()-1) + (pkgIndex == 3 ? 1 : pkgIndex + 1);
+        String enumClassName = pkgdependency.toUpperCase() + "E" + index;
+        sb.append("package ").append(pkg).append(";\n")
+                .append("import " + pkgdependency + ".*;\n")
+                .append("public class ").append(cn).append(" {\n");
+        // fields
+        for (int f = 0; f < 3; f++) {
+            sb.append("public int f").append(f).append(";\n");
+        }
+        // constructors
+        for (int c = 0; c < 3; c++) {
+            sb.append("public ").append(cn).append("(");
+            for (int i = 0; i < c; i++) {
+                sb.append(i == 0 ? "" : ", ").append("int i").append(i);
+            }
+            sb.append(") { }\n");
+        }
+        // methods
+        for (int m = 0; m < 3; m++) {
+            sb.append("public void m").append(m).append("() { }\n");
+        }
+        sb.append("public void n(").append(enumClassName).append(" e){}");
+        sb.append("}\n");
+        return sb.toString();
+    }
+
+    String genAnno(String pkg, int index) {
+        String an = (pkg + "a" + index).toUpperCase();
+        StringBuilder sb = new StringBuilder();
+        sb.append("package ").append(pkg).append(";\n")
+                .append("public @interface ").append(an).append(" {\n");
+        // fields
+        for (int f = 0; f < 3; f++) {
+            sb.append("public static final int f").append(f).append(" = 0;\n");
+        }
+            // values
+        for (int v = 0; v < 6; v++) {
+            sb.append("public int v").append(v).append("()").append(v< 3 ? "" :  " default " + v).append(";\n");
+        }
+        sb.append("}\n");
+        return sb.toString();
+    }
+
+    String genEnum(String pkg, int index) {
+        String en = (pkg + "e" + index).toUpperCase();
+        StringBuilder sb = new StringBuilder();
+        sb.append("package ").append(pkg).append(";\n")
+                .append("public enum ").append(en).append(" {\n");
+             // enum members
+        for (int e = 0; e < 3; e++) {
+            sb.append(e == 0 ? "" : ", ").append("E").append(e);
+        }
+        sb.append(";\n");
+        // fields
+        for (int f = 0; f < 3; f++) {
+            sb.append("public int f").append(f).append(";\n");
+        }
+        // methods
+        for (int m = 0; m < 3; m++) {
+            sb.append("public void m").append(m).append("() { }\n");
+        }
+        sb.append("}\n");
+        return sb.toString();
+    }
+
+    void checkLists() {
+        checking("Check lists");
+        ListChecker c = new ListChecker(out, this::readFile);
+        try {
+            c.checkDirectory(outputDir.toPath());
+            c.report();
+            int errors = c.getErrorCount();
+            if (errors == 0) {
+                passed("No list errors found");
+            } else {
+                failed(errors + " errors found when checking lists");
+            }
+        } catch (IOException e) {
+            failed("exception thrown when reading files: " + e);
+        }
+    }
+
+    /**
+     * A class to check the presence of singleton lists.
+     */
+    public class ListChecker extends HtmlChecker {
+        private int listErrors;
+
+        private boolean inBody;
+        private boolean inNoScript;
+        private Stack<Map<String,Integer>> counts = new Stack<>();
+        private int regionErrors;
+        private String fileName;
+        private boolean inheritanceClass;
+        private List<String> excludeFiles = List.of("overview-tree.html","package-tree.html","module-summary.html");
+
+        ListChecker(PrintStream out, Function<Path,String> fileReader) {
+            super(out, fileReader);
+        }
+
+        protected int getErrorCount() {
+            return errors;
+        }
+
+        @Override
+        public void report() {
+            if (listErrors == 0) {
+                out.println("All lists OK");
+            } else {
+                out.println(listErrors + " list errors");
+            }
+
+            if (regionErrors == 0) {
+                out.println("All regions OK");
+            } else {
+                out.println(regionErrors + " errors in regions");
+            }
+        }
+
+        @Override
+        public void startFile(Path path) {
+            fileName = path.getFileName().toString();
+        }
+
+        @Override
+        public void endFile() {
+        }
+
+        @Override
+        public void docType(String doctype) {
+        }
+
+        @Override
+        public void startElement(String name, Map<String,String> attrs, boolean selfClosing) {
+            switch (name) {
+
+                case "ul": case "ol": case "dl":
+                    counts.push(new TreeMap<>());
+                    break;
+
+                case "li": case "dd": case "dt": {
+                    Map<String, Integer> c = counts.peek();
+                    c.put(name, 1 + c.computeIfAbsent(name, n -> 0));
+                    break;
+                }
+            }
+        }
+
+        @Override
+        public void endElement(String name) {
+            switch (name) {
+                case "ul": case "ol": {
+                    Map<String,Integer> c = counts.pop();
+                    if (c.get("li") == 0) {
+                        error(currFile, getLineNumber(), "empty list");
+                    } else if (c.get("li") == 1 && fileName != null && !excludeFiles.contains(fileName)) {
+                        error(currFile, getLineNumber(), "singleton list");
+                    }
+                    break;
+                }
+
+                case "dl": {
+                    Map<String, Integer> c = counts.pop();
+                    if (c.get("dd") == 0 || c.get("dt") == 0) {
+                        error(currFile, getLineNumber(), "empty list");
+                    }
+                    /*if (c.get("dd") == 1 || c.get("dt") == 1) {
+                        error(currFile, getLineNumber(), "singleton list");
+                    }*/
+                    break;
+                }
+            }
+        }
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java	Fri May 03 14:59:32 2019 -0400
@@ -85,11 +85,14 @@
 
         // make sure the second @summary's content is displayed correctly
         checkOutput("p1/A.html", true,
-             "<li class=\"blockList\">\n"
+             "<section class=\"detail\">\n"
              + "<h3>m3</h3>\n"
+             + "<a id=\"m3()\">\n"
+             + "<!--   -->\n"
+             + "</a>\n"
              + "<pre class=\"methodSignature\">public&nbsp;void&nbsp;m3()</pre>\n"
              + "<div class=\"block\">First sentence  some text maybe second sentence.</div>\n"
-             + "</li>\n"
+             + "</section>\n"
         );
 
         checkOutput("p1/package-summary.html", true,
--- a/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testUseOption/TestUseOption.java	Fri May 03 14:59:32 2019 -0400
@@ -151,7 +151,7 @@
         );
         checkOutput("class-use/UsedInC.html", true,
                 "<li class=\"blockList\">\n"
-                + "<section><a id=\"unnamed.package\">"
+                + "<section class=\"detail\"><a id=\"unnamed.package\">"
         );
         checkOutput("package-use.html", true,
                 "<th class=\"colFirst\" scope=\"row\">"
--- a/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/A11yChecker.java	Fri May 03 14:59:32 2019 -0400
@@ -48,7 +48,7 @@
         super(out, fileReader);
     }
 
-    int getErrorCount() {
+    protected int getErrorCount() {
         return errors;
     }
 
--- a/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlChecker.java	Fri May 03 14:59:32 2019 -0400
@@ -43,15 +43,15 @@
     protected int files;
     protected int errors;
 
-    HtmlChecker(PrintStream out, Function<Path,String> fileReader) {
+    protected HtmlChecker(PrintStream out, Function<Path,String> fileReader) {
         super(out, fileReader);
     }
 
-    void checkDirectory(Path dir) throws IOException {
+    public void checkDirectory(Path dir) throws IOException {
         checkFiles(List.of(dir), false, Collections.emptySet());
     }
 
-    void checkFiles(List<Path> files, boolean skipSubdirs, Set<Path> excludeFiles) throws IOException {
+    public void checkFiles(List<Path> files, boolean skipSubdirs, Set<Path> excludeFiles) throws IOException {
         for (Path file : files) {
             Files.walkFileTree(file, new SimpleFileVisitor<Path>() {
                 int depth = 0;
@@ -86,7 +86,7 @@
         }
     }
 
-    void checkFile(Path file) {
+    protected void checkFile(Path file) {
         try {
             currFile = file.toAbsolutePath().normalize();
             read(file);
@@ -96,9 +96,9 @@
         }
     }
 
-    abstract void report();
+    protected abstract void report();
 
-    int getErrorCount() {
+    protected int getErrorCount() {
         return errors;
     }
 
--- a/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/HtmlParser.java	Fri May 03 14:59:32 2019 -0400
@@ -101,7 +101,7 @@
     }
 
 
-    int getLineNumber() {
+    protected int getLineNumber() {
         return lineNumber;
     }
 
--- a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java	Fri May 03 14:59:32 2019 -0400
@@ -772,7 +772,7 @@
         return readFile(new File(baseDir), fileName);
     }
 
-    private String readFile(Path file) {
+    protected String readFile(Path file) {
         File baseDir;
         if (file.startsWith(outputDir.toPath())) {
             baseDir = outputDir;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/annotations/8218152/MalformedAnnotationProcessorTests.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,186 @@
+/*
+ * 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 8218152
+ * @summary A bad annotation processor class file should fail with an error
+ * @author Steven Groeger
+ *
+ * @library /tools/lib /tools/javac/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask JavacTestingAbstractProcessor
+ * @run main MalformedAnnotationProcessorTests
+ */
+
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import javax.annotation.processing.Processor;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class MalformedAnnotationProcessorTests extends TestRunner{
+    public static void main(String... args) throws Exception {
+        new MalformedAnnotationProcessorTests().runTests(
+                m -> new Object[] { Paths.get(m.getName()) }
+        );
+    }
+
+    private ToolBox tb = new ToolBox();
+
+    public MalformedAnnotationProcessorTests() {
+        super(System.err);
+    }
+
+    @Test
+    public void testBadAnnotationProcessor(Path base) throws Exception {
+        Path apDir = base.resolve("annoprocessor");
+        tb.writeFile(apDir.resolve("META-INF").resolve("services")
+                          .resolve(Processor.class.getCanonicalName()), "BadAnnoProcessor");
+        tb.writeFile(apDir.resolve("BadAnnoProcessor.class"), "badannoprocessor");
+
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src, "package test; public class Test {}");
+
+        List<String> actualErrors =
+                new JavacTask(tb)
+                    .options("-XDrawDiagnostics",
+                             "-classpath", "",
+                             "-sourcepath", src.toString(),
+                             "-processorpath", apDir.toString())
+                    .outdir(classes)
+                    .files(tb.findJavaFiles(src))
+                    .run(Expect.FAIL)
+                    .writeAll()
+                    .getOutputLines(Task.OutputKind.DIRECT);
+
+        System.out.println(actualErrors.get(0));
+        if (!actualErrors.get(0).contains("- compiler.err.proc.cant.load.class: " +
+                                          "Incompatible magic value")) {
+            throw new AssertionError("Unexpected errors reported: " + actualErrors);
+        }
+    }
+
+    @Test
+    public void testMissingAnnotationProcessor(Path base) throws Exception {
+        Path apDir = base.resolve("annoprocessor");
+        tb.writeFile(apDir.resolve("META-INF").resolve("services").resolve(Processor.class.getCanonicalName()),
+                     "MissingAnnoProcessor");
+
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src, "package test; public class Test {}");
+
+        List<String> actualErrors =
+                new JavacTask(tb)
+                    .options("-XDrawDiagnostics",
+                             "-classpath", "",
+                             "-sourcepath", src.toString(),
+                             "-processorpath", apDir.toString())
+                    .outdir(classes)
+                    .files(tb.findJavaFiles(src))
+                    .run(Expect.FAIL)
+                    .writeAll()
+                    .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!actualErrors.get(0).contains("- compiler.err.proc.bad.config.file: " +
+            "javax.annotation.processing.Processor: Provider MissingAnnoProcessor not found")) {
+            throw new AssertionError("Unexpected errors reported: " + actualErrors);
+        }
+    }
+
+    @Test
+    public void testWrongClassFileVersion(Path base) throws Exception {
+        Path apDir = base.resolve("ap");
+        tb.writeFile(apDir.resolve("META-INF").resolve("services").resolve(Processor.class.getCanonicalName()),
+                     "WrongClassFileVersion");
+
+        new JavacTask(tb)
+                .outdir(apDir)
+                .sources("class WrongClassFileVersion {}")
+                .run()
+                .writeAll();
+
+        increaseMajor(apDir.resolve("WrongClassFileVersion.class"), 1);
+
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src, "package test; public class Test {}");
+
+        List<String> actualErrors =
+                new JavacTask(tb)
+                    .options("-XDrawDiagnostics",
+                             "-classpath", "",
+                             "-sourcepath", src.toString(),
+                             "-processorpath", apDir.toString())
+                    .outdir(classes)
+                    .files(tb.findJavaFiles(src))
+                    .run(Expect.FAIL)
+                    .writeAll()
+                    .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!actualErrors.get(0).contains("- compiler.err.proc.cant.load.class: " +
+            "WrongClassFileVersion has been compiled by a more recent version")) {
+            throw new AssertionError("Unexpected errors reported: " + actualErrors);
+        }
+    }
+
+    // Increase class file cfile's major version by delta
+    // (note: based on test/langtools/tools/javac/6330997/T6330997.java)
+    static void increaseMajor(Path cfile, int delta) {
+        try (RandomAccessFile cls =
+             new RandomAccessFile(cfile.toFile(), "rw");
+             FileChannel fc = cls.getChannel()) {
+            ByteBuffer rbuf = ByteBuffer.allocate(2);
+            fc.read(rbuf, 6);
+            ByteBuffer wbuf = ByteBuffer.allocate(2);
+            wbuf.putShort(0, (short)(rbuf.getShort(0) + delta));
+            fc.write(wbuf, 6);
+            fc.force(false);
+        } catch (Exception e){
+            throw new RuntimeException("Failed: unexpected exception");
+         }
+     }
+}
--- a/test/langtools/tools/javac/api/file/SJFM_TestBase.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/tools/javac/api/file/SJFM_TestBase.java	Fri May 03 14:59:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, 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
@@ -160,7 +160,7 @@
     List<Path> getTestZipPaths() throws IOException {
         if (zipfs == null) {
             Path testZip = createSourceZip();
-            zipfs = FileSystems.newFileSystem(testZip, null);
+            zipfs = FileSystems.newFileSystem(testZip);
             closeables.add(zipfs);
             zipPaths = Files.list(zipfs.getRootDirectories().iterator().next())
                 .filter(p -> p.getFileName().toString().endsWith(".java"))
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Fri May 03 14:59:32 2019 -0400
@@ -35,6 +35,7 @@
 compiler.err.proc.no.service                            # JavacProcessingEnvironment: no service loader available
 compiler.err.proc.processor.bad.option.name             # cannot happen? masked by javac.err.invalid.A.key
 compiler.err.proc.service.problem                       # JavacProcessingEnvironment: catch Throwable from service loader
+compiler.err.proc.cant.load.class                       # JavacProcessingEnvironment: cant load the class/jar file
 compiler.err.signature.doesnt.match.intf                # UNUSED
 compiler.err.signature.doesnt.match.supertype           # UNUSED
 compiler.err.source.cant.overwrite.input.file
--- a/test/langtools/tools/javac/modules/ContainsTest.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/langtools/tools/javac/modules/ContainsTest.java	Fri May 03 14:59:32 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
@@ -129,7 +129,7 @@
         Path c = src.resolve("p/C.java");
         Path x = base.resolve("src2/p/C.java");
 
-        try (FileSystem jarFS = FileSystems.newFileSystem(jar, null);
+        try (FileSystem jarFS = FileSystems.newFileSystem(jar);
                 StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
             Path jarRoot = jarFS.getRootDirectories().iterator().next();
             fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jarRoot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/TestRepeatedSupportedItems.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8146726
+ * @summary Test that warnings about repeated supported options and annotation types output as expected.
+ * @compile TestRepeatedSupportedItems.java
+ * @compile/ref=au_8.out       -XDrawDiagnostics -processor TestRepeatedSupportedItems -proc:only  -source 8 -Xlint:-options TestRepeatedSupportedItems.java
+ * @compile/ref=au_current.out -XDrawDiagnostics -processor TestRepeatedSupportedItems -proc:only            -Xlint:-options TestRepeatedSupportedItems.java
+ */
+
+import java.lang.annotation.*;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A warning should be issued by the logic in
+ * javax.annotation.processing.AbstractProcessor for the repeated
+ * information.  The "Foo" option warnings occur regardless of source
+ * level. The number of times the Baz annotation type is repeated
+ * depends on whether or not the source level supports modules.
+ */
+@SupportedAnnotationTypes({"foo/Baz", "foo/Baz", "bar/Baz", "Baz", "Baz"})
+@SupportedOptions({"Foo", "Foo"})
+@Baz
+public class TestRepeatedSupportedItems extends AbstractProcessor {
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    public boolean process(Set<? extends TypeElement> annotations,
+                           RoundEnvironment roundEnvironment) {
+        return true;
+    }
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Baz {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/au_8.out	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,4 @@
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate option value ``Foo'' for processor TestRepeatedSupportedItems in its @SupportedOptionsannotation.
+3 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/au_current.out	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,4 @@
+- compiler.warn.proc.messager: Duplicate annotation type ``foo/Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate option value ``Foo'' for processor TestRepeatedSupportedItems in its @SupportedOptionsannotation.
+3 warnings
--- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java	Fri May 03 14:59:32 2019 -0400
@@ -184,15 +184,15 @@
 
 
     /**
-     * Run Java inside the docker image with specified parameters and options.
+     * Build the docker command to run java inside a container
      *
      * @param DockerRunOptions optins for running docker
      *
-     * @return output of the run command
+     * @return command
      * @throws Exception
      */
-    public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception {
-        ArrayList<String> cmd = new ArrayList<>();
+    public static List<String> buildJavaCommand(DockerRunOptions opts) throws Exception {
+        List<String> cmd = new ArrayList<>();
 
         cmd.add(DOCKER_COMMAND);
         cmd.add("run");
@@ -213,7 +213,19 @@
         cmd.add(opts.classToRun);
         cmd.addAll(opts.classParams);
 
-        return execute(cmd);
+        return cmd;
+    }
+
+    /**
+     * Run Java inside the docker image with specified parameters and options.
+     *
+     * @param DockerRunOptions optins for running docker
+     *
+     * @return output of the run command
+     * @throws Exception
+     */
+    public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception {
+        return execute(buildJavaCommand(opts));
     }
 
 
--- a/test/lib/jdk/test/lib/net/URIBuilder.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/lib/jdk/test/lib/net/URIBuilder.java	Fri May 03 14:59:32 2019 -0400
@@ -61,6 +61,12 @@
         return this;
     }
 
+    public URIBuilder host(InetAddress address) {
+        String hostaddr = address.isAnyLocalAddress()
+               ? "localhost" : address.getHostAddress();
+        return host(hostaddr);
+    }
+
     public URIBuilder loopback() {
         return host(InetAddress.getLoopbackAddress().getHostAddress());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/java/lang/ArrayFiddle.java	Fri May 03 14:59:32 2019 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.bench.java.lang;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Explores the cost of copying the contents of one array to another, as is
+ * commonly seen in collection classes that need to resize their backing
+ * array, like ArrayList.
+ *
+ * We have multiple variations on copying, and we explore the cost of
+ * clearing the old array, which might help for generational GCs.
+ *
+ * Benchmarks the operations in the ancient
+ * JDK-6428387: array clone() much slower than Arrays.copyOf
+ *
+ * 2019 results on x86:
+ *
+ * The "simple" benchmarks below have the same performance, except that
+ * simple_copyLoop is surprisingly 5x slower.  The array copying intrinsics
+ * are very effective and a naive loop does not get optimized the same way.
+ * OTOH there is no intrinsic for Arrays.fill but the naive array zeroing loop
+ * *does* get optimized to something a little faster than than arraycopy.
+ *
+ * System.arraycopy and Arrays.fill have such outstanding performance that
+ * one should use them to replace handwritten loops whenever possible.
+ *
+ * This benchmark is great for measuring cache effects, e.g. size=10^6 has 5x
+ * the per-element cost of size=10^3 (See "The Myth of RAM".)
+ *
+ * (cd $(hg root) && for size in 3 16 999 999999; do make test TEST="micro:java.lang.ArrayFiddle" MICRO="FORK=2;WARMUP_ITER=4;ITER=4;OPTIONS=-opi $size -p size=$size" |& perl -ne 'print if /^Benchmark/ .. /^Finished running test/'; done)
+ */
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Benchmark)
+public class ArrayFiddle {
+    @Param("999")
+    public int size;
+
+    public int largerSize;
+    public Object[] data;
+    public Object[] copy;
+
+    @Setup
+    public void setup() {
+        largerSize = size + (size >> 1);
+
+        data = new Object[size];
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        for (int i = data.length; i--> 0; )
+            data[i] = rnd.nextInt(256);
+
+        copy = data.clone();
+    }
+
+    // --- "simple" benchmarks just make an array clone
+
+    @Benchmark
+    public Object[] simple_clone() {
+        return data.clone();
+    }
+
+    @Benchmark
+    public Object[] simple_copyOf() {
+        return Arrays.copyOf(data, data.length);
+    }
+
+    @Benchmark
+    public Object[] simple_arraycopy() {
+        Object[] out = new Object[data.length];
+        System.arraycopy(data, 0, out, 0, data.length);
+        return out;
+    }
+
+    @Benchmark
+    public Object[] simple_copyLoop() {
+        final Object[] data = this.data;
+        int len = data.length;
+        Object[] out = new Object[len];
+        for (int i = 0; i < len; i++)
+            out[i] = data[i];
+        return out;
+    }
+
+    // --- "grow" benchmarks have an output array that is larger
+
+    private Object[] input_array() {
+        System.arraycopy(data, 0, copy, 0, size);
+        return copy;
+    }
+
+    @Benchmark
+    public Object[] grow_copyLoop() {
+        Object[] in = input_array();
+        Object[] out = new Object[largerSize];
+        for (int i = 0, len = in.length; i < len; i++)
+            out[i] = in[i];
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_copyZeroLoop() {
+        Object[] in = input_array();
+        Object[] out = new Object[largerSize];
+        for (int i = 0, len = in.length; i < len; i++) {
+            out[i] = in[i];
+            in[i] = null;
+        }
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_arraycopy() {
+        Object[] in = input_array();
+        Object[] out = new Object[largerSize];
+        System.arraycopy(in, 0, out, 0, size);
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_arraycopy_fill() {
+        Object[] in = input_array();
+        Object[] out = new Object[largerSize];
+        System.arraycopy(in, 0, out, 0, size);
+        Arrays.fill(in, null);
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_arraycopy_zeroLoop() {
+        Object[] in = input_array();
+        Object[] out = new Object[largerSize];
+        System.arraycopy(in, 0, out, 0, size);
+        for (int i = 0, len = in.length; i < len; i++)
+            in[i] = null;
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_copyOf() {
+        Object[] in = input_array();
+        Object[] out = Arrays.copyOf(in, largerSize);
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_copyOf_fill() {
+        Object[] in = input_array();
+        Object[] out = Arrays.copyOf(in, largerSize);
+        Arrays.fill(in, null);
+        return out;
+    }
+
+    @Benchmark
+    public Object[] grow_copyOf_zeroLoop() {
+        Object[] in = input_array();
+        Object[] out = Arrays.copyOf(in, largerSize);
+        for (int i = 0, len = in.length; i < len; i++)
+            in[i] = null;
+        return out;
+    }
+
+}
--- a/test/micro/org/openjdk/bench/java/lang/StringConcat.java	Fri May 03 11:28:14 2019 -0700
+++ b/test/micro/org/openjdk/bench/java/lang/StringConcat.java	Fri May 03 14:59:32 2019 -0400
@@ -26,6 +26,7 @@
 import org.openjdk.jmh.annotations.BenchmarkMode;
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
 import org.openjdk.jmh.annotations.Scope;
 import org.openjdk.jmh.annotations.Setup;
 import org.openjdk.jmh.annotations.State;
@@ -42,7 +43,8 @@
 @State(Scope.Thread)
 public class StringConcat {
 
-    public int intValue = 4711;
+    @Param("4711")
+    public int intValue;
 
     public String stringValue = String.valueOf(intValue);
 
@@ -78,11 +80,26 @@
     }
 
     @Benchmark
+    public String concatMix4String() {
+        // Investigate "profile pollution" between shared LFs that might eliminate some JIT optimizations
+        String s1 = "string" + stringValue + stringValue + stringValue + stringValue;
+        String s2 = "string" + stringValue + "string" + stringValue + stringValue + stringValue;
+        String s3 = stringValue + stringValue + "string" + stringValue + "string" + stringValue + "string";
+        String s4 = "string" + stringValue + "string" + stringValue + "string" + stringValue + "string" + stringValue + "string";
+        return s1 + s2 + s3 + s4;
+    }
+
+    @Benchmark
     public String concatConst4String() {
         return "string" + stringValue + stringValue + stringValue + stringValue;
     }
 
     @Benchmark
+    public String concat4String() {
+        return stringValue + stringValue + stringValue + stringValue;
+    }
+
+    @Benchmark
     public String concatConst2String() {
         return "string" + stringValue + stringValue;
     }
@@ -98,6 +115,11 @@
     }
 
     @Benchmark
+    public String concat6String() {
+        return stringValue + stringValue + stringValue + stringValue + stringValue + stringValue;
+    }
+
+    @Benchmark
     public String concatConst6Object() {
         return "string" + objectValue + objectValue + objectValue + objectValue + objectValue + objectValue;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/java/lang/StringEquals.java	Fri May 03 14:59:32 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.
+ */
+package org.openjdk.bench.java.lang;
+
+import org.openjdk.jmh.annotations.*;
+import java.util.concurrent.TimeUnit;
+
+/*
+ * This benchmark naively explores String::equals performance
+ */
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Benchmark)
+public class StringEquals {
+
+    public String test = new String("0123456789");
+    public String test2 = new String("tgntogjnrognagronagroangroarngorngaorng");
+    public String test3 = new String(test); // equal to test, but not same
+    public String test4 = new String("0123\u01FF");
+    public String test5 = new String(test4); // equal to test4, but not same
+    public String test6 = new String("0123456780");
+    public String test7 = new String("0123\u01FE");
+
+    @Benchmark
+    public boolean different() {
+        return test.equals(test2);
+    }
+
+    @Benchmark
+    public boolean equal() {
+        return test.equals(test3);
+    }
+
+    @Benchmark
+    public boolean almostEqual() {
+        return test.equals(test6);
+    }
+
+    @Benchmark
+    public boolean almostEqualUTF16() {
+        return test4.equals(test7);
+    }
+
+    @Benchmark
+    public boolean differentCoders() {
+        return test.equals(test4);
+    }
+
+    @Benchmark
+    public boolean equalsUTF16() {
+        return test5.equals(test4);
+    }
+}
+