Merge niosocketimpl-branch
authoralanb
Fri, 03 May 2019 08:26:44 +0100
branchniosocketimpl-branch
changeset 57347 16c087c9103e
parent 57344 8b621b0d921c (current diff)
parent 54696 0907dce4b90e (diff)
child 57353 ddfb12ab18e1
Merge
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/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
src/java.base/share/classes/java/net/HttpConnectSocketImpl.java
src/java.base/share/classes/java/net/ServerSocket.java
src/java.base/share/classes/java/net/Socket.java
src/java.base/share/classes/java/net/SocketImpl.java
src/java.base/share/classes/java/net/SocksSocketImpl.java
src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
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
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/net/SocketOption/OptionsTest.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
--- a/.hgtags	Tue Apr 30 19:34:13 2019 +0100
+++ b/.hgtags	Fri May 03 08:26:44 2019 +0100
@@ -556,3 +556,4 @@
 9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16
 93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17
 bebb82ef3434a25f8142edafec20165f07ac562d jdk-13+18
+a43d6467317d8f1e160f67aadec37919c9d64443 jdk-13+19
--- a/doc/building.html	Tue Apr 30 19:34:13 2019 +0100
+++ b/doc/building.html	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/doc/building.md	Fri May 03 08:26:44 2019 +0100
@@ -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/autoconf/flags-cflags.m4	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/autoconf/flags-cflags.m4	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/autoconf/hotspot.m4	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/autoconf/toolchain_windows.m4	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/conf/jib-profiles.js	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/data/lsrdata/language-subtag-registry.txt	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/make/lib/Lib-jdk.jdwp.agent.gmk	Fri May 03 08:26:44 2019 +0100
@@ -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/src/hotspot/.mx.jvmci/suite.py	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/.mx.jvmci/suite.py	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Fri May 03 08:26:44 2019 +0100
@@ -14046,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/globals_aarch64.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/arm/globals_arm.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/ppc/globals_ppc.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/s390/globals_s390.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/sparc/globals_sparc.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/x86/globals_x86.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/cpu/zero/globals_zero.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/linux/os_linux.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/os/linux/os_linux.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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_cpu/linux_x86/os_linux_x86.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
--- a/src/hotspot/share/aot/aotLoader.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/aot/aotLoader.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
--- a/src/hotspot/share/classfile/javaClasses.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Fri May 03 08:26:44 2019 +0100
@@ -2607,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Fri May 03 08:26:44 2019 +0100
@@ -1368,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/metadataOnStackMark.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/systemDictionary.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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
@@ -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);
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
@@ -215,9 +214,6 @@
   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*/
 
 
@@ -236,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
   };
 
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/nmethod.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/code/nmethod.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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,
@@ -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
 )
 {
@@ -493,12 +503,19 @@
   // create nmethod
   nmethod* nm = NULL;
   { 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
 }
 
@@ -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() {
@@ -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
@@ -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");
   }
@@ -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();
@@ -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
-  {
-    MutexLocker 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.
-  MutexLocker 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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/code/nmethod.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/compiler/abstractCompiler.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/abstractCompiler.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/abstractCompiler.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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(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(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();
     }
   }
 
@@ -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()) {
--- a/src/hotspot/share/compiler/compileTask.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/compileTask.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/compilerDefinitions.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/disassembler.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/compiler/disassembler.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/gc/cms/cmsArguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/cmsArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/cmsArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/compactibleFreeListSpace.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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]);
     )
@@ -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();
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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;
@@ -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 --
@@ -5258,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));
     }
   }
 
@@ -5643,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;
@@ -7526,7 +7534,7 @@
   }
 
   ConcurrentMarkSweepThread::synchronize(true);
-  _freelistLock->lock();
+  _freelistLock->lock_without_safepoint_check();
   _bitMap->lock()->lock_without_safepoint_check();
   _collector->startTimer();
 }
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/parNewGeneration.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/cms/yieldingWorkgroup.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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");
 }
--- a/src/hotspot/share/gc/epsilon/epsilonArguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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);
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/g1Arguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1Arguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1Arguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
@@ -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;
 }
@@ -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 {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Fri May 03 08:26:44 2019 +0100
@@ -338,9 +338,9 @@
   }
 
   {
-    MutexLocker x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
+    MonitorLocker ml(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
     while (scan_in_progress()) {
-      RootRegionScan_lock->wait_without_safepoint_check();
+      ml.wait();
     }
   }
   return true;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp	Fri May 03 08:26:44 2019 +0100
@@ -407,9 +407,9 @@
   // below while the world is otherwise stopped.
   assert(!in_progress(), "should have been cleared");
 
-  MutexLocker x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(CGC_lock, Mutex::_no_safepoint_check_flag);
   while (!started() && !should_terminate()) {
-    CGC_lock->wait_without_safepoint_check();
+    ml.wait();
   }
 
   if (started()) {
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Fri May 03 08:26:44 2019 +0100
@@ -59,9 +59,9 @@
 }
 
 void G1ConcurrentRefineThread::wait_for_completed_buffers() {
-  MutexLocker x(_monitor, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag);
   while (!should_terminate() && !is_active()) {
-    _monitor->wait_without_safepoint_check();
+    ml.wait();
   }
 }
 
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/g1GCPhaseTimes.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapYoungGenSizer.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/g1Policy.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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");
@@ -61,7 +64,7 @@
   if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
     MonitorLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
     while ((uint)_n_workers_discovered_strong_classes != n_workers()) {
-      _lock.wait_without_safepoint_check(0);
+      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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/g1VMOperations.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp	Fri May 03 08:26:44 2019 +0100
@@ -191,10 +191,10 @@
       JavaThread* jt = (JavaThread*)thr;
       ThreadToNativeFromVM native(jt);
 
-      MutexLocker 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_without_safepoint_check();
+        ml.wait();
       }
     }
   }
--- a/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1YoungGenSizer.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp	Fri May 03 08:26:44 2019 +0100
@@ -47,10 +47,10 @@
 }
 
 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
-  MutexLocker x(&_monitor, Mutex::_no_safepoint_check_flag);
+  MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
   if (!should_terminate()) {
     uintx waitms = G1ConcRefinementServiceIntervalMillis;
-    _monitor.wait_without_safepoint_check(waitms);
+    ml.wait(waitms);
   }
 }
 
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/parallel/adjoiningGenerations.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerationsForHeteroHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/asPSOldGen.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/asPSYoungGen.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/gcTaskManager.cpp	Fri May 03 08:26:44 2019 +0100
@@ -654,7 +654,7 @@
 GCTask* GCTaskManager::get_task(uint which) {
   GCTask* result = NULL;
   // Grab the queue lock.
-  MutexLocker 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_without_safepoint_check(0);
+    ml.wait(0);
   }
   // We've reacquired the queue lock here.
   // Figure out which condition caused us to exit the loop above.
@@ -872,15 +872,15 @@
   log_trace(gc, task)("[" INTPTR_FORMAT "] IdleGCTask:::do_it() should_wait: %s",
       p2i(this), wait_helper->should_wait() ? "true" : "false");
 
-  MutexLocker 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_without_safepoint_check(0);
+    ml.wait(0);
   }
   manager->decrement_idle_workers();
 
@@ -991,7 +991,7 @@
   }
   {
     // Grab the lock and check again.
-    MutexLocker 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_without_safepoint_check(0);
+      ml.wait(0);
     }
     // Reset the flag in case someone reuses this task.
     if (reset) {
--- a/src/hotspot/share/gc/parallel/generationSizer.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/parallelArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/pcTasks.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psOldGen.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psTasks.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psTasks.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/serialArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/serialArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/serialHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/ageTable.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -44,7 +44,6 @@
 
 class AdaptiveSizePolicy;
 class BarrierSet;
-class CollectorPolicy;
 class GCHeapSummary;
 class GCTimer;
 class GCTracer;
@@ -388,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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/concurrentGCPhaseManager.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/gcArguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcConfiguration.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcLocker.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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(),
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/generation.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/generationSpec.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/generationSpec.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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) {
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/parallelCleaning.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/threadLocalAllocBuffer.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shared/workgroup.cpp	Fri May 03 08:26:44 2019 +0100
@@ -200,7 +200,7 @@
   }
 
   void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) {
-    MutexLocker 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_without_safepoint_check();
+      ml.wait();
     }
 
     _task        = NULL;
@@ -367,7 +367,7 @@
 }
 
 bool WorkGangBarrierSync::enter() {
-  MutexLocker 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
@@ -387,10 +387,10 @@
     // 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_without_safepoint_check();
+      ml.wait();
     }
   }
   return !aborted();
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/shenandoahCollectorPolicy.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/shenandoahHeap.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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();
 
@@ -1159,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) {
@@ -1489,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();
@@ -1542,6 +1545,7 @@
       }
 
       if (ShenandoahVerify) {
+        verifier()->verify_roots_no_forwarded();
         verifier()->verify_during_evacuation();
       }
     } else {
@@ -2178,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);
 
@@ -2188,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/shenandoahUtils.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/zArguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/z/zArguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -24,12 +24,16 @@
 #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"
 
+void ZArguments::initialize_alignments() {
+  SpaceAlignment = ZGranuleSize;
+  HeapAlignment = SpaceAlignment;
+}
+
 void ZArguments::initialize() {
   GCArguments::initialize();
 
@@ -101,5 +105,5 @@
 }
 
 CollectedHeap* ZArguments::create_heap() {
-  return create_heap_with_policy<ZCollectedHeap, ZCollectorPolicy>();
+  return new ZCollectedHeap();
 }
--- a/src/hotspot/share/gc/z/zArguments.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/z/zArguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -40,8 +40,7 @@
   return (ZCollectedHeap*)heap;
 }
 
-ZCollectedHeap::ZCollectedHeap(ZCollectorPolicy* policy) :
-    _collector_policy(policy),
+ZCollectedHeap::ZCollectedHeap() :
     _soft_ref_policy(),
     _barrier_set(),
     _initialize(&_barrier_set),
@@ -80,10 +79,6 @@
   _stat->stop();
 }
 
-CollectorPolicy* ZCollectedHeap::collector_policy() const {
-  return _collector_policy;
-}
-
 SoftRefPolicy* ZCollectedHeap::soft_ref_policy() {
   return &_soft_ref_policy;
 }
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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,14 +54,13 @@
 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;
--- a/src/hotspot/share/gc/z/zCollectorPolicy.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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/zStat.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/gc/z/zStat.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/jfr/leakprofiler/chains/rootSetClosure.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/sampling/jfrThreadSampler.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri May 03 08:26:44 2019 +0100
@@ -395,9 +395,9 @@
   JfrThreadLocal* const tl = thread->jfr_thread_local();
   tl->set_trace_block();
   {
-    MutexLocker 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_without_safepoint_check();
+      ml.wait();
     }
     tl->clear_trace_block();
   }
--- a/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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!");
-  MutexLocker 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();
   }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jniAccessMark.inline.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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,163 @@
       } 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);
   }
-  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 +690,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,34 +720,47 @@
   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,
     {
       MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       CodeCache::print_summary(&s, false);
@@ -698,130 +769,115 @@
     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.
-        MutexLocker 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 +902,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 +940,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 +960,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 +977,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 +1029,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 +1099,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 +1127,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 +1161,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 +1191,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 +1204,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 +1237,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 +1260,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 +1280,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 +1321,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 +1339,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 +1375,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 +1393,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 +1449,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 +1506,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 +1628,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 +2281,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 +2381,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 +2405,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 +2434,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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)                                  \
@@ -544,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/memory/allocation.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/universe.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/memory/universe.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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) {
--- a/src/hotspot/share/memory/universe.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/memory/universe.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/method.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/oops/method.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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());
--- a/src/hotspot/share/oops/methodData.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/oops/methodData.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/oops/methodData.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/opto/chaitin.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/opto/ifnode.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/memnode.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/opto/memnode.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/parse1.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/opto/parse1.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/prims/jni.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/jni.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/jvmtiEnvBase.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/jvmtiRedefineClasses.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/nativeLookup.hpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/nativeLookup.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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() {
--- a/src/hotspot/share/prims/whitebox.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/prims/whitebox.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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
--- a/src/hotspot/share/runtime/arguments.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/arguments.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/deoptimization.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/frame.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/globals.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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)                                                      \
@@ -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/init.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/init.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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;
--- a/src/hotspot/share/runtime/java.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/java.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/javaCalls.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/mutex.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/mutex.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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);
@@ -154,14 +160,12 @@
 #endif // ASSERT
 
 bool Monitor::wait_without_safepoint_check(long timeout) {
-  // Make sure safepoint checking is used properly.
-  assert(_safepoint_check_required != Monitor::_safepoint_check_always,
-         "This lock should always have a safepoint check: %s", name());
+  Thread* const self = Thread::current();
+  check_safepoint_state(self, false);
 
   // timeout is in milliseconds - with zero meaning never timeout
   assert(timeout >= 0, "negative timeout");
 
-  Thread * const self = Thread::current();
   assert_owner(self);
   assert_wait_lock_state(self);
 
@@ -174,14 +178,12 @@
 }
 
 bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
-  // Make sure safepoint checking is used properly.
-  assert(_safepoint_check_required != Monitor::_safepoint_check_never,
-         "This lock should never have a safepoint check: %s", name());
+  Thread* const self = Thread::current();
+  check_safepoint_state(self, true);
 
   // timeout is in milliseconds - with zero meaning never timeout
   assert(timeout >= 0, "negative timeout");
 
-  Thread* const self = Thread::current();
   assert_owner(self);
 
   // Safepoint checking logically implies java_thread
@@ -273,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!");
@@ -281,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
 }
 
@@ -291,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/mutex.hpp	Fri May 03 08:26:44 2019 +0100
@@ -92,6 +92,7 @@
   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;
 
@@ -101,28 +102,39 @@
     _as_suspend_equivalent_flag = true
   };
 
+  // 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
   };
 
-  // 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.
   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;)
@@ -159,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
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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
@@ -229,6 +235,7 @@
 
 // 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 MonitorLocker: public MutexLocker {
   Mutex::SafepointCheckFlag _flag;
@@ -236,35 +243,31 @@
   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");
   }
 
   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(long timeout = 0,
             bool as_suspend_equivalent = !Mutex::_as_suspend_equivalent_flag) {
-    if (_mutex != NULL) {
-      if (_flag == Mutex::_safepoint_check_flag) {
-        return _mutex->wait(timeout, as_suspend_equivalent);
-      } else {
-        return _mutex->wait_without_safepoint_check(timeout);
-      }
+    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 (_mutex != NULL) {
-      _mutex->notify_all();
-    }
+    _mutex->notify_all();
   }
 
   void notify() {
-    if (_mutex != NULL) {
-      _mutex->notify();
-    }
+    _mutex->notify();
   }
 };
 
--- a/src/hotspot/share/runtime/sweeper.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/sweeper.cpp	Fri May 03 08:26:44 2019 +0100
@@ -341,9 +341,9 @@
   while (true) {
     {
       ThreadBlockInVM tbivm(JavaThread::current());
-      MutexLocker 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_without_safepoint_check(wait_time);
+      timeout = waiter.wait(wait_time);
     }
     if (!timeout) {
       possibly_sweep();
@@ -369,7 +369,7 @@
   */
 void NMethodSweeper::force_sweep() {
   ThreadBlockInVM tbivm(JavaThread::current());
-  MutexLocker 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_without_safepoint_check(1000);
+    waiter.wait(1000);
   }
 }
 
--- a/src/hotspot/share/runtime/thread.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/thread.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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"
@@ -794,14 +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
-      if (Thread::current()->is_Java_thread()) {
-        SR_lock()->wait(i * delay);
-      } else {
-        SR_lock()->wait_without_safepoint_check(i * delay);
-      }
+      ml.wait(i * delay);
 
       is_suspended = is_ext_suspend_completed(true /* called_by_wait */,
                                               delay, bits);
@@ -1405,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.
-  MutexLocker 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
@@ -1425,7 +1422,7 @@
   jlong time_before_loop = os::javaTimeNanos();
 
   while (true) {
-    bool timedout = PeriodicTask_lock->wait_without_safepoint_check(remaining);
+    bool timedout = ml.wait(remaining);
     jlong now = os::javaTimeNanos();
 
     if (remaining == 0) {
@@ -1548,12 +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(0, Mutex::_as_suspend_equivalent_flag);
+    mu.wait(0, Mutex::_as_suspend_equivalent_flag);
   }
 }
 
@@ -1578,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]);
         }
       }
     }
@@ -1630,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");
@@ -2424,7 +2421,7 @@
          (is_Java_thread() && !((JavaThread*)this)->has_last_Java_frame()),
          "must have walkable stack");
 
-  MutexLocker 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");
@@ -2452,7 +2449,7 @@
 
     // _ext_suspended flag is cleared by java_resume()
     while (is_ext_suspended()) {
-      this->SR_lock()->wait_without_safepoint_check();
+      ml.wait();
     }
   }
   return ret;
@@ -2526,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);)
 }
 
@@ -3859,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();
       }
     }
   }
@@ -3940,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
@@ -3992,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
@@ -4292,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);
   }
@@ -4340,11 +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(0, Mutex::_as_suspend_equivalent_flag);
+      nu.wait(0, Mutex::_as_suspend_equivalent_flag);
   }
 
   EventShutdown e;
@@ -4480,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");
 
@@ -4508,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/thread.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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
 
@@ -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
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/thread.inline.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/threadHeapSampler.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/tieredThresholdPolicy.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/vmOperations.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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++;
 
-    MutexLocker ml(&timer, Mutex::_no_safepoint_check_flag);
-    timer.wait_without_safepoint_check(10);
+    MonitorLocker ml(&timer, Mutex::_no_safepoint_check_flag);
+    ml.wait(10);
   }
 }
 
--- a/src/hotspot/share/runtime/vmThread.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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().
-    MutexLocker 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
@@ -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.
-  { MutexLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
+  { MonitorLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
     while(!VMThread::is_terminated()) {
-        _terminate_lock->wait_without_safepoint_check();
+      ml.wait();
     }
   }
 }
@@ -476,8 +476,8 @@
     // Wait for VM operation
     //
     // use no_safepoint_check to get lock without attempting to "sneak"
-    { MutexLocker mu_queue(VMOperationQueue_lock,
-                           Mutex::_no_safepoint_check_flag);
+    { MonitorLocker mu_queue(VMOperationQueue_lock,
+                             Mutex::_no_safepoint_check_flag);
 
       // Look for new operation
       assert(_cur_vm_operation == NULL, "no current one should be executing");
@@ -494,7 +494,7 @@
       while (!should_terminate() && _cur_vm_operation == NULL) {
         // wait with a timeout to guarantee safepoints at regular intervals
         bool timedout =
-          VMOperationQueue_lock->wait_without_safepoint_check(GuaranteedSafepointInterval);
+          mu_queue.wait(GuaranteedSafepointInterval);
 
         // Support for self destruction
         if ((SelfDestructTimer != 0) && !VMError::is_error_reported() &&
@@ -623,10 +623,8 @@
     }
 
     //
-    //  Notify (potential) waiting Java thread(s) - lock without safepoint
-    //  check so that sneaking is not possible
-    { MutexLocker 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();
     }
 
@@ -718,13 +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) {
-        if (t->is_Java_thread()) {
-          VMOperationRequest_lock->wait();
-        } else {
-          VMOperationRequest_lock->wait_without_safepoint_check();
-        }
+        ml.wait();
       }
     }
 
--- a/src/hotspot/share/utilities/bitMap.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/utilities/bitMap.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/utilities/bitMap.hpp	Fri May 03 08:26:44 2019 +0100
@@ -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/decoder.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/utilities/decoder.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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() :
-  MutexLocker(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;
-  MutexLocker 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;
-  MutexLocker 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;
-  MutexLocker 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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/hotspot/share/utilities/decoder.hpp	Fri May 03 08:26:44 2019 +0100
@@ -136,14 +136,4 @@
   friend class DecoderLocker;
 };
 
-class DecoderLocker : public MutexLocker {
-  AbstractDecoder* _decoder;
-  inline bool is_first_error_thread();
-public:
-  DecoderLocker();
-  AbstractDecoder* decoder() {
-    return _decoder;
-  }
-};
-
 #endif // SHARE_UTILITIES_DECODER_HPP
--- a/src/java.base/share/classes/java/io/LineNumberReader.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/io/LineNumberReader.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Fri May 03 08:26:44 2019 +0100
@@ -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/StringConcatHelper.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java	Fri May 03 08:26:44 2019 +0100
@@ -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/constant/ClassDesc.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/Socket.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/SocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -72,19 +72,13 @@
     @SuppressWarnings("unchecked")
     static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
         if (USE_PLAINSOCKETIMPL) {
-            return (S) new PlainSocketImpl();
+            return (S) new PlainSocketImpl(server);
         } else {
             return (S) new NioSocketImpl(server);
         }
     }
 
     /**
-     * The actual Socket object.
-     */
-    Socket socket = null;
-    ServerSocket serverSocket = null;
-
-    /**
      * The file descriptor object for this socket.
      */
     protected FileDescriptor fd;
@@ -105,6 +99,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;
@@ -324,22 +335,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}.
      *
@@ -419,11 +414,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);
@@ -432,13 +425,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");
@@ -462,11 +453,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);
@@ -475,13 +464,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");
@@ -528,7 +515,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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/SocketInputStream.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/SocketOutputStream.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/net/URL.java	Fri May 03 08:26:44 2019 +0100
@@ -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/file/FileSystems.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/nio/file/FileSystems.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/security/Key.java	Fri May 03 08:26:44 2019 +0100
@@ -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/concurrent/ConcurrentSkipListMap.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/module-info.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/sun/net/www/ParseUtil.java	Fri May 03 08:26:44 2019 +0100
@@ -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/NioSocketImpl.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -264,7 +264,7 @@
                 dst.get(b, off, n);
             }
             return n;
-        } finally{
+        } finally {
             Util.offerFirstTemporaryDirectBuffer(dst);
         }
     }
Binary file src/java.base/share/lib/security/cacerts has changed
--- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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/fs/UnixFileAttributeViews.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Fri May 03 08:26:44 2019 +0100
@@ -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/PlainSocketImpl.c	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c	Fri May 03 08:26:44 2019 +0100
@@ -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);
@@ -204,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/libnio/fs/UnixNativeDispatcher.c	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Fri May 03 08:26:44 2019 +0100
@@ -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.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Fri May 03 08:26:44 2019 +0100
@@ -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/impl/xs/XMLSchemaValidator.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java	Fri May 03 08:26:44 2019 +0100
@@ -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/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri May 03 08:26:44 2019 +0100
@@ -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/resources/compiler.properties	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyPair.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Fri May 03 08:26:44 2019 +0100
@@ -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/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java	Fri May 03 08:26:44 2019 +0100
@@ -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,16 +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 HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder;
+        return None;
     }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri May 03 08:26:44 2019 +0100
@@ -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;
@@ -227,7 +228,7 @@
         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);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Fri May 03 08:26:44 2019 +0100
@@ -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;
+
 /**
- * JDK 9+ version of {@link GraalServices}.
+ * 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.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri May 03 08:26:44 2019 +0100
@@ -40,7 +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;
@@ -295,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;
     }
 
     /**
@@ -324,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/resources/standard.properties	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Fri May 03 08:26:44 2019 +0100
@@ -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/resources/stylesheet.css	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Fri May 03 08:26:44 2019 +0100
@@ -364,18 +364,12 @@
     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;
--- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Fri May 03 08:26:44 2019 +0100
@@ -884,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;
@@ -899,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();
     }
 
@@ -926,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);
--- a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp	Fri May 03 08:26:44 2019 +0100
@@ -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/jtreg/ProblemList-graal.txt	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Fri May 03 08:26:44 2019 +0100
@@ -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/TEST.groups	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/TEST.groups	Fri May 03 08:26:44 2019 +0100
@@ -439,7 +439,7 @@
 # JVMTI tests
 vmTestbase_nsk_jvmti = \
   vmTestbase/nsk/jvmti \
-  vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv
+  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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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));
+        }
+    }
+}
--- a/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java	Fri May 03 08:26:44 2019 +0100
@@ -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/containers/docker/JfrNetwork.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/containers/docker/JfrNetwork.java	Fri May 03 08:26:44 2019 +0100
@@ -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/gc/TestAgeOutput.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestAgeOutput.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestHumongousReferenceObject.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestPolicyNamePerfCounter.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestSmallHeap.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/TestSystemGC.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestMinInitialErgonomics.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/logging/TestGCId.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/parallel/AdaptiveGCBoundary.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestG1.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestParallelGC.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestParallelScavengeSerialOld.java	Fri May 03 08:26:44 2019 +0100
@@ -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/CommandLine/VMDeprecatedOptions.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java	Fri May 03 08:26:44 2019 +0100
@@ -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)");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Shutdown/ShutdownTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitor.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitor.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorArrayAllSampledTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestAddDeleteMethods.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java	Fri May 03 08:26:44 2019 +0100
@@ -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/share/jni/ExceptionCheckingJniEnv.cpp	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp	Fri May 03 08:26:44 2019 +0100
@@ -22,6 +22,7 @@
  * questions.
  */
 
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -97,7 +98,7 @@
     }
   }
 
-  int DecimalToAsciiRec(char *str, long line) {
+  int DecimalToAsciiRec(char *str, int line) {
     if (line == 0) {
       return 0;
     }
@@ -112,21 +113,27 @@
 
   // Implementing a simple version of sprintf for "%d"...
   void DecimalToAscii(char *str, int line) {
-    // Go to long so that the INT_MIN case can be handled seemlessly.
-    long internal_line = line;
-    if (internal_line == 0) {
+    if (line == 0) {
       str[0] = '0';
       str[1] = '\0';
       return;
     }
 
-    if (internal_line < 0) {
+    // 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 = '-';
-      internal_line *= -1;
+      line *= -1;
       str++;
     }
 
-    str[DecimalToAsciiRec(str, internal_line)] = '\0';
+    str[DecimalToAsciiRec(str, line)] = '\0';
   }
 
   void GenerateErrorMessage() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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/com/sun/jdi/ExceptionEvents.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/com/sun/jdi/ExceptionEvents.java	Fri May 03 08:26:44 2019 +0100
@@ -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/net/httpserver/bugs/B6361557.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/com/sun/net/httpserver/bugs/B6361557.java	Fri May 03 08:26:44 2019 +0100
@@ -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;
--- a/test/jdk/java/io/DataOutputStream/WriteUTF.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/io/DataOutputStream/WriteUTF.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/lang/String/concat/WithSecurityManager.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Authenticator/B4722333.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/HttpURLConnection/UnmodifiableMaps.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/ResponseCache/ResponseCacheTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/GetLocalAddress.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/LingerTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/SetReceiveBufferSize.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/ShutdownBoth.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/SoTimeout.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/TestAfterClose.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socket/UrgentDataTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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/Socks/SocksIPv6Test.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socks/SocksIPv6Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/Socks/SocksServer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/URL/GetContent.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/URLConnection/B5052093.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/net/URLPermission/nstest/LookupTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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/file/Files/SymlinkTime.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/security/KeyPairGenerator/FinalizeHalf.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/Locale/Bug8040211.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/Atomic8Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/AtomicIntegerArray9Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/AtomicLongArray9Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/AtomicReferenceArray9Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/Collection8Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/MapTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/SplittableRandomTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/ThreadLocalRandom8Test.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/java/util/concurrent/tck/VectorTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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/jdk/nio/zipfs/Basic.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/jdk/nio/zipfs/Basic.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/jdk/nio/zipfs/Demo.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/jdk/nio/zipfs/PathOps.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ /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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/ftp/TestFtpClientNameListWithNull.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/http/HttpClient/ProxyTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/http/HttpURLConnection/PostOnDelete.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamClose.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/httptest/TestHttpServer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/protocol/http/B8012625.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/protocol/http/Finalizer.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	Fri May 03 08:26:44 2019 +0100
@@ -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/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java	Fri May 03 08:26:44 2019 +0100
@@ -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/testInterface/TestInterface.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java	Fri May 03 08:26:44 2019 +0100
@@ -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>"
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Fri May 03 08:26:44 2019 +0100
@@ -268,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",
@@ -279,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/testPrivateClasses/TestPrivateClasses.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java	Fri May 03 08:26:44 2019 +0100
@@ -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/testSingletonLists/TestSingletonLists.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testSingletonLists/TestSingletonLists.java	Fri May 03 08:26:44 2019 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8219998
+ * @bug 8219998 8221991
  * @summary Eliminate inherently singleton lists
  * @library /tools/lib ../../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -275,10 +275,6 @@
 
                 case "ul": case "ol": case "dl":
                     counts.push(new TreeMap<>());
-                    if (!attrs.isEmpty() && attrs.containsKey("class")
-                            && attrs.containsValue("inheritance")) {
-                        inheritanceClass = true;
-                    }
                     break;
 
                 case "li": case "dd": case "dt": {
@@ -297,11 +293,7 @@
                     if (c.get("li") == 0) {
                         error(currFile, getLineNumber(), "empty list");
                     } else if (c.get("li") == 1 && fileName != null && !excludeFiles.contains(fileName)) {
-                        if (!inheritanceClass) {
-                            error(currFile, getLineNumber(), "singleton list");
-                        } else {
-                            inheritanceClass = false;
-                        }
+                        error(currFile, getLineNumber(), "singleton list");
                     }
                     break;
                 }
@@ -319,5 +311,4 @@
             }
         }
     }
-
-}
\ No newline at end of file
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/annotations/8218152/MalformedAnnotationProcessorTests.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/tools/javac/api/file/SJFM_TestBase.java	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Fri May 03 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/langtools/tools/javac/modules/ContainsTest.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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/net/URIBuilder.java	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/lib/jdk/test/lib/net/URIBuilder.java	Fri May 03 08:26:44 2019 +0100
@@ -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 08:26:44 2019 +0100
@@ -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	Tue Apr 30 19:34:13 2019 +0100
+++ b/test/micro/org/openjdk/bench/java/lang/StringConcat.java	Fri May 03 08:26:44 2019 +0100
@@ -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;
     }