Merge unixdomainchannels
authormichaelm
Fri, 29 Nov 2019 10:02:07 +0000
branchunixdomainchannels
changeset 59322 cfe31d2f935c
parent 59266 bfc8074ea4ef (current diff)
parent 59321 5775e4825e58 (diff)
Merge
--- a/.hgtags	Tue Nov 26 10:22:13 2019 +0000
+++ b/.hgtags	Fri Nov 29 10:02:07 2019 +0000
@@ -597,3 +597,4 @@
 83810b7d12e7ff761ad3dd91f323a22dad96f108 jdk-14+22
 15936b142f86731afa4b1a2c0fe4a01e806c4944 jdk-14+23
 438337c846fb071900ddb6922bddf8b3e895a514 jdk-14+24
+17d242844fc9e7d18b3eac97426490a9c246119e jdk-14+25
--- a/make/autoconf/flags-cflags.m4	Tue Nov 26 10:22:13 2019 +0000
+++ b/make/autoconf/flags-cflags.m4	Fri Nov 29 10:02:07 2019 +0000
@@ -190,20 +190,7 @@
       WARNINGS_ENABLE_ALL_CXXFLAGS="$WARNINGS_ENABLE_ALL_CFLAGS $WARNINGS_ENABLE_ADDITIONAL_CXX"
 
       DISABLED_WARNINGS="unused-parameter unused"
-
-      # Repeate the check for the BUILD_CC and BUILD_CXX. Need to also reset
-      # CFLAGS since any target specific flags will likely not work with the
-      # build compiler
-      CC_OLD="$CC"
-      CXX_OLD="$CXX"
-      CC="$BUILD_CC"
-      CXX="$BUILD_CXX"
-      CFLAGS_OLD="$CFLAGS"
-      CFLAGS=""
       BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-"
-      CC="$CC_OLD"
-      CXX="$CXX_OLD"
-      CFLAGS="$CFLAGS_OLD"
       ;;
 
     clang)
@@ -420,6 +407,17 @@
 
   FLAGS_SETUP_CFLAGS_CPU_DEP([TARGET])
 
+  # Repeat the check for the BUILD_CC and BUILD_CXX. Need to also reset CFLAGS
+  # since any target specific flags will likely not work with the build compiler.
+  CC_OLD="$CC"
+  CXX_OLD="$CXX"
+  CFLAGS_OLD="$CFLAGS"
+  CXXFLAGS_OLD="$CXXFLAGS"
+  CC="$BUILD_CC"
+  CXX="$BUILD_CXX"
+  CFLAGS=""
+  CXXFLAGS=""
+
   FLAGS_OS=$OPENJDK_BUILD_OS
   FLAGS_OS_TYPE=$OPENJDK_BUILD_OS_TYPE
   FLAGS_CPU=$OPENJDK_BUILD_CPU
@@ -430,6 +428,11 @@
   FLAGS_CPU_LEGACY_LIB=$OPENJDK_BUILD_CPU_LEGACY_LIB
 
   FLAGS_SETUP_CFLAGS_CPU_DEP([BUILD], [OPENJDK_BUILD_], [BUILD_])
+
+  CC="$CC_OLD"
+  CXX="$CXX_OLD"
+  CFLAGS="$CFLAGS_OLD"
+  CXXFLAGS="$CXXFLAGS_OLD"
 ])
 
 ################################################################################
@@ -529,6 +532,11 @@
   if test "x$TOOLCHAIN_TYPE" = xgcc; then
     TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fcheck-new -fstack-protector"
     TOOLCHAIN_CFLAGS_JDK="-pipe -fstack-protector"
+    # reduce lib size on s390x in link step, this needs also special compile flags
+    if test "x$OPENJDK_TARGET_CPU" = xs390x; then
+      TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
+      TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections"
+    fi
     # technically NOT for CXX (but since this gives *worse* performance, use
     # no-strict-aliasing everywhere!)
     TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing"
--- a/make/autoconf/flags-ldflags.m4	Tue Nov 26 10:22:13 2019 +0000
+++ b/make/autoconf/flags-ldflags.m4	Fri Nov 29 10:02:07 2019 +0000
@@ -70,10 +70,14 @@
     fi
 
     # Add -z defs, to forbid undefined symbols in object files.
-    BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,-z,defs"
+    # add relro (mark relocations read only) for all libs
+    BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,-z,defs -Wl,-z,relro"
+    # s390x : remove unused code+data in link step
+    if test "x$OPENJDK_TARGET_CPU" = xs390x; then
+      BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,--gc-sections -Wl,--print-gc-sections"
+    fi
 
-    BASIC_LDFLAGS_JVM_ONLY="-Wl,-O1 -Wl,-z,relro"
-
+    BASIC_LDFLAGS_JVM_ONLY="-Wl,-O1"
 
   elif test "x$TOOLCHAIN_TYPE" = xclang; then
     BASIC_LDFLAGS_JVM_ONLY="-mno-omit-leaf-frame-pointer -mstack-alignment=16 \
@@ -120,9 +124,6 @@
     if test "x$OPENJDK_TARGET_OS" = xlinux; then
       if test x$DEBUG_LEVEL = xrelease; then
         DEBUGLEVEL_LDFLAGS_JDK_ONLY="$DEBUGLEVEL_LDFLAGS_JDK_ONLY -Wl,-O1"
-      else
-        # mark relocations read only on (fast/slow) debug builds
-        DEBUGLEVEL_LDFLAGS_JDK_ONLY="-Wl,-z,relro"
       fi
       if test x$DEBUG_LEVEL = xslowdebug; then
         # do relocations at load
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/data/cacerts/amazonrootca1	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,27 @@
+Owner: CN=Amazon Root CA 1, O=Amazon, C=US
+Issuer: CN=Amazon Root CA 1, O=Amazon, C=US
+Serial number: 66c9fcf99bf8c0a39e2f0788a43e696365bca
+Valid from: Tue May 26 00:00:00 GMT 2015 until: Sun Jan 17 00:00:00 GMT 2038
+Signature algorithm name: SHA256withRSA
+Subject Public Key Algorithm: 2048-bit RSA key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/data/cacerts/amazonrootca2	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,38 @@
+Owner: CN=Amazon Root CA 2, O=Amazon, C=US
+Issuer: CN=Amazon Root CA 2, O=Amazon, C=US
+Serial number: 66c9fd29635869f0a0fe58678f85b26bb8a37
+Valid from: Tue May 26 00:00:00 GMT 2015 until: Sat May 26 00:00:00 GMT 2040
+Signature algorithm name: SHA384withRSA
+Subject Public Key Algorithm: 4096-bit RSA key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/data/cacerts/amazonrootca3	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,19 @@
+Owner: CN=Amazon Root CA 3, O=Amazon, C=US
+Issuer: CN=Amazon Root CA 3, O=Amazon, C=US
+Serial number: 66c9fd5749736663f3b0b9ad9e89e7603f24a
+Valid from: Tue May 26 00:00:00 GMT 2015 until: Sat May 26 00:00:00 GMT 2040
+Signature algorithm name: SHA256withECDSA
+Subject Public Key Algorithm: 256-bit EC key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/data/cacerts/amazonrootca4	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,20 @@
+Owner: CN=Amazon Root CA 4, O=Amazon, C=US
+Issuer: CN=Amazon Root CA 4, O=Amazon, C=US
+Serial number: 66c9fd7c1bb104c2943e5717b7b2cc81ac10e
+Valid from: Tue May 26 00:00:00 GMT 2015 until: Sat May 26 00:00:00 GMT 2040
+Signature algorithm name: SHA384withECDSA
+Subject Public Key Algorithm: 384-bit EC key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Fri Nov 29 10:02:07 2019 +0000
@@ -5639,7 +5639,6 @@
 operand cmpOpEqNe()
 %{
   match(Bool);
-  match(CmpOp);
   op_cost(0);
   predicate(n->as_Bool()->_test._test == BoolTest::ne
             || n->as_Bool()->_test._test == BoolTest::eq);
@@ -5663,7 +5662,6 @@
 operand cmpOpLtGe()
 %{
   match(Bool);
-  match(CmpOp);
   op_cost(0);
 
   predicate(n->as_Bool()->_test._test == BoolTest::lt
@@ -5688,7 +5686,6 @@
 operand cmpOpUEqNeLtGe()
 %{
   match(Bool);
-  match(CmpOp);
   op_cost(0);
 
   predicate(n->as_Bool()->_test._test == BoolTest::eq
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,6 +30,7 @@
 #include "nativeInst_aarch64.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "utilities/ostream.hpp"
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -443,7 +443,6 @@
     Register obj = r0;
     Register mdp = r1;
     Register tmp = r2;
-    __ ldr(mdp, Address(rmethod, Method::method_data_offset()));
     __ profile_return_type(mdp, obj, tmp);
   }
 
@@ -1633,13 +1632,8 @@
   __ mov(rscratch2, true);
   __ strb(rscratch2, do_not_unlock_if_synchronized);
 
-  Label no_mdp;
   Register mdp = r3;
-  __ ldr(mdp, Address(rmethod, Method::method_data_offset()));
-  __ cbz(mdp, no_mdp);
-  __ add(mdp, mdp, in_bytes(MethodData::data_offset()));
   __ profile_parameters_type(mdp, r1, r2);
-  __ bind(no_mdp);
 
   // increment invocation count & check for overflow
   Label invocation_counter_overflow;
--- a/src/hotspot/cpu/arm/arm.ad	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/arm/arm.ad	Fri Nov 29 10:02:07 2019 +0000
@@ -2204,6 +2204,30 @@
   interface(REG_INTER);
 %}
 
+operand R8RegP() %{
+  constraint(ALLOC_IN_RC(R8_regP));
+  match(iRegP);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
+operand R9RegP() %{
+  constraint(ALLOC_IN_RC(R9_regP));
+  match(iRegP);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
+operand R12RegP() %{
+  constraint(ALLOC_IN_RC(R12_regP));
+  match(iRegP);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 operand R2RegP() %{
   constraint(ALLOC_IN_RC(R2_regP));
   match(iRegP);
@@ -2236,6 +2260,14 @@
   interface(REG_INTER);
 %}
 
+operand SPRegP() %{
+  constraint(ALLOC_IN_RC(SP_regP));
+  match(iRegP);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 operand LRRegP() %{
   constraint(ALLOC_IN_RC(LR_regP));
   match(iRegP);
--- a/src/hotspot/cpu/arm/arm_32.ad	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/arm/arm_32.ad	Fri Nov 29 10:02:07 2019 +0000
@@ -232,11 +232,15 @@
 reg_class R1_regP(R_R1);
 reg_class R2_regP(R_R2);
 reg_class R4_regP(R_R4);
+reg_class R8_regP(R_R8);
+reg_class R9_regP(R_R9);
+reg_class R12_regP(R_R12);
 reg_class Rexception_regP(R_Rexception_obj);
 reg_class Ricklass_regP(R_Ricklass);
 reg_class Rmethod_regP(R_Rmethod);
 reg_class Rthread_regP(R_Rthread);
 reg_class IP_regP(R_R12);
+reg_class SP_regP(R_R13);
 reg_class LR_regP(R_R14);
 
 reg_class FP_regP(R_R11);
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -581,6 +581,7 @@
         base_reg = Rtemp;
         __ str(from_lo, Address(Rtemp));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd str
           patching_epilog(patch, lir_patch_low, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_high;
@@ -589,6 +590,7 @@
       } else if (base_reg == from_lo) {
         __ str(from_hi, as_Address_hi(to_addr));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd str
           patching_epilog(patch, lir_patch_high, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_low;
@@ -597,6 +599,7 @@
       } else {
         __ str(from_lo, as_Address_lo(to_addr));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd str
           patching_epilog(patch, lir_patch_low, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_high;
@@ -640,7 +643,7 @@
   }
 
   if (patch != NULL) {
-    // Offset embeedded into LDR/STR instruction may appear not enough
+    // Offset embedded into LDR/STR instruction may appear not enough
     // to address a field. So, provide a space for one more instruction
     // that will deal with larger offsets.
     __ nop();
@@ -791,6 +794,7 @@
         base_reg = Rtemp;
         __ ldr(to_lo, Address(Rtemp));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd ldr
           patching_epilog(patch, lir_patch_low, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_high;
@@ -799,6 +803,7 @@
       } else if (base_reg == to_lo) {
         __ ldr(to_hi, as_Address_hi(addr));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd ldr
           patching_epilog(patch, lir_patch_high, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_low;
@@ -807,6 +812,7 @@
       } else {
         __ ldr(to_lo, as_Address_lo(addr));
         if (patch != NULL) {
+          __ nop(); // see comment before patching_epilog for 2nd ldr
           patching_epilog(patch, lir_patch_low, base_reg, info);
           patch = new PatchingStub(_masm, PatchingStub::access_field_id);
           patch_code = lir_patch_high;
@@ -846,7 +852,7 @@
   }
 
   if (patch != NULL) {
-    // Offset embeedded into LDR/STR instruction may appear not enough
+    // Offset embedded into LDR/STR instruction may appear not enough
     // to address a field. So, provide a space for one more instruction
     // that will deal with larger offsets.
     __ nop();
--- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,7 @@
 #include "asm/macroAssembler.hpp"
 #include "code/codeCache.hpp"
 #include "runtime/icache.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/thread.hpp"
 #include "register_arm.hpp"
--- a/src/hotspot/cpu/arm/relocInfo_arm.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/arm/relocInfo_arm.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,7 +29,6 @@
 #include "nativeInst_arm.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oop.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 
 void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -327,24 +327,42 @@
 #endif
 }
 
+#ifdef _LP64
 void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
   BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
   if (bs_nm == NULL) {
     return;
   }
-#ifndef _LP64
-  ShouldNotReachHere();
-#else
   Label continuation;
-  Register thread = LP64_ONLY(r15_thread);
+  Register thread = r15_thread;
   Address disarmed_addr(thread, in_bytes(bs_nm->thread_disarmed_offset()));
   __ align(8);
   __ cmpl(disarmed_addr, 0);
   __ jcc(Assembler::equal, continuation);
   __ call(RuntimeAddress(StubRoutines::x86::method_entry_barrier()));
   __ bind(continuation);
+}
+#else
+void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
+  BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
+  if (bs_nm == NULL) {
+    return;
+  }
+
+  Label continuation;
+
+  Register tmp = rdi;
+  __ push(tmp);
+  __ movptr(tmp, (intptr_t)bs_nm->disarmed_value_address());
+  Address disarmed_addr(tmp, 0);
+  __ align(4);
+  __ cmpl(disarmed_addr, 0);
+  __ pop(tmp);
+  __ jcc(Assembler::equal, continuation);
+  __ call(RuntimeAddress(StubRoutines::x86::method_entry_barrier()));
+  __ bind(continuation);
+}
 #endif
-}
 
 void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
   BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod();
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -35,6 +35,7 @@
 
 class NativeNMethodCmpBarrier: public NativeInstruction {
 public:
+#ifdef _LP64
   enum Intel_specific_constants {
     instruction_code        = 0x81,
     instruction_size        = 8,
@@ -42,6 +43,14 @@
     instruction_rex_prefix  = Assembler::REX | Assembler::REX_B,
     instruction_modrm       = 0x7f  // [r15 + offset]
   };
+#else
+  enum Intel_specific_constants {
+    instruction_code        = 0x81,
+    instruction_size        = 7,
+    imm_offset              = 2,
+    instruction_modrm       = 0x3f  // [rdi]
+  };
+#endif
 
   address instruction_address() const { return addr_at(0); }
   address immediate_address() const { return addr_at(imm_offset); }
@@ -51,6 +60,7 @@
   void verify() const;
 };
 
+#ifdef _LP64
 void NativeNMethodCmpBarrier::verify() const {
   if (((uintptr_t) instruction_address()) & 0x7) {
     fatal("Not properly aligned");
@@ -77,6 +87,27 @@
     fatal("not a cmp barrier");
   }
 }
+#else
+void NativeNMethodCmpBarrier::verify() const {
+  if (((uintptr_t) instruction_address()) & 0x3) {
+    fatal("Not properly aligned");
+  }
+
+  int inst = ubyte_at(0);
+  if (inst != instruction_code) {
+    tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
+        inst);
+    fatal("not a cmp barrier");
+  }
+
+  int modrm = ubyte_at(1);
+  if (modrm != instruction_modrm) {
+    tty->print_cr("Addr: " INTPTR_FORMAT " mod/rm: 0x%x", p2i(instruction_address()),
+        modrm);
+    fatal("not a cmp barrier");
+  }
+}
+#endif // _LP64
 
 void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
   /*
@@ -127,7 +158,7 @@
 // NativeNMethodCmpBarrier::verify() will immediately complain when it does
 // not find the expected native instruction at this offset, which needs updating.
 // Note that this offset is invariant of PreserveFramePointer.
-static const int entry_barrier_offset = -19;
+static const int entry_barrier_offset = LP64_ONLY(-19) NOT_LP64(-18);
 
 static NativeNMethodCmpBarrier* native_nmethod_barrier(nmethod* nm) {
   address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset;
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -395,6 +395,52 @@
   __ block_comment("load_reference_barrier_native { ");
 }
 
+#ifdef _LP64
+void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
+  // Use default version
+  BarrierSetAssembler::c2i_entry_barrier(masm);
+}
+#else
+void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
+  BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod();
+  if (bs == NULL) {
+    return;
+  }
+
+  Label bad_call;
+  __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters.
+  __ jcc(Assembler::equal, bad_call);
+
+  Register tmp1 = rax;
+  Register tmp2 = rcx;
+
+  __ push(tmp1);
+  __ push(tmp2);
+
+  // Pointer chase to the method holder to find out if the method is concurrently unloading.
+  Label method_live;
+  __ load_method_holder_cld(tmp1, rbx);
+
+   // Is it a strong CLD?
+  __ cmpl(Address(tmp1, ClassLoaderData::keep_alive_offset()), 0);
+  __ jcc(Assembler::greater, method_live);
+
+   // Is it a weak but alive CLD?
+  __ movptr(tmp1, Address(tmp1, ClassLoaderData::holder_offset()));
+  __ resolve_weak_handle(tmp1, tmp2);
+  __ cmpptr(tmp1, 0);
+  __ jcc(Assembler::notEqual, method_live);
+  __ pop(tmp2);
+  __ pop(tmp1);
+
+  __ bind(bad_call);
+  __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+  __ bind(method_live);
+  __ pop(tmp2);
+  __ pop(tmp1);
+}
+#endif
+
 void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
   if (ShenandoahStoreValEnqueueBarrier) {
     storeval_barrier_impl(masm, dst, tmp);
@@ -511,8 +557,12 @@
 
   // 3: apply keep-alive barrier if needed
   if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
-    const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
+    __ push_IU_state();
+    Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
     assert_different_registers(dst, tmp1, tmp_thread);
+    if (!thread->is_valid()) {
+      thread = rdx;
+    }
     NOT_LP64(__ get_thread(thread));
     // Generate the SATB pre-barrier code to log the value of
     // the referent field in an SATB buffer.
@@ -523,6 +573,7 @@
                                  tmp1 /* tmp */,
                                  true /* tosca_live */,
                                  true /* expand_call */);
+    __ pop_IU_state();
   }
 }
 
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -86,6 +86,7 @@
                         Address dst, Register val, Register tmp1, Register tmp2);
   virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
                                              Register obj, Register tmp, Label& slowpath);
+  virtual void c2i_entry_barrier(MacroAssembler* masm);
 
   virtual void barrier_stubs_init();
 
--- a/src/hotspot/cpu/x86/rdtsc_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/rdtsc_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "rdtsc_x86.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 #include "vm_version_ext_x86.hpp"
 
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -975,6 +975,9 @@
 
   address c2i_entry = __ pc();
 
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->c2i_entry_barrier(masm);
+
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
   __ flush();
@@ -1886,6 +1889,10 @@
   // -2 because return address is already present and so is saved rbp
   __ subptr(rsp, stack_size - 2*wordSize);
 
+
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->nmethod_entry_barrier(masm);
+
   // Frame is now completed as far as size and linkage.
   int frame_complete = ((intptr_t)__ pc()) - start;
 
@@ -1921,12 +1928,12 @@
   // if we load it once it is usable thru the entire wrapper
   const Register thread = rdi;
 
-  // We use rsi as the oop handle for the receiver/klass
-  // It is callee save so it survives the call to native
-
-  const Register oop_handle_reg = rsi;
-
-  __ get_thread(thread);
+   // We use rsi as the oop handle for the receiver/klass
+   // It is callee save so it survives the call to native
+
+   const Register oop_handle_reg = rsi;
+
+   __ get_thread(thread);
 
   if (is_critical_native && !Universe::heap()->supports_object_pinning()) {
     check_needs_gc_for_critical_native(masm, thread, stack_slots, total_c_args, total_in_args,
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,6 +27,7 @@
 #include "asm/macroAssembler.inline.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
+#include "gc/shared/barrierSetNMethod.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/universe.hpp"
 #include "nativeInst_x86.hpp"
@@ -3663,6 +3664,68 @@
     __ ret(0);
   }
 
+  address generate_method_entry_barrier() {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier");
+
+    Label deoptimize_label;
+
+    address start = __ pc();
+
+    __ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
+
+    BLOCK_COMMENT("Entry:");
+    __ enter(); // save rbp
+
+    // save rbx, because we want to use that value.
+    // We could do without it but then we depend on the number of slots used by pusha
+    __ push(rbx);
+
+    __ lea(rbx, Address(rsp, wordSize * 3)); // 1 for cookie, 1 for rbp, 1 for rbx - this should be the return address
+
+    __ pusha();
+
+    // xmm0 and xmm1 may be used for passing float/double arguments
+    const int xmm_size = wordSize * 2;
+    const int xmm_spill_size = xmm_size * 2;
+    __ subptr(rsp, xmm_spill_size);
+    __ movdqu(Address(rsp, xmm_size * 1), xmm1);
+    __ movdqu(Address(rsp, xmm_size * 0), xmm0);
+
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast<int (*)(address*)>(BarrierSetNMethod::nmethod_stub_entry_barrier)), rbx);
+
+    __ movdqu(xmm0, Address(rsp, xmm_size * 0));
+    __ movdqu(xmm1, Address(rsp, xmm_size * 1));
+    __ addptr(rsp, xmm_spill_size);
+
+    __ cmpl(rax, 1); // 1 means deoptimize
+    __ jcc(Assembler::equal, deoptimize_label);
+
+    __ popa();
+    __ pop(rbx);
+
+    __ leave();
+
+    __ addptr(rsp, 1 * wordSize); // cookie
+    __ ret(0);
+
+    __ BIND(deoptimize_label);
+
+    __ popa();
+    __ pop(rbx);
+
+    __ leave();
+
+    // this can be taken out, but is good for verification purposes. getting a SIGSEGV
+    // here while still having a correct stack is valuable
+    __ testptr(rsp, Address(rsp, 0));
+
+    __ movptr(rsp, Address(rsp, 0)); // new rsp was written in the barrier
+    __ jmp(Address(rsp, -1 * wordSize)); // jmp target should be callers verified_entry_point
+
+    return start;
+  }
+
  public:
   // Information about frame layout at time of blocking runtime call.
   // Note that we only have to preserve callee-saved registers since
@@ -3959,6 +4022,11 @@
     StubRoutines::_safefetchN_entry           = StubRoutines::_safefetch32_entry;
     StubRoutines::_safefetchN_fault_pc        = StubRoutines::_safefetch32_fault_pc;
     StubRoutines::_safefetchN_continuation_pc = StubRoutines::_safefetch32_continuation_pc;
+
+    BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
+    if (bs_nm != NULL) {
+      StubRoutines::x86::_method_entry_barrier = generate_method_entry_barrier();
+    }
   }
 
 
--- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -55,14 +55,8 @@
   static address _double_sign_mask;
   static address _double_sign_flip;
 
-  static address _method_entry_barrier;
-
  public:
 
-  static address method_entry_barrier() {
-    return _method_entry_barrier;
-  }
-
   static address get_previous_fp_entry() {
     return _get_previous_fp_entry;
   }
@@ -121,6 +115,8 @@
   //shuffle mask for big-endian 128-bit integers
   static address _counter_shuffle_mask_addr;
 
+  static address _method_entry_barrier;
+
   // masks and table for CRC32
   static uint64_t _crc_by128_masks[];
   static juint    _crc_table[];
@@ -221,6 +217,7 @@
   static address upper_word_mask_addr() { return _upper_word_mask_addr; }
   static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; }
   static address k256_addr()      { return _k256_adr; }
+  static address method_entry_barrier() { return _method_entry_barrier; }
 
   static address vector_short_to_byte_mask() {
     return _vector_short_to_byte_mask;
--- a/src/hotspot/cpu/x86/stubRoutines_x86_32.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/stubRoutines_x86_32.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, 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
@@ -32,3 +32,5 @@
 // a description of how to extend it, see the stubRoutines.hpp file.
 
 address StubRoutines::x86::_verify_fpu_cntrl_wrd_entry = NULL;
+address StubRoutines::x86::_method_entry_barrier = NULL;
+
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -367,26 +367,29 @@
     //
     intx saved_useavx = UseAVX;
     intx saved_usesse = UseSSE;
-    // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
-    __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
-    __ movl(rax, 0x10000);
-    __ andl(rax, Address(rsi, 4)); // xcr0 bits sse | ymm
-    __ cmpl(rax, 0x10000);
-    __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
-    // check _cpuid_info.xem_xcr0_eax.bits.opmask
-    // check _cpuid_info.xem_xcr0_eax.bits.zmm512
-    // check _cpuid_info.xem_xcr0_eax.bits.zmm32
-    __ movl(rax, 0xE0);
-    __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
-    __ cmpl(rax, 0xE0);
-    __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
 
-    __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
-    __ movl(rax, Address(rsi, 0));
-    __ cmpl(rax, 0x50654);              // If it is Skylake
-    __ jcc(Assembler::equal, legacy_setup);
     // If UseAVX is unitialized or is set by the user to include EVEX
     if (use_evex) {
+      // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
+      __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
+      __ movl(rax, 0x10000);
+      __ andl(rax, Address(rsi, 4)); // xcr0 bits sse | ymm
+      __ cmpl(rax, 0x10000);
+      __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
+      // check _cpuid_info.xem_xcr0_eax.bits.opmask
+      // check _cpuid_info.xem_xcr0_eax.bits.zmm512
+      // check _cpuid_info.xem_xcr0_eax.bits.zmm32
+      __ movl(rax, 0xE0);
+      __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
+      __ cmpl(rax, 0xE0);
+      __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
+
+      if (FLAG_IS_DEFAULT(UseAVX)) {
+        __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
+        __ movl(rax, Address(rsi, 0));
+        __ cmpl(rax, 0x50654);              // If it is Skylake
+        __ jcc(Assembler::equal, legacy_setup);
+      }
       // EVEX setup: run in lowest evex mode
       VM_Version::set_evex_cpuFeatures(); // Enable temporary to pass asserts
       UseAVX = 3;
@@ -455,27 +458,28 @@
     VM_Version::set_cpuinfo_cont_addr(__ pc());
     // Returns here after signal. Save xmm0 to check it later.
 
-    // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
-    __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
-    __ movl(rax, 0x10000);
-    __ andl(rax, Address(rsi, 4));
-    __ cmpl(rax, 0x10000);
-    __ jcc(Assembler::notEqual, legacy_save_restore);
-    // check _cpuid_info.xem_xcr0_eax.bits.opmask
-    // check _cpuid_info.xem_xcr0_eax.bits.zmm512
-    // check _cpuid_info.xem_xcr0_eax.bits.zmm32
-    __ movl(rax, 0xE0);
-    __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
-    __ cmpl(rax, 0xE0);
-    __ jcc(Assembler::notEqual, legacy_save_restore);
-
-    __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
-    __ movl(rax, Address(rsi, 0));
-    __ cmpl(rax, 0x50654);              // If it is Skylake
-    __ jcc(Assembler::equal, legacy_save_restore);
-
     // If UseAVX is unitialized or is set by the user to include EVEX
     if (use_evex) {
+      // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
+      __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
+      __ movl(rax, 0x10000);
+      __ andl(rax, Address(rsi, 4));
+      __ cmpl(rax, 0x10000);
+      __ jcc(Assembler::notEqual, legacy_save_restore);
+      // check _cpuid_info.xem_xcr0_eax.bits.opmask
+      // check _cpuid_info.xem_xcr0_eax.bits.zmm512
+      // check _cpuid_info.xem_xcr0_eax.bits.zmm32
+      __ movl(rax, 0xE0);
+      __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
+      __ cmpl(rax, 0xE0);
+      __ jcc(Assembler::notEqual, legacy_save_restore);
+
+      if (FLAG_IS_DEFAULT(UseAVX)) {
+        __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
+        __ movl(rax, Address(rsi, 0));
+        __ cmpl(rax, 0x50654);              // If it is Skylake
+        __ jcc(Assembler::equal, legacy_save_restore);
+      }
       // EVEX check: run in lowest evex mode
       VM_Version::set_evex_cpuFeatures(); // Enable temporary to pass asserts
       UseAVX = 3;
--- a/src/hotspot/cpu/x86/x86_32.ad	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/x86_32.ad	Fri Nov 29 10:02:07 2019 +0000
@@ -3917,6 +3917,13 @@
   interface(REG_INTER);
 %}
 
+operand eDXRegP(eRegP reg) %{
+  constraint(ALLOC_IN_RC(edx_reg));
+  match(reg);
+  format %{ "EDX" %}
+  interface(REG_INTER);
+%}
+
 operand eSIRegP(eRegP reg) %{
   constraint(ALLOC_IN_RC(esi_reg));
   match(reg);
@@ -8977,7 +8984,7 @@
   %}
 
   ins_pipe(ialu_reg_reg);
-%} 
+%}
 
 //----------Long Instructions------------------------------------------------
 // Add Long Register with Register
--- a/src/hotspot/cpu/x86/x86_64.ad	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/x86/x86_64.ad	Fri Nov 29 10:02:07 2019 +0000
@@ -267,6 +267,9 @@
 // Singleton class for RSI pointer register
 reg_class ptr_rsi_reg(RSI, RSI_H);
 
+// Singleton class for RBP pointer register
+reg_class ptr_rbp_reg(RBP, RBP_H);
+
 // Singleton class for RDI pointer register
 reg_class ptr_rdi_reg(RDI, RDI_H);
 
@@ -3530,6 +3533,16 @@
   interface(REG_INTER);
 %}
 
+operand rbp_RegP()
+%{
+  constraint(ALLOC_IN_RC(ptr_rbp_reg));
+  match(RegP);
+  match(rRegP);
+
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 // Used in rep stosq
 operand rdi_RegP()
 %{
--- a/src/hotspot/cpu/zero/cppInterpreter_zero.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/cpu/zero/cppInterpreter_zero.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -38,13 +38,11 @@
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/arguments.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/synchronizer.hpp"
--- a/src/hotspot/os/aix/os_aix.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/os/aix/os_aix.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -60,7 +60,6 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
--- a/src/hotspot/os/linux/os_linux.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -53,7 +53,6 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
--- a/src/hotspot/os/posix/os_posix.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/os/posix/os_posix.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,6 +30,8 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "services/memTracker.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
 #include "utilities/events.hpp"
 #include "utilities/formatBuffer.hpp"
--- a/src/hotspot/os/windows/osThread_windows.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/os/windows/osThread_windows.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,6 @@
  */
 
 // no precompiled headers
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
 
--- a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -38,7 +38,6 @@
 #include "prims/jniFastGetField.hpp"
 #include "prims/jvm_misc.hpp"
 #include "runtime/arguments.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/extendedPC.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
--- a/src/hotspot/share/adlc/adlparse.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/adlc/adlparse.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -123,6 +123,7 @@
     parse_err(SEMERR, "Did not declare 'register' definitions");
   }
   regBlock->addSpillRegClass();
+  regBlock->addDynamicRegClass();
 
   // Done with parsing, check consistency.
 
--- a/src/hotspot/share/adlc/archDesc.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/adlc/archDesc.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -245,12 +245,12 @@
     // Construct chain rules
     build_chain_rule(op);
 
-    MatchRule &mrule = *op->_matrule;
-    Predicate *pred  =  op->_predicate;
+    MatchRule *mrule = op->_matrule;
+    Predicate *pred  = op->_predicate;
 
     // Grab the machine type of the operand
     const char  *rootOp    = op->_ident;
-    mrule._machType  = rootOp;
+    mrule->_machType  = rootOp;
 
     // Check for special cases
     if (strcmp(rootOp,"Universe")==0) continue;
@@ -271,10 +271,13 @@
 
     // Find result type for match.
     const char *result      = op->reduce_result();
-    bool        has_root    = false;
 
-    // Construct a MatchList for this entry
-    buildMatchList(op->_matrule, result, rootOp, pred, cost);
+    // Construct a MatchList for this entry.
+    // Iterate over the list to enumerate all match cases for operands with multiple match rules.
+    for (; mrule != NULL; mrule = mrule->_next) {
+      mrule->_machType = rootOp;
+      buildMatchList(mrule, result, rootOp, pred, cost);
+    }
   }
 }
 
@@ -805,6 +808,8 @@
     return "RegMask::Empty";
   } else if (strcmp(reg_class_name,"stack_slots")==0) {
     return "(Compile::current()->FIRST_STACK_mask())";
+  } else if (strcmp(reg_class_name, "dynamic")==0) {
+    return "*_opnds[0]->in_RegMask(0)";
   } else {
     char       *rc_name = toUpper(reg_class_name);
     const char *mask    = "_mask";
@@ -867,7 +872,7 @@
   }
 
   // Instructions producing 'Universe' use RegMask::Empty
-  if( strcmp(result,"Universe")==0 ) {
+  if (strcmp(result,"Universe") == 0) {
     return "RegMask::Empty";
   }
 
--- a/src/hotspot/share/adlc/formsopt.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/adlc/formsopt.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -80,6 +80,15 @@
   _regClass.Insert(rc_name,reg_class);
 }
 
+// Called after parsing the Register block.  Record the register class
+// for operands which are overwritten after matching.
+void RegisterForm::addDynamicRegClass() {
+  const char *rc_name = "dynamic";
+  RegClass* reg_class = new RegClass(rc_name);
+  reg_class->set_stack_version(false);
+  _rclasses.addName(rc_name);
+  _regClass.Insert(rc_name,reg_class);
+}
 
 // Provide iteration over all register definitions
 // in the order used by the register allocator
--- a/src/hotspot/share/adlc/formsopt.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/adlc/formsopt.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -104,6 +104,7 @@
 
   AllocClass *addAllocClass(char *allocName);
   void        addSpillRegClass();
+  void        addDynamicRegClass();
 
   // Provide iteration over all register definitions
   // in the order used by the register allocator
--- a/src/hotspot/share/adlc/output_c.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/adlc/output_c.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -2781,6 +2781,8 @@
       // Return the sole RegMask.
       if (strcmp(first_reg_class, "stack_slots") == 0) {
         fprintf(fp,"  return &(Compile::current()->FIRST_STACK_mask());\n");
+      } else if (strcmp(first_reg_class, "dynamic") == 0) {
+        fprintf(fp,"  return &RegMask::Empty;\n");
       } else {
         const char* first_reg_class_to_upper = toUpper(first_reg_class);
         fprintf(fp,"  return &%s_mask();\n", first_reg_class_to_upper);
--- a/src/hotspot/share/aot/aotCodeHeap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -40,6 +40,7 @@
 #include "oops/compressedOops.hpp"
 #include "oops/klass.inline.hpp"
 #include "oops/method.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/os.hpp"
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,6 +37,7 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/sharedRuntime.hpp"
--- a/src/hotspot/share/asm/assembler.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/asm/assembler.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,7 +29,6 @@
 #include "gc/shared/collectedHeap.hpp"
 #include "memory/universe.hpp"
 #include "oops/compressedOops.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/icache.hpp"
 #include "runtime/os.hpp"
 #include "runtime/thread.hpp"
--- a/src/hotspot/share/classfile/classLoader.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/classLoader.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
 #define SHARE_CLASSFILE_CLASSLOADER_INLINE_HPP
 
 #include "classfile/classLoader.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 // Next entry in class path
 inline ClassPathEntry* ClassPathEntry::next() const { return Atomic::load_acquire(&_next); }
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -67,7 +67,6 @@
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutex.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/macros.hpp"
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -38,7 +38,6 @@
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutex.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "utilities/growableArray.hpp"
--- a/src/hotspot/share/classfile/dictionary.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/dictionary.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,8 +33,6 @@
 #include "memory/metaspaceClosure.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "utilities/hashtable.inline.hpp"
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -79,7 +79,6 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "services/classLoadingService.hpp"
--- a/src/hotspot/share/classfile/verifier.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/classfile/verifier.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -50,7 +50,6 @@
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/thread.hpp"
--- a/src/hotspot/share/code/codeCache.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/code/codeCache.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -47,6 +47,7 @@
 #include "oops/oop.inline.hpp"
 #include "oops/verifyOopClosure.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/icache.hpp"
--- a/src/hotspot/share/code/compiledMethod.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/code/compiledMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -38,6 +38,7 @@
 #include "oops/methodData.hpp"
 #include "oops/method.inline.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
--- a/src/hotspot/share/code/compiledMethod.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/code/compiledMethod.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,8 +27,8 @@
 
 #include "code/compiledMethod.hpp"
 #include "code/nativeInst.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/frame.hpp"
-#include "runtime/orderAccess.hpp"
 
 inline bool CompiledMethod::is_deopt_pc(address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
 
--- a/src/hotspot/share/code/dependencyContext.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/code/dependencyContext.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,7 @@
 #include "code/dependencyContext.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/perfData.hpp"
 #include "utilities/exceptions.hpp"
 
--- a/src/hotspot/share/compiler/compileBroker.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/compiler/compileBroker.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,6 +29,7 @@
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileTask.hpp"
 #include "compiler/compilerDirectives.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/perfData.hpp"
 #include "utilities/stack.hpp"
 #if INCLUDE_JVMCI
--- a/src/hotspot/share/compiler/disassembler.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/compiler/disassembler.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -414,9 +414,10 @@
   _bytes_per_line  = Disassembler::pd_instruction_alignment();
   _print_file_name = true;
 
-  if (_optionsParsed) return;  // parse only once
-
-  // parse the global option string:
+  // parse the global option string
+  // We need to fill the options buffer for each newly created
+  // decode_env instance. The hsdis_* library looks for options
+  // in that buffer.
   collect_options(Disassembler::pd_cpu_opts());
   collect_options(PrintAssemblyOptions);
 
@@ -424,6 +425,8 @@
     _print_raw = (strstr(options(), "xml") ? 2 : 1);
   }
 
+  if (_optionsParsed) return;  // parse only once
+
   if (strstr(options(), "help")) {
     _print_help = true;
   }
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -31,6 +31,7 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/globals.hpp"
 
 jint EpsilonHeap::initialize() {
--- a/src/hotspot/share/gc/g1/g1Analytics.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Analytics.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -45,11 +45,11 @@
 };
 
 // all the same
-static double young_cards_per_entry_ratio_defaults[] = {
+static double young_card_merge_to_scan_ratio_defaults[] = {
   1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
 };
 
-static double young_only_cost_per_remset_card_ms_defaults[] = {
+static double young_only_cost_per_card_scan_ms_defaults[] = {
   0.015, 0.01, 0.01, 0.008, 0.008, 0.0055, 0.0055, 0.005
 };
 
@@ -62,7 +62,6 @@
   5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0
 };
 
-
 static double young_other_cost_per_region_ms_defaults[] = {
   0.3, 0.2, 0.2, 0.15, 0.15, 0.12, 0.12, 0.1
 };
@@ -81,13 +80,13 @@
     _rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
     _concurrent_refine_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
     _logged_cards_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _cost_per_logged_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _cost_scan_hcc_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _mixed_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _young_only_cost_per_remset_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _mixed_cost_per_remset_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
-    _cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _young_card_merge_to_scan_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _mixed_card_merge_to_scan_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _young_cost_per_card_scan_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _mixed_cost_per_card_scan_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _young_cost_per_card_merge_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _mixed_cost_per_card_merge_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+    _copy_cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
     _constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
     _young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
     _non_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
@@ -109,11 +108,10 @@
   _concurrent_refine_rate_ms_seq->add(1/cost_per_logged_card_ms_defaults[0]);
   // Some applications have very low rates for logging cards.
   _logged_cards_rate_ms_seq->add(0.0);
-  _cost_per_logged_card_ms_seq->add(cost_per_logged_card_ms_defaults[index]);
-  _cost_scan_hcc_seq->add(0.0);
-  _young_cards_per_entry_ratio_seq->add(young_cards_per_entry_ratio_defaults[index]);
-  _young_only_cost_per_remset_card_ms_seq->add(young_only_cost_per_remset_card_ms_defaults[index]);
-  _cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]);
+  _young_card_merge_to_scan_ratio_seq->add(young_card_merge_to_scan_ratio_defaults[index]);
+  _young_cost_per_card_scan_ms_seq->add(young_only_cost_per_card_scan_ms_defaults[index]);
+
+  _copy_cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]);
   _constant_other_time_ms_seq->add(constant_other_time_ms_defaults[index]);
   _young_other_cost_per_region_ms_seq->add(young_other_cost_per_region_ms_defaults[index]);
   _non_young_other_cost_per_region_ms_seq->add(non_young_other_cost_per_region_ms_defaults[index]);
@@ -123,12 +121,20 @@
   _concurrent_mark_cleanup_times_ms->add(0.20);
 }
 
-double G1Analytics::get_new_prediction(TruncatedSeq const* seq) const {
-  return _predictor->get_new_prediction(seq);
+bool G1Analytics::enough_samples_available(TruncatedSeq const* seq) const {
+  return seq->num() >= 3;
+}
+
+double G1Analytics::get_new_unit_prediction(TruncatedSeq const* seq) const {
+  return _predictor->get_new_unit_prediction(seq);
 }
 
 size_t G1Analytics::get_new_size_prediction(TruncatedSeq const* seq) const {
-  return (size_t)get_new_prediction(seq);
+  return (size_t)get_new_lower_zero_bound_prediction(seq);
+}
+
+double G1Analytics::get_new_lower_zero_bound_prediction(TruncatedSeq const* seq) const {
+  return _predictor->get_new_lower_zero_bound_prediction(seq);
 }
 
 int G1Analytics::num_alloc_rate_ms() const {
@@ -166,27 +172,27 @@
   _logged_cards_rate_ms_seq->add(cards_per_ms);
 }
 
-void G1Analytics::report_cost_per_logged_card_ms(double cost_per_logged_card_ms) {
-  _cost_per_logged_card_ms_seq->add(cost_per_logged_card_ms);
-}
-
-void G1Analytics::report_cost_scan_hcc(double cost_scan_hcc) {
-  _cost_scan_hcc_seq->add(cost_scan_hcc);
-}
-
-void G1Analytics::report_cost_per_remset_card_ms(double cost_per_remset_card_ms, bool for_young_gc) {
+void G1Analytics::report_cost_per_card_scan_ms(double cost_per_card_ms, bool for_young_gc) {
   if (for_young_gc) {
-    _young_only_cost_per_remset_card_ms_seq->add(cost_per_remset_card_ms);
+    _young_cost_per_card_scan_ms_seq->add(cost_per_card_ms);
   } else {
-    _mixed_cost_per_remset_card_ms_seq->add(cost_per_remset_card_ms);
+    _mixed_cost_per_card_scan_ms_seq->add(cost_per_card_ms);
   }
 }
 
-void G1Analytics::report_cards_per_entry_ratio(double cards_per_entry_ratio, bool for_young_gc) {
+void G1Analytics::report_cost_per_card_merge_ms(double cost_per_card_ms, bool for_young_gc) {
   if (for_young_gc) {
-    _young_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
+    _young_cost_per_card_merge_ms_seq->add(cost_per_card_ms);
   } else {
-    _mixed_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
+    _mixed_cost_per_card_merge_ms_seq->add(cost_per_card_ms);
+  }
+}
+
+void G1Analytics::report_card_merge_to_scan_ratio(double merge_to_scan_ratio, bool for_young_gc) {
+  if (for_young_gc) {
+    _young_card_merge_to_scan_ratio_seq->add(merge_to_scan_ratio);
+  } else {
+    _mixed_card_merge_to_scan_ratio_seq->add(merge_to_scan_ratio);
   }
 }
 
@@ -198,7 +204,7 @@
   if (mark_or_rebuild_in_progress) {
     _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
   } else {
-    _cost_per_byte_ms_seq->add(cost_per_byte_ms);
+    _copy_cost_per_byte_ms_seq->add(cost_per_byte_ms);
   }
 }
 
@@ -223,70 +229,50 @@
 }
 
 double G1Analytics::predict_alloc_rate_ms() const {
-  return get_new_prediction(_alloc_rate_ms_seq);
+  return get_new_lower_zero_bound_prediction(_alloc_rate_ms_seq);
 }
 
 double G1Analytics::predict_concurrent_refine_rate_ms() const {
-  return get_new_prediction(_concurrent_refine_rate_ms_seq);
+  return get_new_lower_zero_bound_prediction(_concurrent_refine_rate_ms_seq);
 }
 
 double G1Analytics::predict_logged_cards_rate_ms() const {
-  return get_new_prediction(_logged_cards_rate_ms_seq);
-}
-
-double G1Analytics::predict_cost_per_logged_card_ms() const {
-  return get_new_prediction(_cost_per_logged_card_ms_seq);
-}
-
-double G1Analytics::predict_scan_hcc_ms() const {
-  return get_new_prediction(_cost_scan_hcc_seq);
+  return get_new_lower_zero_bound_prediction(_logged_cards_rate_ms_seq);
 }
 
-double G1Analytics::predict_rs_update_time_ms(size_t pending_cards) const {
-  return pending_cards * predict_cost_per_logged_card_ms() + predict_scan_hcc_ms();
+double G1Analytics::predict_young_card_merge_to_scan_ratio() const {
+  return get_new_unit_prediction(_young_card_merge_to_scan_ratio_seq);
 }
 
-double G1Analytics::predict_young_cards_per_entry_ratio() const {
-  return get_new_prediction(_young_cards_per_entry_ratio_seq);
-}
-
-double G1Analytics::predict_mixed_cards_per_entry_ratio() const {
-  if (_mixed_cards_per_entry_ratio_seq->num() < 2) {
-    return predict_young_cards_per_entry_ratio();
+size_t G1Analytics::predict_scan_card_num(size_t rs_length, bool for_young_gc) const {
+  if (for_young_gc || !enough_samples_available(_mixed_card_merge_to_scan_ratio_seq)) {
+    return (size_t)(rs_length * predict_young_card_merge_to_scan_ratio());
   } else {
-    return get_new_prediction(_mixed_cards_per_entry_ratio_seq);
+    return (size_t)(rs_length * get_new_unit_prediction(_mixed_card_merge_to_scan_ratio_seq));
   }
 }
 
-size_t G1Analytics::predict_card_num(size_t rs_length, bool for_young_gc) const {
-  if (for_young_gc) {
-    return (size_t) (rs_length * predict_young_cards_per_entry_ratio());
+double G1Analytics::predict_card_merge_time_ms(size_t card_num, bool for_young_gc) const {
+  if (for_young_gc || !enough_samples_available(_mixed_cost_per_card_merge_ms_seq)) {
+    return card_num * get_new_lower_zero_bound_prediction(_young_cost_per_card_merge_ms_seq);
   } else {
-    return (size_t) (rs_length * predict_mixed_cards_per_entry_ratio());
+    return card_num * get_new_lower_zero_bound_prediction(_mixed_cost_per_card_merge_ms_seq);
   }
 }
 
-double G1Analytics::predict_rs_scan_time_ms(size_t card_num, bool for_young_gc) const {
-  if (for_young_gc) {
-    return card_num * get_new_prediction(_young_only_cost_per_remset_card_ms_seq);
+double G1Analytics::predict_card_scan_time_ms(size_t card_num, bool for_young_gc) const {
+  if (for_young_gc || !enough_samples_available(_mixed_cost_per_card_scan_ms_seq)) {
+    return card_num * get_new_lower_zero_bound_prediction(_young_cost_per_card_scan_ms_seq);
   } else {
-    return predict_mixed_rs_scan_time_ms(card_num);
-  }
-}
-
-double G1Analytics::predict_mixed_rs_scan_time_ms(size_t card_num) const {
-  if (_mixed_cost_per_remset_card_ms_seq->num() < 3) {
-    return card_num * get_new_prediction(_young_only_cost_per_remset_card_ms_seq);
-  } else {
-    return card_num * get_new_prediction(_mixed_cost_per_remset_card_ms_seq);
+    return card_num * get_new_lower_zero_bound_prediction(_mixed_cost_per_card_scan_ms_seq);
   }
 }
 
 double G1Analytics::predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const {
-  if (_cost_per_byte_ms_during_cm_seq->num() < 3) {
-    return (1.1 * bytes_to_copy) * get_new_prediction(_cost_per_byte_ms_seq);
+  if (!enough_samples_available(_cost_per_byte_ms_during_cm_seq)) {
+    return (1.1 * bytes_to_copy) * get_new_lower_zero_bound_prediction(_copy_cost_per_byte_ms_seq);
   } else {
-    return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_during_cm_seq);
+    return bytes_to_copy * get_new_lower_zero_bound_prediction(_cost_per_byte_ms_during_cm_seq);
   }
 }
 
@@ -294,36 +280,32 @@
   if (during_concurrent_mark) {
     return predict_object_copy_time_ms_during_cm(bytes_to_copy);
   } else {
-    return bytes_to_copy * get_new_prediction(_cost_per_byte_ms_seq);
+    return bytes_to_copy * get_new_lower_zero_bound_prediction(_copy_cost_per_byte_ms_seq);
   }
 }
 
-double G1Analytics::predict_cost_per_byte_ms() const {
-  return get_new_prediction(_cost_per_byte_ms_seq);
-}
-
 double G1Analytics::predict_constant_other_time_ms() const {
-  return get_new_prediction(_constant_other_time_ms_seq);
+  return get_new_lower_zero_bound_prediction(_constant_other_time_ms_seq);
 }
 
 double G1Analytics::predict_young_other_time_ms(size_t young_num) const {
-  return young_num * get_new_prediction(_young_other_cost_per_region_ms_seq);
+  return young_num * get_new_lower_zero_bound_prediction(_young_other_cost_per_region_ms_seq);
 }
 
 double G1Analytics::predict_non_young_other_time_ms(size_t non_young_num) const {
-  return non_young_num * get_new_prediction(_non_young_other_cost_per_region_ms_seq);
+  return non_young_num * get_new_lower_zero_bound_prediction(_non_young_other_cost_per_region_ms_seq);
 }
 
 double G1Analytics::predict_remark_time_ms() const {
-  return get_new_prediction(_concurrent_mark_remark_times_ms);
+  return get_new_lower_zero_bound_prediction(_concurrent_mark_remark_times_ms);
 }
 
 double G1Analytics::predict_cleanup_time_ms() const {
-  return get_new_prediction(_concurrent_mark_cleanup_times_ms);
+  return get_new_lower_zero_bound_prediction(_concurrent_mark_cleanup_times_ms);
 }
 
 size_t G1Analytics::predict_rs_length() const {
-  return get_new_size_prediction(_rs_length_seq) + get_new_prediction(_rs_length_diff_seq);
+  return get_new_size_prediction(_rs_length_seq) + get_new_size_prediction(_rs_length_diff_seq);
 }
 
 size_t G1Analytics::predict_pending_cards() const {
--- a/src/hotspot/share/gc/g1/g1Analytics.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Analytics.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -48,13 +48,21 @@
   TruncatedSeq* _rs_length_diff_seq;
   TruncatedSeq* _concurrent_refine_rate_ms_seq;
   TruncatedSeq* _logged_cards_rate_ms_seq;
-  TruncatedSeq* _cost_per_logged_card_ms_seq;
-  TruncatedSeq* _cost_scan_hcc_seq;
-  TruncatedSeq* _young_cards_per_entry_ratio_seq;
-  TruncatedSeq* _mixed_cards_per_entry_ratio_seq;
-  TruncatedSeq* _young_only_cost_per_remset_card_ms_seq;
-  TruncatedSeq* _mixed_cost_per_remset_card_ms_seq;
-  TruncatedSeq* _cost_per_byte_ms_seq;
+  // The ratio between the number of merged cards and actually scanned cards, for
+  // young-only and mixed gcs.
+  TruncatedSeq* _young_card_merge_to_scan_ratio_seq;
+  TruncatedSeq* _mixed_card_merge_to_scan_ratio_seq;
+
+  // The cost to scan a card during young-only and mixed gcs in ms.
+  TruncatedSeq* _young_cost_per_card_scan_ms_seq;
+  TruncatedSeq* _mixed_cost_per_card_scan_ms_seq;
+
+  // The cost to merge a card during young-only and mixed gcs in ms.
+  TruncatedSeq* _young_cost_per_card_merge_ms_seq;
+  TruncatedSeq* _mixed_cost_per_card_merge_ms_seq;
+
+  // The cost to copy a byte in ms.
+  TruncatedSeq* _copy_cost_per_byte_ms_seq;
   TruncatedSeq* _constant_other_time_ms_seq;
   TruncatedSeq* _young_other_cost_per_region_ms_seq;
   TruncatedSeq* _non_young_other_cost_per_region_ms_seq;
@@ -72,8 +80,13 @@
   double _recent_avg_pause_time_ratio;
   double _last_pause_time_ratio;
 
-  double get_new_prediction(TruncatedSeq const* seq) const;
+  // Returns whether the sequence have enough samples to get a "good" prediction.
+  // The constant used is random but "small".
+  bool enough_samples_available(TruncatedSeq const* seq) const;
+
+  double get_new_unit_prediction(TruncatedSeq const* seq) const;
   size_t get_new_size_prediction(TruncatedSeq const* seq) const;
+  double get_new_lower_zero_bound_prediction(TruncatedSeq const* seq) const;
 
 public:
   G1Analytics(const G1Predictions* predictor);
@@ -103,10 +116,9 @@
   void report_alloc_rate_ms(double alloc_rate);
   void report_concurrent_refine_rate_ms(double cards_per_ms);
   void report_logged_cards_rate_ms(double cards_per_ms);
-  void report_cost_per_logged_card_ms(double cost_per_logged_card_ms);
-  void report_cost_scan_hcc(double cost_scan_hcc);
-  void report_cost_per_remset_card_ms(double cost_per_remset_card_ms, bool for_young_gc);
-  void report_cards_per_entry_ratio(double cards_per_entry_ratio, bool for_young_gc);
+  void report_cost_per_card_scan_ms(double cost_per_remset_card_ms, bool for_young_gc);
+  void report_cost_per_card_merge_ms(double cost_per_card_ms, bool for_young_gc);
+  void report_card_merge_to_scan_ratio(double cards_per_entry_ratio, bool for_young_gc);
   void report_rs_length_diff(double rs_length_diff);
   void report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress);
   void report_young_other_cost_per_region_ms(double other_cost_per_region_ms);
@@ -120,21 +132,14 @@
 
   double predict_concurrent_refine_rate_ms() const;
   double predict_logged_cards_rate_ms() const;
-  double predict_cost_per_logged_card_ms() const;
-
-  double predict_scan_hcc_ms() const;
+  double predict_young_card_merge_to_scan_ratio() const;
 
-  double predict_rs_update_time_ms(size_t pending_cards) const;
-
-  double predict_young_cards_per_entry_ratio() const;
+  double predict_mixed_card_merge_to_scan_ratio() const;
 
-  double predict_mixed_cards_per_entry_ratio() const;
-
-  size_t predict_card_num(size_t rs_length, bool for_young_gc) const;
+  size_t predict_scan_card_num(size_t rs_length, bool for_young_gc) const;
 
-  double predict_rs_scan_time_ms(size_t card_num, bool for_young_gc) const;
-
-  double predict_mixed_rs_scan_time_ms(size_t card_num) const;
+  double predict_card_merge_time_ms(size_t card_num, bool for_young_gc) const;
+  double predict_card_scan_time_ms(size_t card_num, bool for_young_gc) const;
 
   double predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const;
 
@@ -153,8 +158,6 @@
   size_t predict_rs_length() const;
   size_t predict_pending_cards() const;
 
-  double predict_cost_per_byte_ms() const;
-
   // Add a new GC of the given duration and end time to the record.
   void update_recent_gc_times(double end_time_sec, double elapsed_ms);
   void compute_pause_time_ratio(double interval_ms, double pause_time_ms);
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,6 +37,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/macros.hpp"
 #ifdef COMPILER1
--- a/src/hotspot/share/gc/g1/g1CardTable.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CardTable.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,8 +27,6 @@
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/shared/memset_with_concurrent_readers.hpp"
 #include "logging/log.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 
 void G1CardTable::g1_mark_as_young(const MemRegion& mr) {
   CardValue *const first = byte_for(mr.start());
--- a/src/hotspot/share/gc/g1/g1CardTable.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CardTable.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -92,12 +92,16 @@
     return pointer_delta(p, _byte_map, sizeof(CardValue));
   }
 
-  // Mark the given card as Dirty if it is Clean.
-  inline void mark_clean_as_dirty(size_t card_index);
+  // Mark the given card as Dirty if it is Clean. Returns the number of dirtied
+  // cards that were not yet dirty. This result may be inaccurate as it does not
+  // perform the dirtying atomically.
+  inline size_t mark_clean_as_dirty(size_t card_index);
 
   // Change Clean cards in a (large) area on the card table as Dirty, preserving
   // already scanned cards. Assumes that most cards in that area are Clean.
-  inline void mark_region_dirty(size_t start_card_index, size_t num_cards);
+  // Returns the number of dirtied cards that were not yet dirty. This result may
+  // be inaccurate as it does not perform the dirtying atomically.
+  inline size_t mark_region_dirty(size_t start_card_index, size_t num_cards);
 
   // Mark the given range of cards as Scanned. All of these cards must be Dirty.
   inline void mark_as_scanned(size_t start_card_index, size_t num_cards);
--- a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,17 +33,21 @@
   return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - card_shift));
 }
 
-inline void G1CardTable::mark_clean_as_dirty(size_t card_index) {
+inline size_t G1CardTable::mark_clean_as_dirty(size_t card_index) {
   CardValue value = _byte_map[card_index];
   if (value == clean_card_val()) {
     _byte_map[card_index] = dirty_card_val();
+    return 1;
   }
+  return 0;
 }
 
-inline void G1CardTable::mark_region_dirty(size_t start_card_index, size_t num_cards) {
+inline size_t G1CardTable::mark_region_dirty(size_t start_card_index, size_t num_cards) {
   assert(is_aligned(start_card_index, sizeof(size_t)), "Start card index must be aligned.");
   assert(is_aligned(num_cards, sizeof(size_t)), "Number of cards to change must be evenly divisible.");
 
+  size_t result = 0;
+
   size_t const num_chunks = num_cards / sizeof(size_t);
 
   size_t* cur_word = (size_t*)&_byte_map[start_card_index];
@@ -52,6 +56,7 @@
     size_t value = *cur_word;
     if (value == WordAllClean) {
       *cur_word = WordAllDirty;
+      result += sizeof(value);
     } else if (value == WordAllDirty) {
       // do nothing.
     } else {
@@ -61,12 +66,15 @@
         CardValue value = *cur;
         if (value == clean_card_val()) {
           *cur = dirty_card_val();
+          result++;
         }
         cur++;
       }
     }
     cur_word++;
   }
+
+  return result;
 }
 
 inline void G1CardTable::mark_as_scanned(size_t start_card_index, size_t num_cards) {
--- a/src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,7 @@
 #include "memory/iterator.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/stack.inline.hpp"
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1,4 +1,4 @@
-/*
+ /*
  * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -2777,112 +2777,6 @@
          G1EagerReclaimHumongousObjects && rem_set->is_empty();
 }
 
-class RegisterRegionsWithRegionAttrTableClosure : public HeapRegionClosure {
- private:
-  size_t _total_humongous;
-  size_t _candidate_humongous;
-
-  bool humongous_region_is_candidate(G1CollectedHeap* g1h, HeapRegion* region) const {
-    assert(region->is_starts_humongous(), "Must start a humongous object");
-
-    oop obj = oop(region->bottom());
-
-    // Dead objects cannot be eager reclaim candidates. Due to class
-    // unloading it is unsafe to query their classes so we return early.
-    if (g1h->is_obj_dead(obj, region)) {
-      return false;
-    }
-
-    // If we do not have a complete remembered set for the region, then we can
-    // not be sure that we have all references to it.
-    if (!region->rem_set()->is_complete()) {
-      return false;
-    }
-    // Candidate selection must satisfy the following constraints
-    // while concurrent marking is in progress:
-    //
-    // * In order to maintain SATB invariants, an object must not be
-    // reclaimed if it was allocated before the start of marking and
-    // has not had its references scanned.  Such an object must have
-    // its references (including type metadata) scanned to ensure no
-    // live objects are missed by the marking process.  Objects
-    // allocated after the start of concurrent marking don't need to
-    // be scanned.
-    //
-    // * An object must not be reclaimed if it is on the concurrent
-    // mark stack.  Objects allocated after the start of concurrent
-    // marking are never pushed on the mark stack.
-    //
-    // Nominating only objects allocated after the start of concurrent
-    // marking is sufficient to meet both constraints.  This may miss
-    // some objects that satisfy the constraints, but the marking data
-    // structures don't support efficiently performing the needed
-    // additional tests or scrubbing of the mark stack.
-    //
-    // However, we presently only nominate is_typeArray() objects.
-    // A humongous object containing references induces remembered
-    // set entries on other regions.  In order to reclaim such an
-    // object, those remembered sets would need to be cleaned up.
-    //
-    // We also treat is_typeArray() objects specially, allowing them
-    // to be reclaimed even if allocated before the start of
-    // concurrent mark.  For this we rely on mark stack insertion to
-    // exclude is_typeArray() objects, preventing reclaiming an object
-    // that is in the mark stack.  We also rely on the metadata for
-    // such objects to be built-in and so ensured to be kept live.
-    // Frequent allocation and drop of large binary blobs is an
-    // important use case for eager reclaim, and this special handling
-    // may reduce needed headroom.
-
-    return obj->is_typeArray() &&
-           g1h->is_potential_eager_reclaim_candidate(region);
-  }
-
- public:
-  RegisterRegionsWithRegionAttrTableClosure()
-  : _total_humongous(0),
-    _candidate_humongous(0) {
-  }
-
-  virtual bool do_heap_region(HeapRegion* r) {
-    G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-    if (!r->is_starts_humongous()) {
-      g1h->register_region_with_region_attr(r);
-      return false;
-    }
-
-    bool is_candidate = humongous_region_is_candidate(g1h, r);
-    uint rindex = r->hrm_index();
-    g1h->set_humongous_reclaim_candidate(rindex, is_candidate);
-    if (is_candidate) {
-      g1h->register_humongous_region_with_region_attr(rindex);
-      _candidate_humongous++;
-      // We will later handle the remembered sets of these regions.
-    } else {
-      g1h->register_region_with_region_attr(r);
-    }
-    _total_humongous++;
-
-    return false;
-  }
-
-  size_t total_humongous() const { return _total_humongous; }
-  size_t candidate_humongous() const { return _candidate_humongous; }
-};
-
-void G1CollectedHeap::register_regions_with_region_attr() {
-  Ticks start = Ticks::now();
-
-  RegisterRegionsWithRegionAttrTableClosure cl;
-  heap_region_iterate(&cl);
-
-  phase_times()->record_register_regions((Ticks::now() - start).seconds() * 1000.0,
-                                         cl.total_humongous(),
-                                         cl.candidate_humongous());
-  _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
-}
-
 #ifndef PRODUCT
 void G1CollectedHeap::verify_region_attr_remset_update() {
   class VerifyRegionAttrRemSet : public HeapRegionClosure {
@@ -3699,6 +3593,145 @@
   phase_times()->record_or_add_time_secs(G1GCPhaseTimes::MergePSS, 0 /* worker_id */, (Ticks::now() - start).seconds());
 }
 
+class G1PrepareEvacuationTask : public AbstractGangTask {
+  class G1PrepareRegionsClosure : public HeapRegionClosure {
+    G1CollectedHeap* _g1h;
+    G1PrepareEvacuationTask* _parent_task;
+    size_t _worker_humongous_total;
+    size_t _worker_humongous_candidates;
+
+    bool humongous_region_is_candidate(HeapRegion* region) const {
+      assert(region->is_starts_humongous(), "Must start a humongous object");
+
+      oop obj = oop(region->bottom());
+
+      // Dead objects cannot be eager reclaim candidates. Due to class
+      // unloading it is unsafe to query their classes so we return early.
+      if (_g1h->is_obj_dead(obj, region)) {
+        return false;
+      }
+
+      // If we do not have a complete remembered set for the region, then we can
+      // not be sure that we have all references to it.
+      if (!region->rem_set()->is_complete()) {
+        return false;
+      }
+      // Candidate selection must satisfy the following constraints
+      // while concurrent marking is in progress:
+      //
+      // * In order to maintain SATB invariants, an object must not be
+      // reclaimed if it was allocated before the start of marking and
+      // has not had its references scanned.  Such an object must have
+      // its references (including type metadata) scanned to ensure no
+      // live objects are missed by the marking process.  Objects
+      // allocated after the start of concurrent marking don't need to
+      // be scanned.
+      //
+      // * An object must not be reclaimed if it is on the concurrent
+      // mark stack.  Objects allocated after the start of concurrent
+      // marking are never pushed on the mark stack.
+      //
+      // Nominating only objects allocated after the start of concurrent
+      // marking is sufficient to meet both constraints.  This may miss
+      // some objects that satisfy the constraints, but the marking data
+      // structures don't support efficiently performing the needed
+      // additional tests or scrubbing of the mark stack.
+      //
+      // However, we presently only nominate is_typeArray() objects.
+      // A humongous object containing references induces remembered
+      // set entries on other regions.  In order to reclaim such an
+      // object, those remembered sets would need to be cleaned up.
+      //
+      // We also treat is_typeArray() objects specially, allowing them
+      // to be reclaimed even if allocated before the start of
+      // concurrent mark.  For this we rely on mark stack insertion to
+      // exclude is_typeArray() objects, preventing reclaiming an object
+      // that is in the mark stack.  We also rely on the metadata for
+      // such objects to be built-in and so ensured to be kept live.
+      // Frequent allocation and drop of large binary blobs is an
+      // important use case for eager reclaim, and this special handling
+      // may reduce needed headroom.
+
+      return obj->is_typeArray() &&
+             _g1h->is_potential_eager_reclaim_candidate(region);
+    }
+
+  public:
+    G1PrepareRegionsClosure(G1CollectedHeap* g1h, G1PrepareEvacuationTask* parent_task) :
+      _g1h(g1h),
+      _parent_task(parent_task),
+      _worker_humongous_total(0),
+      _worker_humongous_candidates(0) { }
+
+    ~G1PrepareRegionsClosure() {
+      _parent_task->add_humongous_candidates(_worker_humongous_candidates);
+      _parent_task->add_humongous_total(_worker_humongous_total);
+    }
+
+    virtual bool do_heap_region(HeapRegion* hr) {
+      // First prepare the region for scanning
+      _g1h->rem_set()->prepare_region_for_scan(hr);
+
+      // Now check if region is a humongous candidate
+      if (!hr->is_starts_humongous()) {
+        _g1h->register_region_with_region_attr(hr);
+        return false;
+      }
+
+      uint index = hr->hrm_index();
+      if (humongous_region_is_candidate(hr)) {
+        _g1h->set_humongous_reclaim_candidate(index, true);
+        _g1h->register_humongous_region_with_region_attr(index);
+        _worker_humongous_candidates++;
+        // We will later handle the remembered sets of these regions.
+      } else {
+        _g1h->set_humongous_reclaim_candidate(index, false);
+        _g1h->register_region_with_region_attr(hr);
+      }
+      _worker_humongous_total++;
+
+      return false;
+    }
+  };
+
+  G1CollectedHeap* _g1h;
+  HeapRegionClaimer _claimer;
+  volatile size_t _humongous_total;
+  volatile size_t _humongous_candidates;
+public:
+  G1PrepareEvacuationTask(G1CollectedHeap* g1h) :
+    AbstractGangTask("Prepare Evacuation"),
+    _g1h(g1h),
+    _claimer(_g1h->workers()->active_workers()),
+    _humongous_total(0),
+    _humongous_candidates(0) { }
+
+  ~G1PrepareEvacuationTask() {
+    _g1h->set_has_humongous_reclaim_candidate(_humongous_candidates > 0);
+  }
+
+  void work(uint worker_id) {
+    G1PrepareRegionsClosure cl(_g1h, this);
+    _g1h->heap_region_par_iterate_from_worker_offset(&cl, &_claimer, worker_id);
+  }
+
+  void add_humongous_candidates(size_t candidates) {
+    Atomic::add(&_humongous_candidates, candidates);
+  }
+
+  void add_humongous_total(size_t total) {
+    Atomic::add(&_humongous_total, total);
+  }
+
+  size_t humongous_candidates() {
+    return _humongous_candidates;
+  }
+
+  size_t humongous_total() {
+    return _humongous_total;
+  }
+};
+
 void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
   _bytes_used_during_gc = 0;
 
@@ -3718,9 +3751,16 @@
     phase_times()->record_prepare_heap_roots_time_ms((Ticks::now() - start).seconds() * 1000.0);
   }
 
-  register_regions_with_region_attr();
+  {
+    G1PrepareEvacuationTask g1_prep_task(this);
+    Tickspan task_time = run_task(&g1_prep_task);
+
+    phase_times()->record_register_regions(task_time.seconds() * 1000.0,
+                                           g1_prep_task.humongous_total(),
+                                           g1_prep_task.humongous_candidates());
+  }
+
   assert(_verifier->check_region_attr_table(), "Inconsistency in the region attributes table.");
-
   _preserved_marks_set.assert_empty();
 
 #if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -593,6 +593,7 @@
   // These are only valid for starts_humongous regions.
   inline void set_humongous_reclaim_candidate(uint region, bool value);
   inline bool is_humongous_reclaim_candidate(uint region);
+  inline void set_has_humongous_reclaim_candidate(bool value);
 
   // Remove from the reclaim candidate set.  Also remove from the
   // collection set so that later encounters avoid the slow path.
@@ -600,8 +601,7 @@
 
   // Register the given region to be part of the collection set.
   inline void register_humongous_region_with_region_attr(uint index);
-  // Update region attributes table with information about all regions.
-  void register_regions_with_region_attr();
+
   // We register a region with the fast "in collection set" test. We
   // simply set to true the array slot corresponding to this region.
   void register_young_region_with_region_attr(HeapRegion* r) {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,7 +34,6 @@
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/heapRegionSet.inline.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
-#include "runtime/orderAccess.hpp"
 
 G1GCPhaseTimes* G1CollectedHeap::phase_times() const {
   return _policy->phase_times();
@@ -181,7 +180,7 @@
 
 void G1CollectedHeap::register_old_region_with_region_attr(HeapRegion* r) {
   _region_attr.set_in_old(r->hrm_index(), r->rem_set()->is_tracked());
-  _rem_set->prepare_for_scan_heap_roots(r->hrm_index());
+  _rem_set->exclude_region_from_scan(r->hrm_index());
 }
 
 void G1CollectedHeap::register_optional_region_with_region_attr(HeapRegion* r) {
@@ -299,6 +298,10 @@
   return _humongous_reclaim_candidates.is_candidate(region);
 }
 
+inline void G1CollectedHeap::set_has_humongous_reclaim_candidate(bool value) {
+  _has_humongous_reclaim_candidates = value;
+}
+
 inline void G1CollectedHeap::set_humongous_is_live(oop obj) {
   uint region = addr_to_region((HeapWord*)obj);
   // Clear the flag in the humongous_reclaim_candidates table.  Also
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,12 +27,14 @@
 #include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectionSetCandidates.hpp"
 #include "gc/g1/g1CollectorState.hpp"
+#include "gc/g1/g1HotCardCache.hpp"
 #include "gc/g1/g1ParScanThreadState.hpp"
 #include "gc/g1/g1Policy.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/heapRegionSet.hpp"
 #include "logging/logStream.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/quickSort.hpp"
@@ -276,19 +278,6 @@
   assert(hr->is_young(), "invariant");
   assert(_inc_build_state == Active, "Precondition");
 
-  size_t collection_set_length = _collection_set_cur_length;
-  // We use UINT_MAX as "invalid" marker in verification.
-  assert(collection_set_length < (UINT_MAX - 1),
-         "Collection set is too large with " SIZE_FORMAT " entries", collection_set_length);
-  hr->set_young_index_in_cset((uint)collection_set_length + 1);
-
-  _collection_set_regions[collection_set_length] = hr->hrm_index();
-  // Concurrent readers must observe the store of the value in the array before an
-  // update to the length field.
-  OrderAccess::storestore();
-  _collection_set_cur_length++;
-  assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set larger than maximum allowed.");
-
   // This routine is used when:
   // * adding survivor regions to the incremental cset at the end of an
   //   evacuation pause or
@@ -323,6 +312,19 @@
 
   assert(!hr->in_collection_set(), "invariant");
   _g1h->register_young_region_with_region_attr(hr);
+
+  size_t collection_set_length = _collection_set_cur_length;
+  // We use UINT_MAX as "invalid" marker in verification.
+  assert(collection_set_length < (UINT_MAX - 1),
+         "Collection set is too large with " SIZE_FORMAT " entries", collection_set_length);
+  hr->set_young_index_in_cset((uint)collection_set_length + 1);
+
+  _collection_set_regions[collection_set_length] = hr->hrm_index();
+  // Concurrent readers must observe the store of the value in the array before an
+  // update to the length field.
+  OrderAccess::storestore();
+  _collection_set_cur_length++;
+  assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set larger than maximum allowed.");
 }
 
 void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
@@ -409,7 +411,7 @@
   guarantee(target_pause_time_ms > 0.0,
             "target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
 
-  size_t pending_cards = _policy->pending_cards_at_gc_start();
+  size_t pending_cards = _policy->pending_cards_at_gc_start() + _g1h->hot_card_cache()->num_entries();
   double base_time_ms = _policy->predict_base_elapsed_time_ms(pending_cards);
   double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
 
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -62,6 +62,7 @@
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/align.hpp"
@@ -2587,7 +2588,8 @@
   // and do_marking_step() is not being called serially.
   bool do_stealing = do_termination && !is_serial;
 
-  double diff_prediction_ms = _g1h->policy()->predictor().get_new_prediction(&_marking_step_diff_ms);
+  G1Predictions const& predictor = _g1h->policy()->predictor();
+  double diff_prediction_ms = predictor.get_new_lower_zero_bound_prediction(&_marking_step_diff_ms);
   _time_target_ms = time_target_ms - diff_prediction_ms;
 
   // set up the variables that are used in the work-based scheme to
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,9 +34,9 @@
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/shared/suspendibleThreadSet.hpp"
 #include "gc/shared/workgroup.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/flags/flagSetting.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -72,6 +72,8 @@
   _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_fine, MergeRSMergedFine);
   _merge_rs_merged_coarse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Coarse:");
   _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_coarse, MergeRSMergedCoarse);
+  _merge_rs_dirty_cards = new WorkerDataArray<size_t>(max_gc_threads, "Dirty Cards:");
+  _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_dirty_cards, MergeRSDirtyCards);
 
   _gc_par_phases[OptMergeRS] = new WorkerDataArray<double>(max_gc_threads, "Optional Remembered Sets (ms):");
   _opt_merge_rs_merged_sparse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Sparse:");
@@ -80,6 +82,8 @@
   _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_fine, MergeRSMergedFine);
   _opt_merge_rs_merged_coarse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Coarse:");
   _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_coarse, MergeRSMergedCoarse);
+  _opt_merge_rs_dirty_cards = new WorkerDataArray<size_t>(max_gc_threads, "Dirty Cards:");
+  _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_dirty_cards, MergeRSDirtyCards);
 
   _gc_par_phases[MergeLB] = new WorkerDataArray<double>(max_gc_threads, "Log Buffers (ms):");
   if (G1HotCardCache::default_use_cache()) {
@@ -304,10 +308,16 @@
 
 // return the average time for a phase in milliseconds
 double G1GCPhaseTimes::average_time_ms(GCParPhases phase) {
+  if (_gc_par_phases[phase] == NULL) {
+    return 0.0;
+  }
   return _gc_par_phases[phase]->average() * 1000.0;
 }
 
 size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase, uint index) {
+  if (_gc_par_phases[phase] == NULL) {
+    return 0;
+  }
   assert(_gc_par_phases[phase]->thread_work_items(index) != NULL, "No sub count");
   return _gc_par_phases[phase]->thread_work_items(index)->sum();
 }
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -88,7 +88,8 @@
   enum GCMergeRSWorkTimes {
     MergeRSMergedSparse,
     MergeRSMergedFine,
-    MergeRSMergedCoarse
+    MergeRSMergedCoarse,
+    MergeRSDirtyCards
   };
 
   enum GCScanHRWorkItems {
@@ -124,6 +125,7 @@
   WorkerDataArray<size_t>* _merge_rs_merged_sparse;
   WorkerDataArray<size_t>* _merge_rs_merged_fine;
   WorkerDataArray<size_t>* _merge_rs_merged_coarse;
+  WorkerDataArray<size_t>* _merge_rs_dirty_cards;
 
   WorkerDataArray<size_t>* _merge_hcc_dirty_cards;
   WorkerDataArray<size_t>* _merge_hcc_skipped_cards;
@@ -138,6 +140,7 @@
   WorkerDataArray<size_t>* _opt_merge_rs_merged_sparse;
   WorkerDataArray<size_t>* _opt_merge_rs_merged_fine;
   WorkerDataArray<size_t>* _opt_merge_rs_merged_coarse;
+  WorkerDataArray<size_t>* _opt_merge_rs_dirty_cards;
 
   WorkerDataArray<size_t>* _opt_scan_hr_scanned_cards;
   WorkerDataArray<size_t>* _opt_scan_hr_scanned_blocks;
--- a/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,7 +32,7 @@
 G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
   _g1h(g1h), _use_cache(false), _card_counts(g1h),
   _hot_cache(NULL), _hot_cache_size(0), _hot_cache_par_chunk_size(0),
-  _hot_cache_idx(0), _hot_cache_par_claimed_idx(0)
+  _hot_cache_idx(0), _hot_cache_par_claimed_idx(0), _cache_wrapped_around(false)
 {}
 
 void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) {
@@ -48,6 +48,8 @@
     _hot_cache_par_chunk_size = ClaimChunkSize;
     _hot_cache_par_claimed_idx = 0;
 
+    _cache_wrapped_around = false;
+
     _card_counts.initialize(card_counts_storage);
   }
 }
@@ -69,6 +71,11 @@
   }
   // Otherwise, the card is hot.
   size_t index = Atomic::add(&_hot_cache_idx, 1u) - 1;
+  if (index == _hot_cache_size) {
+    // Can use relaxed store because all racing threads are writing the same
+    // value and there aren't any concurrent readers.
+    Atomic::store(&_cache_wrapped_around, true);
+  }
   size_t masked_index = index & (_hot_cache_size - 1);
   CardValue* current_ptr = _hot_cache[masked_index];
 
--- a/src/hotspot/share/gc/g1/g1HotCardCache.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -81,6 +81,11 @@
 
   char _pad_after[DEFAULT_CACHE_LINE_SIZE];
 
+  // Records whether insertion overflowed the hot card cache at least once. This
+  // avoids the need for a separate atomic counter of how many valid entries are
+  // in the HCC.
+  volatile bool _cache_wrapped_around;
+
   // The number of cached cards a thread claims when flushing the cache
   static const int ClaimChunkSize = 32;
 
@@ -125,13 +130,17 @@
     assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
     assert(Thread::current()->is_VM_thread(), "Current thread should be the VMthread");
     if (default_use_cache()) {
-        reset_hot_cache_internal();
+      reset_hot_cache_internal();
     }
   }
 
   // Zeros the values in the card counts table for the given region
   void reset_card_counts(HeapRegion* hr);
 
+  // Number of entries in the HCC.
+  size_t num_entries() const {
+    return _cache_wrapped_around ? _hot_cache_size : _hot_cache_idx + 1;
+  }
  private:
   void reset_hot_cache_internal() {
     assert(_hot_cache != NULL, "Logic");
@@ -139,6 +148,7 @@
     for (size_t i = 0; i < _hot_cache_size; i++) {
       _hot_cache[i] = NULL;
     }
+    _cache_wrapped_around = false;
   }
 };
 
--- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -113,6 +113,10 @@
     );
 }
 
+double G1AdaptiveIHOPControl::get_new_prediction(TruncatedSeq const* seq) const {
+  return _predictor->get_new_lower_zero_bound_prediction(seq);
+}
+
 bool G1AdaptiveIHOPControl::have_enough_data_for_prediction() const {
   return ((size_t)_marking_times_s.num() >= G1AdaptiveIHOPNumInitialSamples) &&
          ((size_t)_allocation_rate_s.num() >= G1AdaptiveIHOPNumInitialSamples);
@@ -120,8 +124,8 @@
 
 size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() {
   if (have_enough_data_for_prediction()) {
-    double pred_marking_time = _predictor->get_new_prediction(&_marking_times_s);
-    double pred_promotion_rate = _predictor->get_new_prediction(&_allocation_rate_s);
+    double pred_marking_time = get_new_prediction(&_marking_times_s);
+    double pred_promotion_rate = get_new_prediction(&_allocation_rate_s);
     size_t pred_promotion_size = (size_t)(pred_marking_time * pred_promotion_rate);
 
     size_t predicted_needed_bytes_during_marking =
@@ -168,8 +172,8 @@
                       actual_target,
                       G1CollectedHeap::heap()->used(),
                       _last_unrestrained_young_size,
-                      _predictor->get_new_prediction(&_allocation_rate_s),
-                      _predictor->get_new_prediction(&_marking_times_s) * 1000.0,
+                      get_new_prediction(&_allocation_rate_s),
+                      get_new_prediction(&_marking_times_s) * 1000.0,
                       have_enough_data_for_prediction() ? "true" : "false");
 }
 
@@ -179,7 +183,7 @@
                                           actual_target_threshold(),
                                           G1CollectedHeap::heap()->used(),
                                           _last_unrestrained_young_size,
-                                          _predictor->get_new_prediction(&_allocation_rate_s),
-                                          _predictor->get_new_prediction(&_marking_times_s),
+                                          get_new_prediction(&_allocation_rate_s),
+                                          get_new_prediction(&_marking_times_s),
                                           have_enough_data_for_prediction());
 }
--- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -123,6 +123,9 @@
   // as there is no marking or mixed gc that could impact its size too much.
   size_t _last_unrestrained_young_size;
 
+  // Get a new prediction bounded below by zero from the given sequence.
+  double get_new_prediction(TruncatedSeq const* seq) const;
+
   bool have_enough_data_for_prediction() const;
 
   // The "actual" target threshold the algorithm wants to keep during and at the
--- a/src/hotspot/share/gc/g1/g1ParallelCleaning.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ParallelCleaning.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 
 #include "gc/g1/g1ParallelCleaning.hpp"
+#include "runtime/atomic.hpp"
 #if INCLUDE_JVMCI
 #include "jvmci/jvmci.hpp"
 #endif
--- a/src/hotspot/share/gc/g1/g1Policy.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -329,9 +329,8 @@
   const double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
   const double survivor_regions_evac_time = predict_survivor_regions_evac_time();
   const size_t pending_cards = _analytics->predict_pending_cards();
-  const size_t scanned_cards = _analytics->predict_card_num(rs_length, true /* for_young_gc */);
   const double base_time_ms =
-    predict_base_elapsed_time_ms(pending_cards, scanned_cards) +
+    predict_base_elapsed_time_ms(pending_cards, rs_length) +
     survivor_regions_evac_time;
   const uint available_free_regions = _free_regions_at_end_of_collection;
   const uint base_free_regions =
@@ -713,67 +712,58 @@
   }
 
   _short_lived_surv_rate_group->start_adding_regions();
-  // Do that for any other surv rate groups
 
-  double scan_hcc_time_ms = G1HotCardCache::default_use_cache() ? average_time_ms(G1GCPhaseTimes::MergeHCC) : 0.0;
-
+  double merge_hcc_time_ms = average_time_ms(G1GCPhaseTimes::MergeHCC);
   if (update_stats) {
-    double cost_per_logged_card = 0.0;
-    size_t const pending_logged_cards = p->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBDirtyCards);
-    if (pending_logged_cards > 0) {
-      cost_per_logged_card = logged_cards_processing_time() / pending_logged_cards;
-      _analytics->report_cost_per_logged_card_ms(cost_per_logged_card);
-    }
-    _analytics->report_cost_scan_hcc(scan_hcc_time_ms);
+    size_t const total_log_buffer_cards = p->sum_thread_work_items(G1GCPhaseTimes::MergeHCC, G1GCPhaseTimes::MergeHCCDirtyCards) +
+                                          p->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBDirtyCards);
+    // Update prediction for card merge; MergeRSDirtyCards includes the cards from the Eager Reclaim phase.
+    size_t const total_cards_merged = p->sum_thread_work_items(G1GCPhaseTimes::MergeRS, G1GCPhaseTimes::MergeRSDirtyCards) +
+                                      p->sum_thread_work_items(G1GCPhaseTimes::OptMergeRS, G1GCPhaseTimes::MergeRSDirtyCards) +
+                                      total_log_buffer_cards;
 
-    size_t const total_cards_scanned = p->sum_thread_work_items(G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ScanHRScannedCards) +
-                                       p->sum_thread_work_items(G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::ScanHRScannedCards);
-    size_t remset_cards_scanned = 0;
-    // There might have been duplicate log buffer entries in the queues which could
-    // increase this value beyond the cards scanned. In this case attribute all cards
-    // to the log buffers.
-    if (pending_logged_cards <= total_cards_scanned) {
-      remset_cards_scanned = total_cards_scanned - pending_logged_cards;
+    // The threshold for the number of cards in a given sampling which we consider
+    // large enough so that the impact from setup and other costs is negligible.
+    size_t const CardsNumSamplingThreshold = 10;
+
+    if (total_cards_merged > CardsNumSamplingThreshold) {
+      double avg_time_merge_cards = average_time_ms(G1GCPhaseTimes::MergeER) +
+                                    average_time_ms(G1GCPhaseTimes::MergeRS) +
+                                    average_time_ms(G1GCPhaseTimes::MergeHCC) +
+                                    average_time_ms(G1GCPhaseTimes::MergeLB) +
+                                    average_time_ms(G1GCPhaseTimes::OptMergeRS);
+      _analytics->report_cost_per_card_merge_ms(avg_time_merge_cards / total_cards_merged, this_pause_was_young_only);
     }
 
-    double cost_per_remset_card_ms = 0.0;
-    if (remset_cards_scanned > 10) {
-      double avg_time_remset_scan = ((average_time_ms(G1GCPhaseTimes::ScanHR) + average_time_ms(G1GCPhaseTimes::OptScanHR)) *
-                                     remset_cards_scanned / total_cards_scanned) +
-                                     average_time_ms(G1GCPhaseTimes::MergeER) +
-                                     average_time_ms(G1GCPhaseTimes::MergeRS) +
-                                     average_time_ms(G1GCPhaseTimes::OptMergeRS);
+    // Update prediction for card scan
+    size_t const total_cards_scanned = p->sum_thread_work_items(G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ScanHRScannedCards) +
+                                       p->sum_thread_work_items(G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::ScanHRScannedCards);
 
-      cost_per_remset_card_ms = avg_time_remset_scan / remset_cards_scanned;
-      _analytics->report_cost_per_remset_card_ms(cost_per_remset_card_ms, this_pause_was_young_only);
-    }
+    if (total_cards_scanned > CardsNumSamplingThreshold) {
+      double avg_time_dirty_card_scan = average_time_ms(G1GCPhaseTimes::ScanHR) +
+                                        average_time_ms(G1GCPhaseTimes::OptScanHR);
 
-    if (_rs_length > 0) {
-      double cards_per_entry_ratio =
-        (double) remset_cards_scanned / (double) _rs_length;
-      _analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, this_pause_was_young_only);
+      _analytics->report_cost_per_card_scan_ms(avg_time_dirty_card_scan / total_cards_scanned, this_pause_was_young_only);
     }
 
-    // This is defensive. For a while _rs_length could get
-    // smaller than _recorded_rs_length which was causing
-    // rs_length_diff to get very large and mess up the RSet length
-    // predictions. The reason was unsafe concurrent updates to the
-    // _inc_cset_recorded_rs_length field which the code below guards
-    // against (see CR 7118202). This bug has now been fixed (see CR
-    // 7119027). However, I'm still worried that
-    // _inc_cset_recorded_rs_length might still end up somewhat
-    // inaccurate. The concurrent refinement thread calculates an
-    // RSet's length concurrently with other CR threads updating it
-    // which might cause it to calculate the length incorrectly (if,
-    // say, it's in mid-coarsening). So I'll leave in the defensive
-    // conditional below just in case.
-    size_t rs_length_diff = 0;
-    size_t recorded_rs_length = _collection_set->recorded_rs_length();
-    if (_rs_length > recorded_rs_length) {
-      rs_length_diff = _rs_length - recorded_rs_length;
+    // Update prediction for the ratio between cards from the remembered
+    // sets and actually scanned cards from the remembered sets.
+    // Cards from the remembered sets are all cards not duplicated by cards from
+    // the logs.
+    // Due to duplicates in the log buffers, the number of actually scanned cards
+    // can be smaller than the cards in the log buffers.
+    const size_t from_rs_length_cards = (total_cards_scanned > total_log_buffer_cards) ? total_cards_scanned - total_log_buffer_cards : 0;
+    double merge_to_scan_ratio = 0.0;
+    if (total_cards_scanned > 0) {
+      merge_to_scan_ratio = (double) from_rs_length_cards / total_cards_scanned;
     }
-    _analytics->report_rs_length_diff((double) rs_length_diff);
+    _analytics->report_card_merge_to_scan_ratio(merge_to_scan_ratio, this_pause_was_young_only);
 
+    const size_t recorded_rs_length = _collection_set->recorded_rs_length();
+    const size_t rs_length_diff = _rs_length > recorded_rs_length ? _rs_length - recorded_rs_length : 0;
+    _analytics->report_rs_length_diff(rs_length_diff);
+
+    // Update prediction for copy cost per byte
     size_t copied_bytes = p->sum_thread_work_items(G1GCPhaseTimes::MergePSS, G1GCPhaseTimes::MergePSSCopiedBytes);
 
     if (copied_bytes > 0) {
@@ -842,21 +832,21 @@
   // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
   double scan_logged_cards_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
 
-  if (scan_logged_cards_time_goal_ms < scan_hcc_time_ms) {
+  if (scan_logged_cards_time_goal_ms < merge_hcc_time_ms) {
     log_debug(gc, ergo, refine)("Adjust concurrent refinement thresholds (scanning the HCC expected to take longer than Update RS time goal)."
                                 "Logged Cards Scan time goal: %1.2fms Scan HCC time: %1.2fms",
-                                scan_logged_cards_time_goal_ms, scan_hcc_time_ms);
+                                scan_logged_cards_time_goal_ms, merge_hcc_time_ms);
 
     scan_logged_cards_time_goal_ms = 0;
   } else {
-    scan_logged_cards_time_goal_ms -= scan_hcc_time_ms;
+    scan_logged_cards_time_goal_ms -= merge_hcc_time_ms;
   }
 
   _pending_cards_at_prev_gc_end = _g1h->pending_card_num();
   double const logged_cards_time = logged_cards_processing_time();
 
   log_debug(gc, ergo, refine)("Concurrent refinement times: Logged Cards Scan time goal: %1.2fms Logged Cards Scan time: %1.2fms HCC time: %1.2fms",
-                              scan_logged_cards_time_goal_ms, logged_cards_time, scan_hcc_time_ms);
+                              scan_logged_cards_time_goal_ms, logged_cards_time, merge_hcc_time_ms);
 
   _g1h->concurrent_refine()->adjust(logged_cards_time,
                                     phase_times()->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBDirtyCards),
@@ -924,11 +914,7 @@
 double G1Policy::predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
   TruncatedSeq* seq = surv_rate_group->get_seq(age);
   guarantee(seq->num() > 0, "There should be some young gen survivor samples available. Tried to access with age %d", age);
-  double pred = _predictor.get_new_prediction(seq);
-  if (pred > 1.0) {
-    pred = 1.0;
-  }
-  return pred;
+  return _predictor.get_new_unit_prediction(seq);
 }
 
 double G1Policy::accum_yg_surv_rate_pred(int age) const {
@@ -936,17 +922,17 @@
 }
 
 double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards,
-                                              size_t scanned_cards) const {
+                                              size_t rs_length) const {
+  size_t effective_scanned_cards = _analytics->predict_scan_card_num(rs_length, collector_state()->in_young_only_phase());
   return
-    _analytics->predict_rs_update_time_ms(pending_cards) +
-    _analytics->predict_rs_scan_time_ms(scanned_cards, collector_state()->in_young_only_phase()) +
+    _analytics->predict_card_merge_time_ms(pending_cards + rs_length, collector_state()->in_young_only_phase()) +
+    _analytics->predict_card_scan_time_ms(effective_scanned_cards, collector_state()->in_young_only_phase()) +
     _analytics->predict_constant_other_time_ms();
 }
 
 double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards) const {
   size_t rs_length = _analytics->predict_rs_length();
-  size_t card_num = _analytics->predict_card_num(rs_length, collector_state()->in_young_only_phase());
-  return predict_base_elapsed_time_ms(pending_cards, card_num);
+  return predict_base_elapsed_time_ms(pending_cards, rs_length);
 }
 
 size_t G1Policy::predict_bytes_to_copy(HeapRegion* hr) const {
@@ -965,13 +951,13 @@
 double G1Policy::predict_region_elapsed_time_ms(HeapRegion* hr,
                                                 bool for_young_gc) const {
   size_t rs_length = hr->rem_set()->occupied();
-  // Predicting the number of cards is based on which type of GC
-  // we're predicting for.
-  size_t card_num = _analytics->predict_card_num(rs_length, for_young_gc);
+  size_t scan_card_num = _analytics->predict_scan_card_num(rs_length, for_young_gc);
+
   size_t bytes_to_copy = predict_bytes_to_copy(hr);
 
   double region_elapsed_time_ms =
-    _analytics->predict_rs_scan_time_ms(card_num, collector_state()->in_young_only_phase()) +
+    _analytics->predict_card_merge_time_ms(rs_length, collector_state()->in_young_only_phase()) +
+    _analytics->predict_card_scan_time_ms(scan_card_num, collector_state()->in_young_only_phase()) +
     _analytics->predict_object_copy_time_ms(bytes_to_copy, collector_state()->mark_or_rebuild_in_progress());
 
   // The prediction of the "other" time for this region is based
--- a/src/hotspot/share/gc/g1/g1Policy.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -140,9 +140,9 @@
     _rs_length = rs_length;
   }
 
-  double predict_base_elapsed_time_ms(size_t pending_cards) const;
-  double predict_base_elapsed_time_ms(size_t pending_cards,
-                                      size_t scanned_cards) const;
+  double predict_base_elapsed_time_ms(size_t num_pending_cards) const;
+  double predict_base_elapsed_time_ms(size_t num_pending_cards,
+                                      size_t rs_length) const;
   size_t predict_bytes_to_copy(HeapRegion* hr) const;
   double predict_region_elapsed_time_ms(HeapRegion* hr, bool for_young_gc) const;
 
--- a/src/hotspot/share/gc/g1/g1Predictions.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Predictions.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -57,6 +57,14 @@
   double get_new_prediction(TruncatedSeq const* seq) const {
     return seq->davg() + _sigma * stddev_estimate(seq);
   }
+
+  double get_new_unit_prediction(TruncatedSeq const* seq) const {
+    return clamp(get_new_prediction(seq), 0.0, 1.0);
+  }
+
+  double get_new_lower_zero_bound_prediction(TruncatedSeq const* seq) const {
+    return MAX2(get_new_prediction(seq), 0.0);
+  }
 };
 
 #endif // SHARE_GC_G1_G1PREDICTIONS_HPP
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -49,6 +49,7 @@
 #include "memory/resourceArea.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "utilities/align.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -196,30 +197,6 @@
     }
   };
 
-  // Creates a snapshot of the current _top values at the start of collection to
-  // filter out card marks that we do not want to scan.
-  class G1ResetScanTopClosure : public HeapRegionClosure {
-    G1RemSetScanState* _scan_state;
-
-  public:
-    G1ResetScanTopClosure(G1RemSetScanState* scan_state) : _scan_state(scan_state) { }
-
-    virtual bool do_heap_region(HeapRegion* r) {
-      uint hrm_index = r->hrm_index();
-      if (r->in_collection_set()) {
-        // Young regions had their card table marked as young at their allocation;
-        // we need to make sure that these marks are cleared at the end of GC, *but*
-        // they should not be scanned for cards.
-        // So directly add them to the "all_dirty_regions".
-        // Same for regions in the (initial) collection set: they may contain cards from
-        // the log buffers, make sure they are cleaned.
-        _scan_state->add_all_dirty_region(hrm_index);
-       } else if (r->is_old_or_humongous_or_archive()) {
-        _scan_state->set_scan_top(hrm_index, r->top());
-       }
-       return false;
-     }
-  };
   // For each region, contains the maximum top() value to be used during this garbage
   // collection. Subsumes common checks like filtering out everything but old and
   // humongous regions outside the collection set.
@@ -328,16 +305,8 @@
   }
 
   void prepare() {
-    for (size_t i = 0; i < _max_regions; i++) {
-      _collection_set_iter_state[i] = false;
-      clear_scan_top((uint)i);
-    }
-
     _all_dirty_regions = new G1DirtyRegions(_max_regions);
     _next_dirty_regions = new G1DirtyRegions(_max_regions);
-
-    G1ResetScanTopClosure cl(this);
-    G1CollectedHeap::heap()->heap_region_iterate(&cl);
   }
 
   void prepare_for_merge_heap_roots() {
@@ -430,6 +399,10 @@
     } while (cur != start_pos);
   }
 
+  void reset_region_claim(uint region_idx) {
+    _collection_set_iter_state[region_idx] = false;
+  }
+
   // Attempt to claim the given region in the collection set for iteration. Returns true
   // if this call caused the transition from Unclaimed to Claimed.
   inline bool claim_collection_set_region(uint region) {
@@ -909,6 +882,26 @@
   }
 }
 
+void G1RemSet::prepare_region_for_scan(HeapRegion* region) {
+  uint hrm_index = region->hrm_index();
+
+  _scan_state->reset_region_claim(hrm_index);
+  if (region->in_collection_set()) {
+    // Young regions had their card table marked as young at their allocation;
+    // we need to make sure that these marks are cleared at the end of GC, *but*
+    // they should not be scanned for cards.
+    // So directly add them to the "all_dirty_regions".
+    // Same for regions in the (initial) collection set: they may contain cards from
+    // the log buffers, make sure they are cleaned.
+    _scan_state->clear_scan_top(hrm_index);
+    _scan_state->add_all_dirty_region(hrm_index);
+  } else if (region->is_old_or_humongous_or_archive()) {
+    _scan_state->set_scan_top(hrm_index, region->top());
+  } else {
+    assert(region->is_free(), "Should only be free region at this point %s", region->get_type_str());
+  }
+}
+
 void G1RemSet::prepare_for_scan_heap_roots() {
   G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   dcqs.concatenate_logs();
@@ -927,6 +920,8 @@
     uint _merged_fine;
     uint _merged_coarse;
 
+    size_t _cards_dirty;
+
     // Returns if the region contains cards we need to scan. If so, remember that
     // region in the current set of dirty regions.
     bool remember_if_interesting(uint const region_idx) {
@@ -942,7 +937,8 @@
       _ct(G1CollectedHeap::heap()->card_table()),
       _merged_sparse(0),
       _merged_fine(0),
-      _merged_coarse(0) { }
+      _merged_coarse(0),
+      _cards_dirty(0) { }
 
     void next_coarse_prt(uint const region_idx) {
       if (!remember_if_interesting(region_idx)) {
@@ -952,7 +948,7 @@
       _merged_coarse++;
 
       size_t region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
-      _ct->mark_region_dirty(region_base_idx, HeapRegion::CardsPerRegion);
+      _cards_dirty += _ct->mark_region_dirty(region_base_idx, HeapRegion::CardsPerRegion);
       _scan_state->set_chunk_region_dirty(region_base_idx);
     }
 
@@ -966,7 +962,7 @@
       size_t const region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
       BitMap::idx_t cur = bm->get_next_one_offset(0);
       while (cur != bm->size()) {
-        _ct->mark_clean_as_dirty(region_base_idx + cur);
+        _cards_dirty += _ct->mark_clean_as_dirty(region_base_idx + cur);
         _scan_state->set_chunk_dirty(region_base_idx + cur);
         cur = bm->get_next_one_offset(cur + 1);
       }
@@ -982,7 +978,7 @@
       size_t const region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
       for (uint i = 0; i < num_cards; i++) {
         size_t card_idx = region_base_idx + cards[i];
-        _ct->mark_clean_as_dirty(card_idx);
+        _cards_dirty += _ct->mark_clean_as_dirty(card_idx);
         _scan_state->set_chunk_dirty(card_idx);
       }
     }
@@ -1001,6 +997,8 @@
     size_t merged_sparse() const { return _merged_sparse; }
     size_t merged_fine() const { return _merged_fine; }
     size_t merged_coarse() const { return _merged_coarse; }
+
+    size_t cards_dirty() const { return _cards_dirty; }
   };
 
   // Visitor for the remembered sets of humongous candidate regions to merge their
@@ -1046,6 +1044,8 @@
     size_t merged_sparse() const { return _cl.merged_sparse(); }
     size_t merged_fine() const { return _cl.merged_fine(); }
     size_t merged_coarse() const { return _cl.merged_coarse(); }
+
+    size_t cards_dirty() const { return _cl.cards_dirty(); }
   };
 
   // Visitor for the log buffer entries to merge them into the card table.
@@ -1147,6 +1147,7 @@
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_sparse(), G1GCPhaseTimes::MergeRSMergedSparse);
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_fine(), G1GCPhaseTimes::MergeRSMergedFine);
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_coarse(), G1GCPhaseTimes::MergeRSMergedCoarse);
+      p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.cards_dirty(), G1GCPhaseTimes::MergeRSDirtyCards);
     }
 
     // Merge remembered sets of current candidates.
@@ -1158,6 +1159,7 @@
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_sparse(), G1GCPhaseTimes::MergeRSMergedSparse);
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_fine(), G1GCPhaseTimes::MergeRSMergedFine);
       p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.merged_coarse(), G1GCPhaseTimes::MergeRSMergedCoarse);
+      p->record_or_add_thread_work_item(merge_remset_phase, worker_id, cl.cards_dirty(), G1GCPhaseTimes::MergeRSDirtyCards);
     }
 
     // Apply closure to log entries in the HCC.
@@ -1236,7 +1238,7 @@
   }
 }
 
-void G1RemSet::prepare_for_scan_heap_roots(uint region_idx) {
+void G1RemSet::exclude_region_from_scan(uint region_idx) {
   _scan_state->clear_scan_top(region_idx);
 }
 
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -102,8 +102,11 @@
   void prepare_for_scan_heap_roots();
   // Cleans the card table from temporary duplicate detection information.
   void cleanup_after_scan_heap_roots();
-  // Prepares the given region for heap root scanning.
-  void prepare_for_scan_heap_roots(uint region_idx);
+  // Excludes the given region from heap root scanning.
+  void exclude_region_from_scan(uint region_idx);
+  // Creates a snapshot of the current _top values at the start of collection to
+  // filter out card marks that we do not want to scan.
+  void prepare_region_for_scan(HeapRegion* region);
 
   // Do work for regions in the current increment of the collection set, scanning
   // non-card based (heap) roots.
--- a/src/hotspot/share/gc/g1/g1StringDedup.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1StringDedup.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,7 +34,6 @@
 #include "gc/shared/stringdedup/stringDedupTable.hpp"
 #include "gc/shared/stringdedup/stringDedupThread.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
 
 void G1StringDedup::initialize() {
   assert(UseG1GC, "String deduplication available with G1");
@@ -88,4 +87,3 @@
     G1StringDedupQueue::push(worker_id, java_string);
   }
 }
-
--- a/src/hotspot/share/gc/g1/heapRegion.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -43,8 +43,6 @@
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 
 int    HeapRegion::LogOfHRGrainBytes = 0;
 int    HeapRegion::LogOfHRGrainWords = 0;
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,6 +33,8 @@
 #include "gc/g1/heterogeneousHeapRegionManager.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/bitMap.inline.hpp"
 
 class MasterFreeRegionListChecker : public HeapRegionSetChecker {
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,7 @@
 #include "gc/g1/g1CodeCacheRemSet.hpp"
 #include "gc/g1/g1FromCardCache.hpp"
 #include "gc/g1/sparsePRT.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/bitMap.hpp"
 
 // Remembered set for a heap region.  Represent a set of "cards" that
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,7 @@
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/sparsePRT.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/bitMap.inline.hpp"
 
 template <class Closure>
--- a/src/hotspot/share/gc/g1/sparsePRT.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/sparsePRT.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,7 +30,6 @@
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/space.inline.hpp"
 #include "memory/allocation.inline.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
 
 // Check that the size of the SparsePRTEntry is evenly divisible by the maximum
--- a/src/hotspot/share/gc/g1/survRateGroup.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/g1/survRateGroup.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -116,8 +116,7 @@
   double accum = 0.0;
   double pred = 0.0;
   for (size_t i = 0; i < _stats_arrays_length; ++i) {
-    pred = predictor.get_new_prediction(_surv_rate_pred[i]);
-    if (pred > 1.0) pred = 1.0;
+    pred = predictor.get_new_unit_prediction(_surv_rate_pred[i]);
     accum += pred;
     _accum_surv_rate_pred[i] = accum;
   }
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -39,7 +39,6 @@
 #include "oops/instanceMirrorKlass.inline.hpp"
 #include "oops/objArrayKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
 
 PSOldGen*            ParCompactionManager::_old_gen = NULL;
 ParCompactionManager**  ParCompactionManager::_manager_array = NULL;
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,8 @@
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/collectorCounters.hpp"
 #include "oops/oop.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 
 class ParallelScavengeHeap;
 class PSAdaptiveSizePolicy;
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -51,7 +51,6 @@
 #include "memory/resourceArea.hpp"
 #include "oops/instanceRefKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/java.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "runtime/thread.inline.hpp"
--- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,9 +32,7 @@
 #include "utilities/debug.hpp"
 
 int BarrierSetNMethod::disarmed_value() const {
-  char* disarmed_addr = reinterpret_cast<char*>(Thread::current());
-  disarmed_addr += in_bytes(thread_disarmed_offset());
-  return *reinterpret_cast<int*>(disarmed_addr);
+  return *disarmed_value_address();
 }
 
 bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) {
--- a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,13 +34,14 @@
 class BarrierSetNMethod: public CHeapObj<mtGC> {
   bool supports_entry_barrier(nmethod* nm);
   void deoptimize(nmethod* nm, address* return_addr_ptr);
+  int disarmed_value() const;
 
 protected:
-  virtual int disarmed_value() const;
   virtual bool nmethod_entry_barrier(nmethod* nm) = 0;
 
 public:
   virtual ByteSize thread_disarmed_offset() const = 0;
+  virtual int* disarmed_value_address() const = 0;
 
   static int nmethod_stub_entry_barrier(address* return_address_ptr);
   bool nmethod_osr_entry_barrier(nmethod* nm);
--- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,9 +24,9 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/concurrentGCThread.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/init.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 
 ConcurrentGCThread::ConcurrentGCThread() :
--- a/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -166,10 +166,11 @@
           "Use the Garbage-First garbage collector")                        \
                                                                             \
   product(bool, UseParallelGC, false,                                       \
-          "Use the Parallel Scavenge garbage collector")                    \
+          "Use the Parallel garbage collector.")                            \
                                                                             \
   product(bool, UseParallelOldGC, false,                                    \
-          "Use the Parallel Old garbage collector")                         \
+          "Use the Parallel or Serial garbage collector when collecting "   \
+          "the old generation. Deprecated.")                                \
                                                                             \
   experimental(bool, UseEpsilonGC, false,                                   \
           "Use the Epsilon (no-op) garbage collector")                      \
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,6 +30,7 @@
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
+#include "runtime/atomic.hpp"
 
 StringDedupCleaningTask::StringDedupCleaningTask(BoolObjectClosure* is_alive,
                                                  OopClosure* keep_alive,
--- a/src/hotspot/share/gc/shared/preservedMarks.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/preservedMarks.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,7 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/macros.hpp"
 
 void PreservedMarks::restore() {
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,7 +30,6 @@
 #include "runtime/atomic.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/globalCounter.inline.hpp"
 
--- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,6 +30,7 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
+#include "runtime/atomic.hpp"
 
 #define ASSERT_REF_TYPE(ref_type) assert((ref_type) >= REF_SOFT && (ref_type) <= REF_PHANTOM, \
                                          "Invariant (%d)", (int)ref_type)
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,7 +30,6 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
--- a/src/hotspot/share/gc/shared/space.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/space.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,7 +37,6 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/java.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "runtime/safepoint.hpp"
 #include "utilities/align.hpp"
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
 #include "oops/arrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayOop.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepointVerifiers.hpp"
 
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,7 +33,6 @@
 #include "logging/log.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
 
 StringDedupThread* StringDedupThread::_thread = NULL;
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -171,11 +171,7 @@
   }
 
   // If class unloading is disabled, no unloading for concurrent cycles as well.
-  // If class unloading is enabled, users should opt-in for unloading during
-  // concurrent cycles.
-  if (!ClassUnloading || !FLAG_IS_CMDLINE(ClassUnloadingWithConcurrentMark)) {
-    log_info(gc)("Consider -XX:+ClassUnloadingWithConcurrentMark if large pause times "
-                 "are observed on class-unloading sensitive workloads");
+  if (!ClassUnloading) {
     FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false);
   }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
 #include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp"
 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
+#include "gc/shenandoah/shenandoahBarrierSetNMethod.hpp"
 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
 #include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
@@ -43,11 +44,19 @@
 class ShenandoahBarrierSetC1;
 class ShenandoahBarrierSetC2;
 
+static BarrierSetNMethod* make_barrier_set_nmethod(ShenandoahHeap* heap) {
+  // NMethod barriers are only used when concurrent nmethod unloading is enabled
+  if (!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
+    return NULL;
+  }
+  return new ShenandoahBarrierSetNMethod(heap);
+}
+
 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
   BarrierSet(make_barrier_set_assembler<ShenandoahBarrierSetAssembler>(),
              make_barrier_set_c1<ShenandoahBarrierSetC1>(),
              make_barrier_set_c2<ShenandoahBarrierSetC2>(),
-             NULL /* barrier_set_nmethod */,
+             make_barrier_set_nmethod(heap),
              BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
   _heap(heap),
   _satb_mark_queue_buffer_allocator("SATB Buffer Allocator", ShenandoahSATBBufferSize),
@@ -101,36 +110,6 @@
   return (on_weak_ref || unknown) && (keep_alive || is_traversal_mode);
 }
 
-template <class T>
-inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop new_val) {
-  shenandoah_assert_not_in_cset_loc_except(field, _heap->cancelled_gc());
-  if (_heap->is_concurrent_mark_in_progress()) {
-    T heap_oop = RawAccess<>::oop_load(field);
-    if (!CompressedOops::is_null(heap_oop)) {
-      enqueue(CompressedOops::decode(heap_oop));
-    }
-  }
-}
-
-// These are the more general virtual versions.
-void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
-  inline_write_ref_field_pre(field, new_val);
-}
-
-void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
-  inline_write_ref_field_pre(field, new_val);
-}
-
-void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
-  guarantee(false, "Not needed");
-}
-
-void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
-  shenandoah_assert_not_in_cset_loc_except(v, _heap->cancelled_gc());
-  shenandoah_assert_not_forwarded_except  (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
-  shenandoah_assert_not_in_cset_except    (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
-}
-
 oop ShenandoahBarrierSet::load_reference_barrier_not_null(oop obj) {
   if (ShenandoahLoadRefBarrier && _heap->has_forwarded_objects()) {
     return load_reference_barrier_impl(obj);
@@ -234,30 +213,6 @@
   }
 }
 
-void ShenandoahBarrierSet::storeval_barrier(oop obj) {
-  if (ShenandoahStoreValEnqueueBarrier && !CompressedOops::is_null(obj) && _heap->is_concurrent_traversal_in_progress()) {
-    enqueue(obj);
-  }
-}
-
-void ShenandoahBarrierSet::keep_alive_barrier(oop obj) {
-  if (ShenandoahKeepAliveBarrier && _heap->is_concurrent_mark_in_progress()) {
-    enqueue(obj);
-  }
-}
-
-void ShenandoahBarrierSet::enqueue(oop obj) {
-  shenandoah_assert_not_forwarded_if(NULL, obj, _heap->is_concurrent_traversal_in_progress());
-  assert(_satb_mark_queue_set.is_active(), "only get here when SATB active");
-
-  // Filter marked objects before hitting the SATB queues. The same predicate would
-  // be used by SATBMQ::filter to eliminate already marked objects downstream, but
-  // filtering here helps to avoid wasteful SATB queueing work to begin with.
-  if (!_heap->requires_marking<false>(obj)) return;
-
-  ShenandoahThreadLocalData::satb_mark_queue(Thread::current()).enqueue_known_active(obj);
-}
-
 void ShenandoahBarrierSet::on_thread_create(Thread* thread) {
   // Create thread local data
   ShenandoahThreadLocalData::create(thread);
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -77,17 +77,6 @@
   inline void clone_barrier(oop src);
   void clone_barrier_runtime(oop src);
 
-  // We export this to make it available in cases where the static
-  // type of the barrier set is known.  Note that it is non-virtual.
-  template <class T> inline void inline_write_ref_field_pre(T* field, oop new_val);
-
-  // These are the more general virtual versions.
-  void write_ref_field_pre_work(oop* field, oop new_val);
-  void write_ref_field_pre_work(narrowOop* field, oop new_val);
-  void write_ref_field_pre_work(void* field, oop new_val);
-
-  void write_ref_field_work(void* v, oop o, bool release = false);
-
   virtual void on_thread_create(Thread* thread);
   virtual void on_thread_destroy(Thread* thread);
   virtual void on_thread_attach(Thread* thread);
@@ -96,8 +85,17 @@
   static inline oop resolve_forwarded_not_null(oop p);
   static inline oop resolve_forwarded(oop p);
 
-  void storeval_barrier(oop obj);
-  void keep_alive_barrier(oop obj);
+  template <DecoratorSet decorators, typename T>
+  inline void satb_barrier(T* field);
+  inline void satb_enqueue(oop value);
+  inline void storeval_barrier(oop obj);
+
+  template <DecoratorSet decorators>
+  inline void keep_alive_if_weak(oop value);
+  inline void keep_alive_if_weak(DecoratorSet decorators, oop value);
+  inline void keep_alive_barrier(oop value);
+
+  inline void enqueue(oop obj);
 
   oop load_reference_barrier(oop obj);
   oop load_reference_barrier_not_null(oop obj);
@@ -111,8 +109,6 @@
   oop load_reference_barrier_native(oop obj, oop* load_addr);
   oop load_reference_barrier_native(oop obj, narrowOop* load_addr);
 
-  void enqueue(oop obj);
-
 private:
   template <class T>
   inline void arraycopy_pre_work(T* src, T* dst, size_t count);
@@ -126,27 +122,12 @@
   template <class T>
   oop load_reference_barrier_native_impl(oop obj, T* load_addr);
 
-  static void keep_alive_if_weak(DecoratorSet decorators, oop value) {
-    assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
-    const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0;
-    const bool peek              = (decorators & AS_NO_KEEPALIVE) != 0;
-    if (!peek && !on_strong_oop_ref && value != NULL) {
-      ShenandoahBarrierSet::barrier_set()->keep_alive_barrier(value);
-    }
-  }
-
 public:
   // Callbacks for runtime accesses.
   template <DecoratorSet decorators, typename BarrierSetT = ShenandoahBarrierSet>
   class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> {
     typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw;
 
-    template <typename T>
-    static oop oop_atomic_cmpxchg_in_heap_impl(T* addr, oop compare_value, oop new_value);
-
-    template <typename T>
-    static oop oop_atomic_xchg_in_heap_impl(T* addr, oop new_value);
-
   public:
     // Heap oop accesses. These accessors get resolved when
     // IN_HEAP is set (e.g. when using the HeapAccess API), it is
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -48,41 +48,124 @@
   }
 }
 
+inline void ShenandoahBarrierSet::enqueue(oop obj) {
+  shenandoah_assert_not_forwarded_if(NULL, obj, _heap->is_concurrent_traversal_in_progress());
+  assert(_satb_mark_queue_set.is_active(), "only get here when SATB active");
+
+  // Filter marked objects before hitting the SATB queues. The same predicate would
+  // be used by SATBMQ::filter to eliminate already marked objects downstream, but
+  // filtering here helps to avoid wasteful SATB queueing work to begin with.
+  if (!_heap->requires_marking<false>(obj)) return;
+
+  ShenandoahThreadLocalData::satb_mark_queue(Thread::current()).enqueue_known_active(obj);
+}
+
+template <DecoratorSet decorators, typename T>
+inline void ShenandoahBarrierSet::satb_barrier(T *field) {
+  if (HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value ||
+      HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
+    return;
+  }
+  if (ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) {
+    T heap_oop = RawAccess<>::oop_load(field);
+    if (!CompressedOops::is_null(heap_oop)) {
+      enqueue(CompressedOops::decode(heap_oop));
+    }
+  }
+}
+
+inline void ShenandoahBarrierSet::satb_enqueue(oop value) {
+  assert(value != NULL, "checked before");
+  if (ShenandoahSATBBarrier && _heap->is_concurrent_mark_in_progress()) {
+    enqueue(value);
+  }
+}
+
+inline void ShenandoahBarrierSet::storeval_barrier(oop obj) {
+  if (obj != NULL && ShenandoahStoreValEnqueueBarrier && _heap->is_concurrent_traversal_in_progress()) {
+    enqueue(obj);
+  }
+}
+
+inline void ShenandoahBarrierSet::keep_alive_barrier(oop value) {
+  assert(value != NULL, "checked before");
+  if (ShenandoahKeepAliveBarrier && _heap->is_concurrent_mark_in_progress()) {
+    enqueue(value);
+  }
+}
+
+inline void ShenandoahBarrierSet::keep_alive_if_weak(DecoratorSet decorators, oop value) {
+  assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
+  const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0;
+  const bool peek              = (decorators & AS_NO_KEEPALIVE) != 0;
+  if (!peek && !on_strong_oop_ref) {
+    keep_alive_barrier(value);
+  }
+}
+
+template <DecoratorSet decorators>
+inline void ShenandoahBarrierSet::keep_alive_if_weak(oop value) {
+  assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known");
+  if (!HasDecorator<decorators, ON_STRONG_OOP_REF>::value &&
+      !HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
+    keep_alive_barrier(value);
+  }
+}
+
+template <DecoratorSet decorators, typename BarrierSetT>
+template <typename T>
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) {
+  oop value = Raw::oop_load_not_in_heap(addr);
+  if (value != NULL) {
+    ShenandoahBarrierSet *const bs = ShenandoahBarrierSet::barrier_set();
+    value = bs->load_reference_barrier_native(value, addr);
+    bs->keep_alive_if_weak<decorators>(value);
+  }
+  return value;
+}
+
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(T* addr) {
   oop value = Raw::oop_load_in_heap(addr);
-  value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(value);
-  keep_alive_if_weak(decorators, value);
+  if (value != NULL) {
+    ShenandoahBarrierSet *const bs = ShenandoahBarrierSet::barrier_set();
+    value = bs->load_reference_barrier_not_null(value);
+    bs->keep_alive_if_weak<decorators>(value);
+  }
   return value;
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) {
   oop value = Raw::oop_load_in_heap_at(base, offset);
-  value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(value);
-  keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), value);
+  if (value != NULL) {
+    ShenandoahBarrierSet *const bs = ShenandoahBarrierSet::barrier_set();
+    value = bs->load_reference_barrier_not_null(value);
+    bs->keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset),
+                           value);
+  }
   return value;
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
-inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) {
-  oop value = Raw::oop_load_not_in_heap(addr);
-  value = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_native(value, addr);
-  keep_alive_if_weak(decorators, value);
-  return value;
+inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_not_in_heap(T* addr, oop value) {
+  shenandoah_assert_marked_if(NULL, value, !CompressedOops::is_null(value) && ShenandoahHeap::heap()->is_evacuation_in_progress());
+  ShenandoahBarrierSet* const bs = ShenandoahBarrierSet::barrier_set();
+  bs->storeval_barrier(value);
+  bs->satb_barrier<decorators>(addr);
+  Raw::oop_store(addr, value);
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
 inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_in_heap(T* addr, oop value) {
-  ShenandoahBarrierSet::barrier_set()->storeval_barrier(value);
-  const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
-  if (keep_alive) {
-    ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
-  }
-  Raw::oop_store_in_heap(addr, value);
+  shenandoah_assert_not_in_cset_loc_except(addr, ShenandoahHeap::heap()->cancelled_gc());
+  shenandoah_assert_not_forwarded_except  (addr, value, value == NULL || ShenandoahHeap::heap()->cancelled_gc() || !ShenandoahHeap::heap()->is_concurrent_mark_in_progress());
+  shenandoah_assert_not_in_cset_except    (addr, value, value == NULL || ShenandoahHeap::heap()->cancelled_gc() || !ShenandoahHeap::heap()->is_concurrent_mark_in_progress());
+
+  oop_store_not_in_heap(addr, value);
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
@@ -92,14 +175,10 @@
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
-inline void ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_store_not_in_heap(T* addr, oop value) {
-  shenandoah_assert_marked_if(NULL, value, !CompressedOops::is_null(value) && ShenandoahHeap::heap()->is_evacuation_in_progress());
-  Raw::oop_store(addr, value);
-}
+inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(T* addr, oop compare_value, oop new_value) {
+  ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
+  bs->storeval_barrier(new_value);
 
-template <DecoratorSet decorators, typename BarrierSetT>
-template <typename T>
-inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(T* addr, oop compare_value, oop new_value) {
   oop res;
   oop expected = compare_value;
   do {
@@ -107,79 +186,53 @@
     res = Raw::oop_atomic_cmpxchg(addr, compare_value, new_value);
     expected = res;
   } while ((compare_value != expected) && (resolve_forwarded(compare_value) == resolve_forwarded(expected)));
+
+  // Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
+  // because it must be the previous value.
   if (res != NULL) {
-    return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(res);
-  } else {
-    return res;
+    res = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(res);
+    bs->satb_enqueue(res);
   }
-}
-
-template <DecoratorSet decorators, typename BarrierSetT>
-template <typename T>
-inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_impl(T* addr, oop compare_value, oop new_value) {
-  ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
-  oop result = oop_atomic_cmpxchg_not_in_heap(addr, compare_value, new_value);
-  const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
-  if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(result) &&
-      (result == compare_value) &&
-      ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
-    ShenandoahBarrierSet::barrier_set()->enqueue(result);
-  }
-  return result;
+  return res;
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value) {
-  oop result = oop_atomic_cmpxchg_in_heap_impl(addr, compare_value, new_value);
-  keep_alive_if_weak(decorators, result);
-  return result;
+  return oop_atomic_cmpxchg_not_in_heap(addr, compare_value, new_value);
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) {
-  oop result = oop_atomic_cmpxchg_in_heap_impl(AccessInternal::oop_field_addr<decorators>(base, offset), compare_value, new_value);
-  keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), result);
-  return result;
+  return oop_atomic_cmpxchg_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), compare_value, new_value);
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(T* addr, oop new_value) {
+  ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
+  bs->storeval_barrier(new_value);
+
   oop previous = Raw::oop_atomic_xchg(addr, new_value);
-  if (previous != NULL) {
-    return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(previous);
-  } else {
-    return previous;
-  }
-}
 
-template <DecoratorSet decorators, typename BarrierSetT>
-template <typename T>
-inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_impl(T* addr, oop new_value) {
-  ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value);
-  oop result = oop_atomic_xchg_not_in_heap(addr, new_value);
-  const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
-  if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(result) &&
-      ShenandoahHeap::heap()->is_concurrent_mark_in_progress()) {
-    ShenandoahBarrierSet::barrier_set()->enqueue(result);
+  // Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway,
+  // because it must be the previous value.
+  if (previous != NULL) {
+    previous = ShenandoahBarrierSet::barrier_set()->load_reference_barrier_not_null(previous);
+    bs->satb_enqueue(previous);
   }
-  return result;
+  return previous;
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 template <typename T>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(T* addr, oop new_value) {
-  oop result = oop_atomic_xchg_in_heap_impl(addr, new_value);
-  keep_alive_if_weak(addr, result);
-  return result;
+  return oop_atomic_xchg_not_in_heap(addr, new_value);
 }
 
 template <DecoratorSet decorators, typename BarrierSetT>
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) {
-  oop result = oop_atomic_xchg_in_heap_impl(AccessInternal::oop_field_addr<decorators>(base, offset), new_value);
-  keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset), result);
-  return result;
+  return oop_atomic_xchg_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), new_value);
 }
 
 // Clone barrier support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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/shenandoah/shenandoahBarrierSetNMethod.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahCodeRoots.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahLock.hpp"
+#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
+#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
+#include "memory/iterator.hpp"
+#include "memory/resourceArea.hpp"
+
+bool ShenandoahBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
+  ShenandoahReentrantLock* lock = ShenandoahNMethod::lock_for_nmethod(nm);
+  assert(lock != NULL, "Must be");
+  ShenandoahReentrantLocker locker(lock);
+
+  if (!is_armed(nm)) {
+    // Some other thread got here first and healed the oops
+    // and disarmed the nmethod.
+    return true;
+  }
+
+  if (nm->is_unloading()) {
+    // We don't need to take the lock when unlinking nmethods from
+    // the Method, because it is only concurrently unlinked by
+    // the entry barrier, which acquires the per nmethod lock.
+    nm->unlink_from_method();
+
+    // We can end up calling nmethods that are unloading
+    // since we clear compiled ICs lazily. Returning false
+    // will re-resovle the call and update the compiled IC.
+    return false;
+  }
+
+  // Heal oops and disarm
+  ShenandoahEvacOOMScope scope;
+  ShenandoahNMethod::heal_nmethod(nm);
+  ShenandoahNMethod::disarm_nmethod(nm);
+  return true;
+}
+
+int ShenandoahBarrierSetNMethod::disarmed_value() const {
+  return ShenandoahCodeRoots::disarmed_value();
+}
+
+ByteSize ShenandoahBarrierSetNMethod::thread_disarmed_offset() const {
+  return ShenandoahThreadLocalData::disarmed_value_offset();
+}
+
+int* ShenandoahBarrierSetNMethod::disarmed_value_address() const {
+  return ShenandoahCodeRoots::disarmed_value_address();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_SHENANDOAH_SHENANDOAHBARRIERSETNMETHOD_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSETNMETHOD_HPP
+
+#include "gc/shared/barrierSetNMethod.hpp"
+#include "memory/allocation.hpp"
+
+class nmethod;
+class ShenandoahHeap;
+
+class ShenandoahBarrierSetNMethod : public BarrierSetNMethod {
+private:
+  ShenandoahHeap* _heap;
+
+protected:
+  virtual int disarmed_value() const;
+  virtual bool nmethod_entry_barrier(nmethod* nm);
+
+public:
+  ShenandoahBarrierSetNMethod(ShenandoahHeap* heap) : _heap(heap) {
+  }
+
+  virtual ByteSize thread_disarmed_offset() const;
+  virtual int* disarmed_value_address() const;
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSETNMETHOD_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -104,6 +104,15 @@
   inline void do_oop(narrowOop* p);
 };
 
+class ShenandoahCodeBlobAndDisarmClosure: public CodeBlobToOopClosure {
+private:
+  BarrierSetNMethod* const _bs;
+
+public:
+  inline ShenandoahCodeBlobAndDisarmClosure(OopClosure* cl);
+  inline void do_code_blob(CodeBlob* cb);
+};
+
 #ifdef ASSERT
 class ShenandoahAssertNotForwardedClosure : public OopClosure {
 private:
--- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,11 +23,14 @@
 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
 #define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
 
+#include "gc/shared/barrierSetNMethod.hpp"
 #include "gc/shenandoah/shenandoahAsserts.hpp"
 #include "gc/shenandoah/shenandoahClosures.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
 #include "gc/shenandoah/shenandoahTraversalGC.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/thread.hpp"
 
 ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
@@ -156,6 +159,20 @@
   ShouldNotReachHere();
 }
 
+ShenandoahCodeBlobAndDisarmClosure::ShenandoahCodeBlobAndDisarmClosure(OopClosure* cl) :
+  CodeBlobToOopClosure(cl, true /* fix_relocations */),
+   _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {
+}
+
+void ShenandoahCodeBlobAndDisarmClosure::do_code_blob(CodeBlob* cb) {
+  nmethod* const nm = cb->as_nmethod_or_null();
+  if (nm != NULL && nm->oops_do_try_claim()) {
+    assert(!ShenandoahNMethod::gc_data(nm)->is_unregistered(), "Should not be here");
+    CodeBlobToOopClosure::do_code_blob(cb);
+    _bs->disarm(nm);
+  }
+}
+
 #ifdef ASSERT
 template <class T>
 void ShenandoahAssertNotForwardedClosure::do_oop_work(T* p) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,12 +23,15 @@
 
 #include "precompiled.hpp"
 #include "code/codeCache.hpp"
+#include "code/icBuffer.hpp"
 #include "code/nmethod.hpp"
+#include "gc/shenandoah/shenandoahCodeRoots.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
-#include "gc/shenandoah/shenandoahCodeRoots.hpp"
+#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
+#include "runtime/atomic.hpp"
 
 ShenandoahParallelCodeCacheIterator::ShenandoahParallelCodeCacheIterator(const GrowableArray<CodeHeap*>* heaps) {
   _length = heaps->length();
@@ -97,69 +100,45 @@
   _finished = true;
 }
 
-class ShenandoahNMethodOopDetector : public OopClosure {
-private:
-  ResourceMark rm; // For growable array allocation below.
-  GrowableArray<oop*> _oops;
-
-public:
-  ShenandoahNMethodOopDetector() : _oops(10) {};
-
-  void do_oop(oop* o) {
-    _oops.append(o);
-  }
-  void do_oop(narrowOop* o) {
-    fatal("NMethods should not have compressed oops embedded.");
-  }
-
-  GrowableArray<oop*>* oops() {
-    return &_oops;
-  }
-
-  bool has_oops() {
-    return !_oops.is_empty();
-  }
-};
-
-GrowableArray<ShenandoahNMethod*>* ShenandoahCodeRoots::_recorded_nms;
-ShenandoahLock                     ShenandoahCodeRoots::_recorded_nms_lock;
+ShenandoahNMethodTable* ShenandoahCodeRoots::_nmethod_table;
+int ShenandoahCodeRoots::_disarmed_value = 1;
 
 void ShenandoahCodeRoots::initialize() {
-  _recorded_nms = new (ResourceObj::C_HEAP, mtGC) GrowableArray<ShenandoahNMethod*>(100, true, mtGC);
+  _nmethod_table = new ShenandoahNMethodTable();
 }
 
-void ShenandoahCodeRoots::add_nmethod(nmethod* nm) {
+void ShenandoahCodeRoots::register_nmethod(nmethod* nm) {
   switch (ShenandoahCodeRootsStyle) {
     case 0:
     case 1:
       break;
     case 2: {
       assert_locked_or_safepoint(CodeCache_lock);
-      ShenandoahLocker locker(CodeCache_lock->owned_by_self() ? NULL : &_recorded_nms_lock);
-
-      ShenandoahNMethodOopDetector detector;
-      nm->oops_do(&detector);
-
-      if (detector.has_oops()) {
-        ShenandoahNMethod* nmr = new ShenandoahNMethod(nm, detector.oops());
-        nmr->assert_alive_and_correct();
-        int idx = _recorded_nms->find(nm, ShenandoahNMethod::find_with_nmethod);
-        if (idx != -1) {
-          ShenandoahNMethod* old = _recorded_nms->at(idx);
-          _recorded_nms->at_put(idx, nmr);
-          delete old;
-        } else {
-          _recorded_nms->append(nmr);
-        }
-      }
+      _nmethod_table->register_nmethod(nm);
       break;
     }
     default:
       ShouldNotReachHere();
   }
-};
+}
 
-void ShenandoahCodeRoots::remove_nmethod(nmethod* nm) {
+void ShenandoahCodeRoots::unregister_nmethod(nmethod* nm) {
+  switch (ShenandoahCodeRootsStyle) {
+    case 0:
+    case 1: {
+      break;
+    }
+    case 2: {
+      assert_locked_or_safepoint(CodeCache_lock);
+      _nmethod_table->unregister_nmethod(nm);
+      break;
+    }
+    default:
+      ShouldNotReachHere();
+  }
+}
+
+void ShenandoahCodeRoots::flush_nmethod(nmethod* nm) {
   switch (ShenandoahCodeRootsStyle) {
     case 0:
     case 1: {
@@ -167,19 +146,7 @@
     }
     case 2: {
       assert_locked_or_safepoint(CodeCache_lock);
-      ShenandoahLocker locker(CodeCache_lock->owned_by_self() ? NULL : &_recorded_nms_lock);
-
-      ShenandoahNMethodOopDetector detector;
-      nm->oops_do(&detector, /* allow_dead = */ true);
-
-      if (detector.has_oops()) {
-        int idx = _recorded_nms->find(nm, ShenandoahNMethod::find_with_nmethod);
-        assert(idx != -1, "nmethod " PTR_FORMAT " should be registered", p2i(nm));
-        ShenandoahNMethod* old = _recorded_nms->at(idx);
-        old->assert_same_oops(detector.oops());
-        _recorded_nms->delete_at(idx);
-        delete old;
-      }
+      _nmethod_table->flush_nmethod(nm);
       break;
     }
     default:
@@ -187,10 +154,186 @@
   }
 }
 
+void ShenandoahCodeRoots::prepare_concurrent_unloading() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+  _disarmed_value ++;
+  // 0 is reserved for new nmethod
+  if (_disarmed_value == 0) {
+    _disarmed_value = 1;
+  }
+
+  JavaThreadIteratorWithHandle jtiwh;
+  for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) {
+    ShenandoahThreadLocalData::set_disarmed_value(thr, _disarmed_value);
+  }
+}
+
+class ShenandoahNMethodUnlinkClosure : public NMethodClosure {
+private:
+  bool            _unloading_occurred;
+  volatile bool   _failed;
+  ShenandoahHeap* _heap;
+
+  void set_failed() {
+    Atomic::store(&_failed, true);
+  }
+
+   void unlink(nmethod* nm) {
+     // Unlinking of the dependencies must happen before the
+     // handshake separating unlink and purge.
+     nm->flush_dependencies(false /* delete_immediately */);
+
+     // unlink_from_method will take the CompiledMethod_lock.
+     // In this case we don't strictly need it when unlinking nmethods from
+     // the Method, because it is only concurrently unlinked by
+     // the entry barrier, which acquires the per nmethod lock.
+     nm->unlink_from_method();
+
+     if (nm->is_osr_method()) {
+       // Invalidate the osr nmethod only once
+       nm->invalidate_osr_method();
+     }
+   }
+public:
+  ShenandoahNMethodUnlinkClosure(bool unloading_occurred) :
+      _unloading_occurred(unloading_occurred),
+      _failed(false),
+      _heap(ShenandoahHeap::heap()) {}
+
+  virtual void do_nmethod(nmethod* nm) {
+    if (failed()) {
+      return;
+    }
+
+    ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
+    assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
+
+    if (!nm->is_alive()) {
+      return;
+    }
+
+    if (nm->is_unloading()) {
+      ShenandoahReentrantLocker locker(nm_data->lock());
+      unlink(nm);
+      return;
+    }
+
+    ShenandoahReentrantLocker locker(nm_data->lock());
+
+    // Heal oops and disarm
+    ShenandoahEvacOOMScope scope;
+    ShenandoahNMethod::heal_nmethod(nm);
+    ShenandoahNMethod::disarm_nmethod(nm);
+
+    // Clear compiled ICs and exception caches
+    if (!nm->unload_nmethod_caches(_unloading_occurred)) {
+      set_failed();
+    }
+  }
+
+  bool failed() const {
+    return Atomic::load(&_failed);
+  }
+};
+
+class ShenandoahUnlinkTask : public AbstractGangTask {
+private:
+  ShenandoahNMethodUnlinkClosure      _cl;
+  ICRefillVerifier*                   _verifier;
+  ShenandoahConcurrentNMethodIterator _iterator;
+
+public:
+  ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
+    AbstractGangTask("ShenandoahNMethodUnlinkTask"),
+    _cl(unloading_occurred),
+    _verifier(verifier),
+    _iterator(ShenandoahCodeRoots::table()) {
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    _iterator.nmethods_do_begin();
+  }
+
+  ~ShenandoahUnlinkTask() {
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    _iterator.nmethods_do_end();
+  }
+
+  virtual void work(uint worker_id) {
+    ICRefillVerifierMark mark(_verifier);
+    _iterator.nmethods_do(&_cl);
+  }
+
+  bool success() const {
+    return !_cl.failed();
+  }
+};
+
+void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
+  assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
+         "Only when running concurrent class unloading");
+
+  for (;;) {
+    ICRefillVerifier verifier;
+
+    {
+      ShenandoahUnlinkTask task(unloading_occurred, &verifier);
+      workers->run_task(&task);
+      if (task.success()) {
+        return;
+      }
+    }
+
+    // Cleaning failed because we ran out of transitional IC stubs,
+    // so we have to refill and try again. Refilling requires taking
+    // a safepoint, so we temporarily leave the suspendible thread set.
+    SuspendibleThreadSetLeaver sts;
+    InlineCacheBuffer::refill_ic_stubs();
+  }
+}
+
+class ShenandoahNMethodPurgeClosure : public NMethodClosure {
+public:
+  virtual void do_nmethod(nmethod* nm) {
+    if (nm->is_alive() && nm->is_unloading()) {
+      nm->make_unloaded();
+    }
+  }
+};
+
+class ShenandoahNMethodPurgeTask : public AbstractGangTask {
+private:
+  ShenandoahNMethodPurgeClosure       _cl;
+  ShenandoahConcurrentNMethodIterator _iterator;
+
+public:
+  ShenandoahNMethodPurgeTask() :
+    AbstractGangTask("ShenandoahNMethodPurgeTask"),
+    _cl(),
+    _iterator(ShenandoahCodeRoots::table()) {
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    _iterator.nmethods_do_begin();
+  }
+
+  ~ShenandoahNMethodPurgeTask() {
+    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    _iterator.nmethods_do_end();
+  }
+
+  virtual void work(uint worker_id) {
+    _iterator.nmethods_do(&_cl);
+  }
+};
+
+void ShenandoahCodeRoots::purge(WorkGang* workers) {
+  assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
+         "Only when running concurrent class unloading");
+
+  ShenandoahNMethodPurgeTask task;
+  workers->run_task(&task);
+}
+
 ShenandoahCodeRootsIterator::ShenandoahCodeRootsIterator() :
-        _heap(ShenandoahHeap::heap()),
         _par_iterator(CodeCache::heaps()),
-        _claimed(0) {
+        _table_snapshot(NULL) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
   assert(!Thread::current()->is_Worker_thread(), "Should not be acquired by workers");
   switch (ShenandoahCodeRootsStyle) {
@@ -201,6 +344,7 @@
     }
     case 2: {
       CodeCache_lock->lock_without_safepoint_check();
+      _table_snapshot = ShenandoahCodeRoots::table()->snapshot_for_iteration();
       break;
     }
     default:
@@ -216,6 +360,8 @@
       break;
     }
     case 2: {
+      ShenandoahCodeRoots::table()->finish_iteration(_table_snapshot);
+      _table_snapshot = NULL;
       CodeCache_lock->unlock();
       break;
     }
@@ -257,77 +403,7 @@
 template <bool CSET_FILTER>
 void ShenandoahCodeRootsIterator::fast_parallel_blobs_do(CodeBlobClosure *f) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
-
-  size_t stride = 256; // educated guess
-
-  GrowableArray<ShenandoahNMethod*>* list = ShenandoahCodeRoots::_recorded_nms;
-
-  size_t max = (size_t)list->length();
-  while (_claimed < max) {
-    size_t cur = Atomic::add(&_claimed, stride) - stride;
-    size_t start = cur;
-    size_t end = MIN2(cur + stride, max);
-    if (start >= max) break;
-
-    for (size_t idx = start; idx < end; idx++) {
-      ShenandoahNMethod* nmr = list->at((int) idx);
-      nmr->assert_alive_and_correct();
-
-      if (CSET_FILTER && !nmr->has_cset_oops(_heap)) {
-        continue;
-      }
-
-      f->do_code_blob(nmr->nm());
-    }
-  }
-}
-
-ShenandoahNMethod::ShenandoahNMethod(nmethod* nm, GrowableArray<oop*>* oops) {
-  _nm = nm;
-  _oops = NEW_C_HEAP_ARRAY(oop*, oops->length(), mtGC);
-  _oops_count = oops->length();
-  for (int c = 0; c < _oops_count; c++) {
-    _oops[c] = oops->at(c);
-  }
+  assert(_table_snapshot != NULL, "Sanity");
+  _table_snapshot->parallel_blobs_do<CSET_FILTER>(f);
 }
 
-ShenandoahNMethod::~ShenandoahNMethod() {
-  if (_oops != NULL) {
-    FREE_C_HEAP_ARRAY(oop*, _oops);
-  }
-}
-
-bool ShenandoahNMethod::has_cset_oops(ShenandoahHeap *heap) {
-  for (int c = 0; c < _oops_count; c++) {
-    oop o = RawAccess<>::oop_load(_oops[c]);
-    if (heap->in_collection_set(o)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-#ifdef ASSERT
-void ShenandoahNMethod::assert_alive_and_correct() {
-  assert(_nm->is_alive(), "only alive nmethods here");
-  assert(_oops_count > 0, "should have filtered nmethods without oops before");
-  ShenandoahHeap* heap = ShenandoahHeap::heap();
-  for (int c = 0; c < _oops_count; c++) {
-    oop *loc = _oops[c];
-    assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
-    oop o = RawAccess<>::oop_load(loc);
-    shenandoah_assert_correct_except(loc, o,
-             o == NULL ||
-             heap->is_full_gc_move_in_progress() ||
-             (VMThread::vm_operation() != NULL) && (VMThread::vm_operation()->type() == VM_Operation::VMOp_HeapWalkOperation)
-    );
-  }
-}
-
-void ShenandoahNMethod::assert_same_oops(GrowableArray<oop*>* oops) {
-  assert(_oops_count == oops->length(), "should have the same number of oop*");
-  for (int c = 0; c < _oops_count; c++) {
-    assert(_oops[c] == oops->at(c), "should be the same oop*");
-  }
-}
-#endif
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,6 +27,7 @@
 #include "code/codeCache.hpp"
 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
 #include "gc/shenandoah/shenandoahLock.hpp"
+#include "gc/shenandoah/shenandoahNMethod.hpp"
 #include "memory/allocation.hpp"
 #include "memory/iterator.hpp"
 
@@ -62,43 +63,13 @@
   void parallel_blobs_do(CodeBlobClosure* f);
 };
 
-// ShenandoahNMethod tuple records the internal locations of oop slots within the nmethod.
-// This allows us to quickly scan the oops without doing the nmethod-internal scans, that
-// sometimes involves parsing the machine code. Note it does not record the oops themselves,
-// because it would then require handling these tuples as the new class of roots.
-class ShenandoahNMethod : public CHeapObj<mtGC> {
-private:
-  nmethod* _nm;
-  oop**    _oops;
-  int      _oops_count;
-
-public:
-  ShenandoahNMethod(nmethod *nm, GrowableArray<oop*>* oops);
-  ~ShenandoahNMethod();
-
-  nmethod* nm() {
-    return _nm;
-  }
-
-  bool has_cset_oops(ShenandoahHeap* heap);
-
-  void assert_alive_and_correct() NOT_DEBUG_RETURN;
-  void assert_same_oops(GrowableArray<oop*>* oops) NOT_DEBUG_RETURN;
-
-  static bool find_with_nmethod(void* nm, ShenandoahNMethod* other) {
-    return other->_nm == nm;
-  }
-};
-
 class ShenandoahCodeRootsIterator {
   friend class ShenandoahCodeRoots;
 protected:
-  ShenandoahHeap* _heap;
   ShenandoahParallelCodeCacheIterator _par_iterator;
   ShenandoahSharedFlag _seq_claimed;
-  DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
-  volatile size_t _claimed;
-  DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
+  ShenandoahNMethodTableSnapshot* _table_snapshot;
+
 protected:
   ShenandoahCodeRootsIterator();
   ~ShenandoahCodeRootsIterator();
@@ -128,12 +99,24 @@
 
 public:
   static void initialize();
-  static void add_nmethod(nmethod* nm);
-  static void remove_nmethod(nmethod* nm);
+  static void register_nmethod(nmethod* nm);
+  static void unregister_nmethod(nmethod* nm);
+  static void flush_nmethod(nmethod* nm);
+
+  static ShenandoahNMethodTable* table() {
+    return _nmethod_table;
+  }
+
+  // Concurrent nmethod unloading support
+  static void unlink(WorkGang* workers, bool unloading_occurred);
+  static void purge(WorkGang* workers);
+  static void prepare_concurrent_unloading();
+  static int  disarmed_value()         { return _disarmed_value; }
+  static int* disarmed_value_address() { return &_disarmed_value; }
 
 private:
-  static GrowableArray<ShenandoahNMethod*>* _recorded_nms;
-  static ShenandoahLock                     _recorded_nms_lock;
+  static ShenandoahNMethodTable* _nmethod_table;
+  static int                     _disarmed_value;
 };
 
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,9 +32,21 @@
 }
 
 bool ShenandoahConcurrentRoots::should_do_concurrent_roots() {
-  ShenandoahHeap* const heap = ShenandoahHeap::heap();
-  bool stw_gc_in_progress = heap->is_full_gc_in_progress() ||
-                            heap->is_degenerated_gc_in_progress();
   return can_do_concurrent_roots() &&
-         !stw_gc_in_progress;
+         !ShenandoahHeap::heap()->is_stw_gc_in_progress();
 }
+
+bool ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() {
+#if defined(X86) && !defined(SOLARIS)
+  return ShenandoahCodeRootsStyle == 2 &&
+         ClassUnloading &&
+         strcmp(ShenandoahGCMode, "traversal") != 0;
+#else
+  return false;
+#endif
+}
+
+bool ShenandoahConcurrentRoots::should_do_concurrent_class_unloading() {
+  return can_do_concurrent_class_unloading() &&
+         !ShenandoahHeap::heap()->is_stw_gc_in_progress();
+}
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,11 @@
   static bool can_do_concurrent_roots();
   // If current GC cycle can process roots concurrently
   static bool should_do_concurrent_roots();
+
+  // If GC settings allow concurrent class unloading
+  static bool can_do_concurrent_class_unloading();
+  // If current GC cycle can unload classes concurrently
+  static bool should_do_concurrent_class_unloading();
 };
 
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,6 +37,7 @@
 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
 #include "memory/iterator.hpp"
 #include "memory/universe.hpp"
+#include "runtime/atomic.hpp"
 
 ShenandoahControlThread::ShenandoahControlThread() :
   ConcurrentGCThread(),
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,7 @@
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "gc/shenandoah/shenandoahEvacOOMHandler.hpp"
 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "runtime/thread.hpp"
 
@@ -113,7 +113,7 @@
 void ShenandoahEvacOOMHandler::clear() {
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
   assert((Atomic::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) == 0, "sanity");
-  Atomic::release_store_fence<jint>(&_threads_in_evac, 0);
+  Atomic::release_store_fence(&_threads_in_evac, (jint)0);
 }
 
 ShenandoahEvacOOMScope::ShenandoahEvacOOMScope() {
--- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,6 @@
 #include "gc/shenandoah/shenandoahAsserts.hpp"
 #include "gc/shenandoah/shenandoahForwarding.hpp"
 #include "oops/markWord.inline.hpp"
-#include "runtime/atomic.hpp"
 
 inline HeapWord* ShenandoahForwarding::get_forwardee_raw(oop obj) {
   shenandoah_assert_in_heap(NULL, obj);
--- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -29,6 +29,7 @@
 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
 #include "gc/shenandoah/shenandoahTraversalGC.hpp"
 #include "logging/logStream.hpp"
+#include "runtime/orderAccess.hpp"
 
 ShenandoahFreeSet::ShenandoahFreeSet(ShenandoahHeap* heap, size_t max_regions) :
   _heap(heap),
@@ -148,6 +149,11 @@
 HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, ShenandoahAllocRequest& req, bool& in_new_region) {
   assert (!has_no_alloc_capacity(r), "Performance: should avoid full regions on this path: " SIZE_FORMAT, r->region_number());
 
+  if (_heap->is_concurrent_root_in_progress() &&
+      r->is_trash()) {
+    return NULL;
+  }
+
   try_recycle_trashed(r);
 
   in_new_region = r->is_empty();
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -71,8 +71,10 @@
 
 #include "memory/metaspace.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/safepointMechanism.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/mallocTracker.hpp"
@@ -1074,7 +1076,8 @@
     // Include concurrent roots if current cycle can not process those roots concurrently
     ShenandoahRootEvacuator rp(workers()->active_workers(),
                                ShenandoahPhaseTimings::init_evac,
-                               !ShenandoahConcurrentRoots::should_do_concurrent_roots());
+                               !ShenandoahConcurrentRoots::should_do_concurrent_roots(),
+                               !ShenandoahConcurrentRoots::should_do_concurrent_class_unloading());
     ShenandoahEvacuateUpdateRootsTask roots_task(&rp);
     workers()->run_task(&roots_task);
   }
@@ -1546,6 +1549,8 @@
       set_has_forwarded_objects(true);
 
       if (!is_degenerated_gc_in_progress()) {
+        prepare_concurrent_roots();
+        prepare_concurrent_unloading();
         evacuate_and_update_roots();
       }
 
@@ -1554,13 +1559,16 @@
       }
 
       if (ShenandoahVerify) {
+        ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::None;
         if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
-          ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots);
+          types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots);
           types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CLDGRoots);
-          verifier()->verify_roots_no_forwarded_except(types);
-        } else {
-          verifier()->verify_roots_no_forwarded();
         }
+
+        if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
+          types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CodeRoots);
+        }
+        verifier()->verify_roots_no_forwarded_except(types);
         verifier()->verify_during_evacuation();
       }
     } else {
@@ -1656,11 +1664,18 @@
 };
 
 void ShenandoahHeap::op_roots() {
-  if (is_evacuation_in_progress() &&
-      ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
-    ShenandoahConcurrentRootsEvacUpdateTask task;
-    workers()->run_task(&task);
+  if (is_evacuation_in_progress()) {
+    if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
+      _unloader.unload();
+    }
+
+    if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
+      ShenandoahConcurrentRootsEvacUpdateTask task;
+      workers()->run_task(&task);
+    }
   }
+
+  set_concurrent_root_in_progress(false);
 }
 
 void ShenandoahHeap::op_reset() {
@@ -1918,6 +1933,15 @@
   set_gc_state_mask(EVACUATION, in_progress);
 }
 
+void ShenandoahHeap::set_concurrent_root_in_progress(bool in_progress) {
+  assert(ShenandoahConcurrentRoots::can_do_concurrent_roots(), "Why set the flag?");
+  if (in_progress) {
+    _concurrent_root_in_progress.set();
+  } else {
+    _concurrent_root_in_progress.unset();
+  }
+}
+
 void ShenandoahHeap::ref_processing_init() {
   assert(_max_workers > 0, "Sanity");
 
@@ -2026,10 +2050,10 @@
   MetaspaceUtils::verify_metrics();
 }
 
-// Process leftover weak oops: update them, if needed or assert they do not
-// need updating otherwise.
-// Weak processor API requires us to visit the oops, even if we are not doing
-// anything to them.
+// Weak roots are either pre-evacuated (final mark) or updated (final updaterefs),
+// so they should not have forwarded oops.
+// However, we do need to "null" dead oops in the roots, if can not be done
+// in concurrent cycles.
 void ShenandoahHeap::stw_process_weak_roots(bool full_gc) {
   ShenandoahGCPhase root_phase(full_gc ?
                                ShenandoahPhaseTimings::full_gc_purge :
@@ -2071,7 +2095,9 @@
 void ShenandoahHeap::parallel_cleaning(bool full_gc) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
   stw_process_weak_roots(full_gc);
-  stw_unload_classes(full_gc);
+  if (!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
+    stw_unload_classes(full_gc);
+  }
 }
 
 void ShenandoahHeap::set_has_forwarded_objects(bool cond) {
@@ -2139,11 +2165,15 @@
 }
 
 void ShenandoahHeap::register_nmethod(nmethod* nm) {
-  ShenandoahCodeRoots::add_nmethod(nm);
+  ShenandoahCodeRoots::register_nmethod(nm);
 }
 
 void ShenandoahHeap::unregister_nmethod(nmethod* nm) {
-  ShenandoahCodeRoots::remove_nmethod(nm);
+  ShenandoahCodeRoots::unregister_nmethod(nm);
+}
+
+void ShenandoahHeap::flush_nmethod(nmethod* nm) {
+  ShenandoahCodeRoots::flush_nmethod(nm);
 }
 
 oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) {
@@ -2190,6 +2220,28 @@
   return _gc_timer;
 }
 
+void ShenandoahHeap::prepare_concurrent_roots() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+  if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
+    set_concurrent_root_in_progress(true);
+  }
+}
+
+void ShenandoahHeap::prepare_concurrent_unloading() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+  if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
+    ShenandoahCodeRoots::prepare_concurrent_unloading();
+    _unloader.prepare();
+  }
+}
+
+void ShenandoahHeap::finish_concurrent_unloading() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+  if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
+    _unloader.finish();
+  }
+}
+
 #ifdef ASSERT
 void ShenandoahHeap::assert_gc_workers(uint nworkers) {
   assert(nworkers > 0 && nworkers <= max_workers(), "Sanity");
@@ -2313,6 +2365,8 @@
 void ShenandoahHeap::op_final_updaterefs() {
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint");
 
+  finish_concurrent_unloading();
+
   // Check if there is left-over work, and finish it
   if (_update_refs_iterator.has_next()) {
     ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_finish_work);
@@ -2330,7 +2384,7 @@
   assert(!cancelled_gc(), "Should have been done right before");
 
   if (ShenandoahVerify && !is_degenerated_gc_in_progress()) {
-    verifier()->verify_roots_no_forwarded_except(ShenandoahRootVerifier::ThreadRoots);
+    verifier()->verify_roots_in_to_space_except(ShenandoahRootVerifier::ThreadRoots);
   }
 
   if (is_degenerated_gc_in_progress()) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,7 @@
 #include "gc/shenandoah/shenandoahLock.hpp"
 #include "gc/shenandoah/shenandoahEvacOOMHandler.hpp"
 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
+#include "gc/shenandoah/shenandoahUnload.hpp"
 #include "services/memoryManager.hpp"
 
 class ConcurrentGCTimer;
@@ -271,6 +272,7 @@
   ShenandoahSharedFlag   _full_gc_in_progress;
   ShenandoahSharedFlag   _full_gc_move_in_progress;
   ShenandoahSharedFlag   _progress_last_gc;
+  ShenandoahSharedFlag   _concurrent_root_in_progress;
 
   void set_gc_state_all_threads(char state);
   void set_gc_state_mask(uint mask, bool value);
@@ -287,6 +289,7 @@
   void set_full_gc_move_in_progress(bool in_progress);
   void set_concurrent_traversal_in_progress(bool in_progress);
   void set_has_forwarded_objects(bool cond);
+  void set_concurrent_root_in_progress(bool cond);
 
   inline bool is_stable() const;
   inline bool is_idle() const;
@@ -299,6 +302,8 @@
   inline bool is_concurrent_traversal_in_progress() const;
   inline bool has_forwarded_objects() const;
   inline bool is_gc_in_progress_mask(uint mask) const;
+  inline bool is_stw_gc_in_progress() const;
+  inline bool is_concurrent_root_in_progress() const;
 
 // ---------- GC cancellation and degeneration machinery
 //
@@ -511,6 +516,7 @@
 //
 private:
   ShenandoahSharedFlag _unload_classes;
+  ShenandoahUnload     _unloader;
 
 public:
   void set_unload_classes(bool uc);
@@ -523,6 +529,12 @@
   void stw_unload_classes(bool full_gc);
   void stw_process_weak_roots(bool full_gc);
 
+  // Prepare concurrent root processing
+  void prepare_concurrent_roots();
+  // Prepare and finish concurrent unloading
+  void prepare_concurrent_unloading();
+  void finish_concurrent_unloading();
+
 // ---------- Generic interface hooks
 // Minor things that super-interface expects us to implement to play nice with
 // the rest of runtime. Some of the things here are not required to be implemented,
@@ -562,7 +574,7 @@
 public:
   void register_nmethod(nmethod* nm);
   void unregister_nmethod(nmethod* nm);
-  void flush_nmethod(nmethod* nm) {}
+  void flush_nmethod(nmethod* nm);
   void verify_nmethod(nmethod* nm) {}
 
 // ---------- Pinning hooks
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -372,6 +372,14 @@
   return _gc_state.is_set(UPDATEREFS);
 }
 
+inline bool ShenandoahHeap::is_stw_gc_in_progress() const {
+  return is_full_gc_in_progress() || is_degenerated_gc_in_progress();
+}
+
+inline bool ShenandoahHeap::is_concurrent_root_in_progress() const {
+  return _concurrent_root_in_progress.is_set();
+}
+
 template<class T>
 inline void ShenandoahHeap::marked_object_iterate(ShenandoahHeapRegion* region, T* cl) {
   marked_object_iterate(region, cl, region->top());
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,6 +34,7 @@
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/java.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,6 +27,7 @@
 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
 #include "gc/shenandoah/shenandoahHeapRegionCounters.hpp"
 #include "memory/resourceArea.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/perfData.inline.hpp"
 
 ShenandoahHeapRegionCounters::ShenandoahHeapRegionCounters() :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 "runtime/os.hpp"
+
+#include "gc/shenandoah/shenandoahLock.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/os.inline.hpp"
+#include "runtime/thread.hpp"
+
+ShenandoahSimpleLock::ShenandoahSimpleLock() {
+  assert(os::mutex_init_done(), "Too early!");
+}
+
+void ShenandoahSimpleLock::lock() {
+  _lock.lock();
+}
+
+void ShenandoahSimpleLock::unlock() {
+  _lock.unlock();
+}
+
+ShenandoahReentrantLock::ShenandoahReentrantLock() :
+  ShenandoahSimpleLock(), _owner(NULL), _count(0) {
+  assert(os::mutex_init_done(), "Too early!");
+}
+
+ShenandoahReentrantLock::~ShenandoahReentrantLock() {
+  assert(_count == 0, "Unbalance");
+}
+
+void ShenandoahReentrantLock::lock() {
+  Thread* const thread = Thread::current();
+  Thread* const owner = Atomic::load(&_owner);
+
+  if (owner != thread) {
+    ShenandoahSimpleLock::lock();
+    Atomic::store(&_owner, thread);
+  }
+
+  _count++;
+}
+
+void ShenandoahReentrantLock::unlock() {
+  assert(owned_by_self(), "Invalid owner");
+  assert(_count > 0, "Invalid count");
+
+  _count--;
+
+  if (_count == 0) {
+    Atomic::store(&_owner, (Thread*)NULL);
+    ShenandoahSimpleLock::unlock();
+  }
+}
+
+bool ShenandoahReentrantLock::owned_by_self() const {
+  Thread* const thread = Thread::current();
+  Thread* const owner = Atomic::load(&_owner);
+  return owner == thread;
+}
--- a/src/hotspot/share/gc/shenandoah/shenandoahLock.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahLock.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
 #define SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP
 
 #include "memory/allocation.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
 
 class ShenandoahLock  {
@@ -96,4 +97,50 @@
   }
 };
 
+class ShenandoahSimpleLock {
+private:
+  os::PlatformMonitor   _lock; // native lock
+public:
+  ShenandoahSimpleLock();
+
+  virtual void lock();
+  virtual void unlock();
+};
+
+class ShenandoahReentrantLock : public ShenandoahSimpleLock {
+private:
+  Thread* volatile      _owner;
+  uint64_t              _count;
+
+public:
+  ShenandoahReentrantLock();
+  ~ShenandoahReentrantLock();
+
+  virtual void lock();
+  virtual void unlock();
+
+  // If the lock already owned by this thread
+  bool owned_by_self() const ;
+};
+
+class ShenandoahReentrantLocker : public StackObj {
+private:
+  ShenandoahReentrantLock* const _lock;
+
+public:
+  ShenandoahReentrantLocker(ShenandoahReentrantLock* lock) :
+    _lock(lock) {
+    if (_lock != NULL) {
+      _lock->lock();
+    }
+  }
+
+  ~ShenandoahReentrantLocker() {
+    if (_lock != NULL) {
+      assert(_lock->owned_by_self(), "Must be owner");
+      _lock->unlock();
+    }
+  }
+};
+
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -48,6 +48,7 @@
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/growableArray.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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/shenandoah/shenandoahClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
+#include "memory/resourceArea.hpp"
+
+ShenandoahNMethod::ShenandoahNMethod(nmethod* nm, GrowableArray<oop*>& oops, bool non_immediate_oops) :
+  _nm(nm), _oops(NULL), _oops_count(0), _unregistered(false) {
+
+  if (!oops.is_empty()) {
+    _oops_count = oops.length();
+    _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
+    for (int c = 0; c < _oops_count; c++) {
+      _oops[c] = oops.at(c);
+    }
+  }
+  _has_non_immed_oops = non_immediate_oops;
+
+  assert_same_oops();
+}
+
+ShenandoahNMethod::~ShenandoahNMethod() {
+  if (_oops != NULL) {
+    FREE_C_HEAP_ARRAY(oop*, _oops);
+  }
+}
+
+class ShenandoahHasCSetOopClosure : public OopClosure {
+private:
+  ShenandoahHeap* const _heap;
+  bool                  _has_cset_oops;
+
+public:
+  ShenandoahHasCSetOopClosure() :
+    _heap(ShenandoahHeap::heap()),
+    _has_cset_oops(false) {
+  }
+
+  bool has_cset_oops() const {
+    return _has_cset_oops;
+  }
+
+  void do_oop(oop* p) {
+    oop value = RawAccess<>::oop_load(p);
+    if (!_has_cset_oops && _heap->in_collection_set(value)) {
+      _has_cset_oops = true;
+    }
+  }
+
+  void do_oop(narrowOop* p) {
+    ShouldNotReachHere();
+  }
+};
+
+bool ShenandoahNMethod::has_cset_oops(ShenandoahHeap *heap) {
+  ShenandoahHasCSetOopClosure cl;
+  oops_do(&cl);
+  return cl.has_cset_oops();
+}
+
+void ShenandoahNMethod::update() {
+  ResourceMark rm;
+  bool non_immediate_oops = false;
+  GrowableArray<oop*> oops;
+
+  detect_reloc_oops(nm(), oops, non_immediate_oops);
+  if (oops.length() != _oops_count) {
+    if (_oops != NULL) {
+      FREE_C_HEAP_ARRAY(oop*, _oops);
+      _oops = NULL;
+    }
+
+    _oops_count = oops.length();
+    if (_oops_count > 0) {
+      _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
+    }
+  }
+
+  for (int index = 0; index < _oops_count; index ++) {
+    _oops[index] = oops.at(index);
+  }
+  _has_non_immed_oops = non_immediate_oops;
+
+  assert_same_oops();
+}
+
+void ShenandoahNMethod::oops_do(OopClosure* oops, bool fix_relocations) {
+  for (int c = 0; c < _oops_count; c ++) {
+    oops->do_oop(_oops[c]);
+  }
+
+  oop* const begin = _nm->oops_begin();
+  oop* const end = _nm->oops_end();
+  for (oop* p = begin; p < end; p++) {
+    if (*p != Universe::non_oop_word()) {
+      oops->do_oop(p);
+    }
+  }
+
+  if (fix_relocations && _has_non_immed_oops) {
+    _nm->fix_oop_relocations();
+  }
+}
+
+void ShenandoahNMethod::detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& has_non_immed_oops) {
+  has_non_immed_oops = false;
+  // Find all oops relocations
+  RelocIterator iter(nm);
+  while (iter.next()) {
+    if (iter.type() != relocInfo::oop_type) {
+      // Not an oop
+      continue;
+    }
+
+    oop_Relocation* r = iter.oop_reloc();
+    if (!r->oop_is_immediate()) {
+      // Non-immediate oop found
+      has_non_immed_oops = true;
+      continue;
+    }
+
+    if (r->oop_value() != NULL) {
+      // Non-NULL immediate oop found. NULL oops can safely be
+      // ignored since the method will be re-registered if they
+      // are later patched to be non-NULL.
+      oops.push(r->oop_addr());
+    }
+  }
+}
+
+ShenandoahNMethod* ShenandoahNMethod::for_nmethod(nmethod* nm) {
+  ResourceMark rm;
+  bool non_immediate_oops = false;
+  GrowableArray<oop*> oops;
+
+  detect_reloc_oops(nm, oops, non_immediate_oops);
+
+  // No embedded oops
+  if(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() &&
+    oops.is_empty() && nm->oops_begin() >= nm->oops_end()) {
+    return NULL;
+  }
+
+  return new ShenandoahNMethod(nm, oops, non_immediate_oops);
+}
+
+void ShenandoahNMethod::heal_nmethod(nmethod* nm) {
+  ShenandoahNMethod* data = gc_data(nm);
+  assert(data != NULL, "Sanity");
+  assert(data->lock()->owned_by_self(), "Must hold the lock");
+
+  ShenandoahEvacuateUpdateRootsClosure cl;
+  data->oops_do(&cl, true /*fix relocation*/);
+}
+
+#ifdef ASSERT
+void ShenandoahNMethod::assert_alive_and_correct() {
+  assert(_nm->is_alive(), "only alive nmethods here");
+  ShenandoahHeap* heap = ShenandoahHeap::heap();
+  for (int c = 0; c < _oops_count; c++) {
+    oop *loc = _oops[c];
+    assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
+    oop o = RawAccess<>::oop_load(loc);
+    shenandoah_assert_correct_except(loc, o, o == NULL || heap->is_full_gc_move_in_progress());
+  }
+
+  oop* const begin = _nm->oops_begin();
+  oop* const end = _nm->oops_end();
+  for (oop* p = begin; p < end; p++) {
+    if (*p != Universe::non_oop_word()) {
+      oop o = RawAccess<>::oop_load(p);
+      shenandoah_assert_correct_except(p, o, o == NULL || heap->is_full_gc_move_in_progress());
+    }
+  }
+}
+
+class ShenandoahNMethodOopDetector : public OopClosure {
+private:
+  ResourceMark rm; // For growable array allocation below.
+  GrowableArray<oop*> _oops;
+
+public:
+  ShenandoahNMethodOopDetector() : _oops(10) {};
+
+  void do_oop(oop* o) {
+    _oops.append(o);
+  }
+  void do_oop(narrowOop* o) {
+    fatal("NMethods should not have compressed oops embedded.");
+  }
+
+  GrowableArray<oop*>* oops() {
+    return &_oops;
+  }
+
+  bool has_oops() {
+    return !_oops.is_empty();
+  }
+};
+
+void ShenandoahNMethod::assert_same_oops(bool allow_dead) {
+  ShenandoahNMethodOopDetector detector;
+  nm()->oops_do(&detector, allow_dead);
+
+  GrowableArray<oop*>* oops = detector.oops();
+
+  assert(oops->length() == oop_count(), "Must match");
+
+  for (int index = 0; index < _oops_count; index ++) {
+    assert(oops->contains(_oops[index]), "Must contain this oop");
+  }
+
+  for (oop* p = nm()->oops_begin(); p < nm()->oops_end(); p ++) {
+    assert(oops->contains(p), "Must contain this oop");
+  }
+}
+
+void ShenandoahNMethod::assert_no_oops(nmethod* nm, bool allow_dead) {
+  ShenandoahNMethodOopDetector detector;
+  nm->oops_do(&detector, allow_dead);
+  assert(detector.oops()->length() == 0, "Should not have oops");
+}
+#endif
+
+ShenandoahNMethodTable::ShenandoahNMethodTable() :
+  _heap(ShenandoahHeap::heap()),
+  _size(minSize),
+  _index(0),
+  _iteration_in_progress(false) {
+  _array = NEW_C_HEAP_ARRAY(ShenandoahNMethod*, _size, mtGC);
+}
+
+ShenandoahNMethodTable::~ShenandoahNMethodTable() {
+  assert(_array != NULL, "Sanity");
+  FREE_C_HEAP_ARRAY(ShenandoahNMethod*, _array);
+}
+
+void ShenandoahNMethodTable::register_nmethod(nmethod* nm) {
+  assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
+  assert(_index >= 0 && _index <= _size, "Sanity");
+
+  ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
+  ShenandoahReentrantLocker data_locker(data != NULL ? data->lock() : NULL);
+
+  if (data != NULL) {
+    assert(contain(nm), "Must have been registered");
+    data->update();
+  } else {
+    data = ShenandoahNMethod::for_nmethod(nm);
+    if (data == NULL) {
+      assert(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
+             "Only possible when concurrent class unloading is off");
+      return;
+    }
+    ShenandoahNMethod::attach_gc_data(nm, data);
+    ShenandoahLocker locker(&_lock);
+    log_register_nmethod(nm);
+    append(data);
+  }
+  // Disarm new nmethod
+  ShenandoahNMethod::disarm_nmethod(nm);
+}
+
+void ShenandoahNMethodTable::unregister_nmethod(nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
+  if (data == NULL) {
+    assert(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
+           "Only possible when concurrent class unloading is off");
+    ShenandoahNMethod::assert_no_oops(nm, true /*allow_dead*/);
+    return;
+  }
+
+  if (Thread::current()->is_Code_cache_sweeper_thread()) {
+    wait_until_concurrent_iteration_done();
+  }
+  log_unregister_nmethod(nm);
+  ShenandoahLocker locker(&_lock);
+  assert(contain(nm), "Must have been registered");
+
+  ShenandoahReentrantLocker data_locker(data->lock());
+  data->mark_unregistered();
+}
+
+void ShenandoahNMethodTable::flush_nmethod(nmethod* nm) {
+  assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
+  assert(Thread::current()->is_Code_cache_sweeper_thread(), "Must from Sweep thread");
+  ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
+  assert(data != NULL || !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
+         "Only possible when concurrent class unloading is off");
+  if (data == NULL) {
+    ShenandoahNMethod::assert_no_oops(nm, true /*allow_dead*/);
+    return;
+  }
+
+  // Can not alter the array when iteration is in progress
+  wait_until_concurrent_iteration_done();
+  log_flush_nmethod(nm);
+
+  ShenandoahLocker locker(&_lock);
+  int idx = index_of(nm);
+  assert(idx >= 0 && idx < _index, "Invalid index");
+  ShenandoahNMethod::attach_gc_data(nm, NULL);
+  remove(idx);
+}
+
+bool ShenandoahNMethodTable::contain(nmethod* nm) const {
+  return index_of(nm) != -1;
+}
+
+ShenandoahNMethod* ShenandoahNMethodTable::at(int index) const {
+  assert(index >= 0 && index < _index, "Out of bound");
+  return _array[index];
+}
+
+int ShenandoahNMethodTable::index_of(nmethod* nm) const {
+  for (int index = 0; index < length(); index ++) {
+    if (_array[index]->nm() == nm) {
+      return index;
+    }
+  }
+  return -1;
+}
+
+void ShenandoahNMethodTable::remove(int idx) {
+  shenandoah_assert_locked_or_safepoint(CodeCache_lock);
+  assert(!_iteration_in_progress, "Can not happen");
+  assert(_index >= 0 && _index <= _size, "Sanity");
+
+  assert(idx >= 0 && idx < _index, "Out of bound");
+  ShenandoahNMethod* snm = _array[idx];
+
+  _index --;
+  _array[idx] = _array[_index];
+
+  delete snm;
+}
+
+void ShenandoahNMethodTable::wait_until_concurrent_iteration_done() {
+  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
+  while (iteration_in_progress()) {
+    CodeCache_lock->wait_without_safepoint_check();
+  }
+}
+
+void ShenandoahNMethodTable::append(ShenandoahNMethod* snm) {
+  if (is_full()) {
+    int new_size = 2 * _size;
+    ShenandoahNMethod** old_table = _array;
+
+    // Rebuild table and replace current one
+    rebuild(new_size);
+
+    // An iteration is in progress over early snapshot,
+    // can not release the array until iteration is completed
+    if (!iteration_in_progress()) {
+      FREE_C_HEAP_ARRAY(ShenandoahNMethod*, old_table);
+    }
+  }
+
+  _array[_index ++] = snm;
+  assert(_index >= 0 && _index <= _size, "Sanity");
+}
+
+void ShenandoahNMethodTable::rebuild(int size) {
+  ShenandoahNMethod** arr = NEW_C_HEAP_ARRAY(ShenandoahNMethod*, size, mtGC);
+  for (int index = 0; index < _index; index ++) {
+      arr[index] = _array[index];
+  }
+  _array = arr;
+  _size = size;
+}
+
+ShenandoahNMethodTableSnapshot* ShenandoahNMethodTable::snapshot_for_iteration() {
+  assert(!iteration_in_progress(), "Already in progress");
+  _iteration_in_progress = true;
+
+  return new ShenandoahNMethodTableSnapshot(this);
+}
+
+void ShenandoahNMethodTable::finish_iteration(ShenandoahNMethodTableSnapshot* snapshot) {
+  assert(iteration_in_progress(), "Why we here?");
+  assert(snapshot != NULL, "No snapshot");
+  _iteration_in_progress = false;
+
+  // Table has been rebuilt during iteration, free old table
+  if (snapshot->_array != _array) {
+    FREE_C_HEAP_ARRAY(ShenandoahNMethod*, snapshot->_array);
+  }
+  delete snapshot;
+}
+
+void ShenandoahNMethodTable::log_register_nmethod(nmethod* nm) {
+  LogTarget(Debug, gc, nmethod) log;
+  if (!log.is_enabled()) {
+    return;
+  }
+
+  ResourceMark rm;
+  log.print("Register NMethod: %s.%s [" PTR_FORMAT "] (%s)",
+            nm->method()->method_holder()->external_name(),
+            nm->method()->name()->as_C_string(),
+            p2i(nm),
+            nm->compiler_name());
+}
+
+void ShenandoahNMethodTable::log_unregister_nmethod(nmethod* nm) {
+  LogTarget(Debug, gc, nmethod) log;
+  if (!log.is_enabled()) {
+    return;
+  }
+
+  ResourceMark rm;
+  log.print("Unregister NMethod: %s.%s [" PTR_FORMAT "]",
+            nm->method()->method_holder()->external_name(),
+            nm->method()->name()->as_C_string(),
+            p2i(nm));
+}
+
+void ShenandoahNMethodTable::log_flush_nmethod(nmethod* nm) {
+  LogTarget(Debug, gc, nmethod) log;
+  if (!log.is_enabled()) {
+    return;
+  }
+
+  ResourceMark rm;
+  log.print("Flush NMethod: (" PTR_FORMAT ")", p2i(nm));
+}
+
+#ifdef ASSERT
+void ShenandoahNMethodTable::assert_nmethods_alive_and_correct() {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  for (int index = 0; index < length(); index ++) {
+    ShenandoahNMethod* m = _array[index];
+    // Concurrent unloading may have dead nmethods to be cleaned by sweeper
+    if (m->is_unregistered()) continue;
+    m->assert_alive_and_correct();
+  }
+}
+#endif
+
+ShenandoahNMethodTableSnapshot::ShenandoahNMethodTableSnapshot(ShenandoahNMethodTable* table) :
+  _heap(ShenandoahHeap::heap()), _table(table), _array(table->_array), _length(table->_index), _claimed(0) {
+}
+
+void ShenandoahNMethodTableSnapshot::concurrent_nmethods_do(NMethodClosure* cl) {
+  size_t stride = 256; // educated guess
+
+  ShenandoahNMethod** list = _array;
+  size_t max = (size_t)_length;
+  while (_claimed < max) {
+    size_t cur = Atomic::add(&_claimed, stride) - stride;
+    size_t start = cur;
+    size_t end = MIN2(cur + stride, max);
+    if (start >= max) break;
+
+    for (size_t idx = start; idx < end; idx++) {
+      ShenandoahNMethod* data = list[idx];
+      assert(data != NULL, "Should not be NULL");
+      if (!data->is_unregistered()) {
+        cl->do_nmethod(data->nm());
+      }
+    }
+  }
+}
+
+ShenandoahConcurrentNMethodIterator::ShenandoahConcurrentNMethodIterator(ShenandoahNMethodTable* table) :
+  _table(table), _table_snapshot(NULL) {
+}
+
+void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
+  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
+  assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
+         "Only for concurrent class unloading");
+  _table_snapshot = _table->snapshot_for_iteration();
+}
+
+void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
+  assert(_table_snapshot != NULL, "Must first call nmethod_do_begin()");
+  _table_snapshot->concurrent_nmethods_do(cl);
+}
+
+void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
+  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
+  assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
+         "Only for concurrent class unloading");
+  _table->finish_iteration(_table_snapshot);
+  CodeCache_lock->notify_all();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_SHENANDOAH_SHENANDOAHNMETHOD_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHNMETHOD_HPP
+
+#include "code/nmethod.hpp"
+#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahLock.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/growableArray.hpp"
+
+// ShenandoahNMethod tuple records the internal locations of oop slots within reclocation stream in
+// the nmethod. This allows us to quickly scan the oops without doing the nmethod-internal scans,
+// that sometimes involves parsing the machine code. Note it does not record the oops themselves,
+// because it would then require handling these tuples as the new class of roots.
+class ShenandoahNMethod : public CHeapObj<mtGC> {
+private:
+  nmethod* const          _nm;
+  oop**                   _oops;
+  int                     _oops_count;
+  bool                    _has_non_immed_oops;
+  bool                    _unregistered;
+  ShenandoahReentrantLock _lock;
+
+public:
+  ShenandoahNMethod(nmethod *nm, GrowableArray<oop*>& oops, bool has_non_immed_oops);
+  ~ShenandoahNMethod();
+
+  inline nmethod* nm() const;
+  inline ShenandoahReentrantLock* lock();
+  void oops_do(OopClosure* oops, bool fix_relocations = false);
+  // Update oops when the nmethod is re-registered
+  void update();
+
+  bool has_cset_oops(ShenandoahHeap* heap);
+
+  inline int oop_count() const;
+  inline bool has_oops() const;
+
+  inline void mark_unregistered();
+  inline bool is_unregistered() const;
+
+  static ShenandoahNMethod* for_nmethod(nmethod* nm);
+  static inline ShenandoahReentrantLock* lock_for_nmethod(nmethod* nm);
+
+  static void heal_nmethod(nmethod* nm);
+  static inline void disarm_nmethod(nmethod* nm);
+
+  static inline ShenandoahNMethod* gc_data(nmethod* nm);
+  static inline void attach_gc_data(nmethod* nm, ShenandoahNMethod* gc_data);
+
+  void assert_alive_and_correct() NOT_DEBUG_RETURN;
+  void assert_same_oops(bool allow_dead = false) NOT_DEBUG_RETURN;
+  static void assert_no_oops(nmethod* nm, bool allow_dea = false) NOT_DEBUG_RETURN;
+
+private:
+  bool has_non_immed_oops() const { return _has_non_immed_oops; }
+  static void detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& _has_non_immed_oops);
+};
+
+class ShenandoahNMethodTable;
+
+// An opaque snapshot of current nmethod table for iteration
+class ShenandoahNMethodTableSnapshot : public CHeapObj<mtGC> {
+  friend class ShenandoahNMethodTable;
+private:
+  ShenandoahHeap* const       _heap;
+  ShenandoahNMethodTable*     _table;
+  ShenandoahNMethod** const   _array;
+  const int                   _length;
+
+  DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t));
+  volatile size_t       _claimed;
+  DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
+
+public:
+  ShenandoahNMethodTableSnapshot(ShenandoahNMethodTable* table);
+
+  template<bool CSET_FILTER>
+  void parallel_blobs_do(CodeBlobClosure *f);
+
+  void concurrent_nmethods_do(NMethodClosure* cl);
+};
+
+class ShenandoahNMethodTable : public CHeapObj<mtGC> {
+  friend class ShenandoahNMethodTableSnapshot;
+private:
+  enum {
+    minSize = 1024
+  };
+
+  ShenandoahHeap* const _heap;
+  ShenandoahNMethod**   _array;
+  int                   _size;
+  int                   _index;
+  ShenandoahLock        _lock;
+  bool                  _iteration_in_progress;
+
+public:
+  ShenandoahNMethodTable();
+  ~ShenandoahNMethodTable();
+
+  void register_nmethod(nmethod* nm);
+  void unregister_nmethod(nmethod* nm);
+  void flush_nmethod(nmethod* nm);
+
+  bool contain(nmethod* nm) const;
+  int length() const { return _index; }
+
+  // Table iteration support
+  ShenandoahNMethodTableSnapshot* snapshot_for_iteration();
+  void finish_iteration(ShenandoahNMethodTableSnapshot* snapshot);
+
+  void assert_nmethods_alive_and_correct() NOT_DEBUG_RETURN;
+private:
+  // Rebuild table and replace current one
+  void rebuild(int size);
+
+  bool is_full() const {
+    assert(_index <= _size, "Sanity");
+    return _index == _size;
+  }
+
+  ShenandoahNMethod* at(int index) const;
+  int  index_of(nmethod* nm) const;
+  void remove(int index);
+  void append(ShenandoahNMethod* snm);
+
+  inline bool iteration_in_progress() const;
+  void wait_until_concurrent_iteration_done();
+
+  // Logging support
+  void log_register_nmethod(nmethod* nm);
+  void log_unregister_nmethod(nmethod* nm);
+  void log_flush_nmethod(nmethod* nm);
+};
+
+class ShenandoahConcurrentNMethodIterator {
+private:
+  ShenandoahNMethodTable*         const _table;
+  ShenandoahNMethodTableSnapshot*       _table_snapshot;
+
+public:
+  ShenandoahConcurrentNMethodIterator(ShenandoahNMethodTable* table);
+
+  void nmethods_do_begin();
+  void nmethods_do(NMethodClosure* cl);
+  void nmethods_do_end();
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHNMETHOD_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_SHENANDOAH_SHENANDOAHNMETHOD_INLINE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHNMETHOD_INLINE_HPP
+
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetNMethod.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
+#include "gc/shenandoah/shenandoahNMethod.hpp"
+
+nmethod* ShenandoahNMethod::nm() const {
+  return _nm;
+}
+
+ShenandoahReentrantLock* ShenandoahNMethod::lock() {
+  return &_lock;
+}
+
+int ShenandoahNMethod::oop_count() const {
+  return _oops_count + static_cast<int>(nm()->oops_end() - nm()->oops_begin());
+}
+
+bool ShenandoahNMethod::has_oops() const {
+  return oop_count() > 0;
+}
+
+void ShenandoahNMethod::mark_unregistered() {
+  _unregistered = true;
+}
+
+bool ShenandoahNMethod::is_unregistered() const {
+  return _unregistered;
+}
+
+void ShenandoahNMethod::disarm_nmethod(nmethod* nm) {
+ if (!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
+   return;
+ }
+
+ BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
+ assert(bs != NULL, "Sanity");
+ bs->disarm(nm);
+}
+
+ShenandoahNMethod* ShenandoahNMethod::gc_data(nmethod* nm) {
+  return nm->gc_data<ShenandoahNMethod>();
+}
+
+void ShenandoahNMethod::attach_gc_data(nmethod* nm, ShenandoahNMethod* gc_data) {
+  nm->set_gc_data<ShenandoahNMethod>(gc_data);
+}
+
+ShenandoahReentrantLock* ShenandoahNMethod::lock_for_nmethod(nmethod* nm) {
+  return gc_data(nm)->lock();
+}
+
+bool ShenandoahNMethodTable::iteration_in_progress() const {
+  return _iteration_in_progress;
+}
+
+template<bool CSET_FILTER>
+void ShenandoahNMethodTableSnapshot::parallel_blobs_do(CodeBlobClosure *f) {
+  size_t stride = 256; // educated guess
+
+  ShenandoahNMethod** const list = _array;
+
+  size_t max = (size_t)_length;
+  while (_claimed < max) {
+    size_t cur = Atomic::add(&_claimed, stride) - stride;
+    size_t start = cur;
+    size_t end = MIN2(cur + stride, max);
+    if (start >= max) break;
+
+    for (size_t idx = start; idx < end; idx++) {
+      ShenandoahNMethod* nmr = list[idx];
+      assert(nmr != NULL, "Sanity");
+      if (nmr->is_unregistered()) {
+        continue;
+      }
+
+      nmr->assert_alive_and_correct();
+
+      if (CSET_FILTER && !nmr->has_cset_oops(_heap)) {
+        continue;
+      }
+
+      f->do_code_blob(nmr->nm());
+    }
+  }
+}
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHNMETHOD_INLINE_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahNormalMode.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNormalMode.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -21,6 +21,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
 #include "gc/shenandoah/shenandoahNormalMode.hpp"
 #include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp"
 #include "gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp"
@@ -32,6 +33,9 @@
 void ShenandoahNormalMode::initialize_flags() const {
   SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
   SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
+  if (ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
+    SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahSuspendibleWorkers);
+  }
 
   // Final configuration checks
   SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
--- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 #include "gc/shenandoah/shenandoahFreeSet.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 #include "gc/shenandoah/shenandoahPacer.hpp"
+#include "runtime/atomic.hpp"
 
 /*
  * In normal concurrent cycle, we have to pace the application to let GC finish.
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,8 +27,10 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
-#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahHeap.hpp"
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
@@ -159,14 +161,22 @@
   _heap->phase_timings()->record_workers_end(_phase);
 }
 
-ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots) :
+ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers,
+                                                 ShenandoahPhaseTimings::Phase phase,
+                                                 bool include_concurrent_roots,
+                                                 bool include_concurrent_code_roots) :
   ShenandoahRootProcessor(phase),
   _thread_roots(n_workers > 1),
-  _include_concurrent_roots(include_concurrent_roots) {
+  _include_concurrent_roots(include_concurrent_roots),
+  _include_concurrent_code_roots(include_concurrent_code_roots) {
 }
 
 void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
   MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
+  ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(oops);
+  CodeBlobToOopClosure* codes_cl = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
+                                   static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
+                                   static_cast<CodeBlobToOopClosure*>(&blobsCl);
   AlwaysTrueClosure always_true;
 
   _serial_roots.oops_do(oops, worker_id);
@@ -178,8 +188,12 @@
     _weak_roots.oops_do<OopClosure>(oops, worker_id);
   }
 
-  _thread_roots.oops_do(oops, NULL, worker_id);
-  _code_roots.code_blobs_do(&blobsCl, worker_id);
+  if (_include_concurrent_code_roots) {
+    _code_roots.code_blobs_do(codes_cl, worker_id);
+    _thread_roots.oops_do(oops, NULL, worker_id);
+  } else {
+    _thread_roots.oops_do(oops, codes_cl, worker_id);
+  }
 
   _dedup_roots.oops_do(&always_true, oops, worker_id);
 }
@@ -208,7 +222,11 @@
 }
 
 void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
-  CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations);
+  CodeBlobToOopClosure code_blob_cl(oops, CodeBlobToOopClosure::FixRelocations);
+  ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(oops);
+  CodeBlobToOopClosure* adjust_code_closure = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
+                                              static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
+                                              static_cast<CodeBlobToOopClosure*>(&code_blob_cl);
   CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong);
   AlwaysTrueClosure always_true;
 
@@ -217,7 +235,7 @@
 
   _thread_roots.oops_do(oops, NULL, worker_id);
   _cld_roots.cld_do(&adjust_cld_closure, worker_id);
-  _code_roots.code_blobs_do(&adjust_code_closure, worker_id);
+  _code_roots.code_blobs_do(adjust_code_closure, worker_id);
 
   _serial_weak_roots.weak_oops_do(oops, worker_id);
   _weak_roots.oops_do<OopClosure>(oops, worker_id);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -277,11 +277,12 @@
   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
   ShenandoahStringDedupRoots                                _dedup_roots;
-  ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
+  ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator>  _code_roots;
   bool                                                      _include_concurrent_roots;
-
+  bool                                                      _include_concurrent_code_roots;
 public:
-  ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots);
+  ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
+                          bool include_concurrent_roots, bool _include_concurrent_code_roots);
 
   void roots_do(uint worker_id, OopClosure* oops);
 };
@@ -297,7 +298,7 @@
   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
   ShenandoahStringDedupRoots                                _dedup_roots;
-  ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
+  ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator>  _code_roots;
 
 public:
   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,8 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/oopStorageParState.inline.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
 #include "gc/shenandoah/shenandoahHeuristics.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
@@ -265,14 +267,19 @@
 template <typename IsAlive, typename KeepAlive>
 void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) {
   CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations);
+  ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(keep_alive);
+  CodeBlobToOopClosure* codes_cl = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
+                                  static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
+                                  static_cast<CodeBlobToOopClosure*>(&update_blobs);
+
   CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong);
 
   _serial_roots.oops_do(keep_alive, worker_id);
   _vm_roots.oops_do(keep_alive, worker_id);
 
-  _thread_roots.oops_do(keep_alive, NULL, worker_id);
   _cld_roots.cld_do(&clds, worker_id);
   _code_roots.code_blobs_do(&update_blobs, worker_id);
+  _thread_roots.oops_do(keep_alive, NULL, worker_id);
 
   _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
   _weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -43,7 +43,7 @@
 // Check for overflow of number of root types.
 STATIC_ASSERT((static_cast<uint>(ShenandoahRootVerifier::AllRoots) + 1) > static_cast<uint>(ShenandoahRootVerifier::AllRoots));
 
-ShenandoahRootVerifier::ShenandoahRootVerifier() : _types(AllRoots) {
+ShenandoahRootVerifier::ShenandoahRootVerifier(RootTypes types) : _types(types) {
 }
 
 void ShenandoahRootVerifier::excludes(RootTypes types) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,6 +30,7 @@
 class ShenandoahRootVerifier : public StackObj {
 public:
   enum RootTypes {
+    None                = 0,
     SerialRoots         = 1 << 0,
     ThreadRoots         = 1 << 1,
     CodeRoots           = 1 << 2,
@@ -44,7 +45,7 @@
   RootTypes _types;
 
 public:
-  ShenandoahRootVerifier();
+  ShenandoahRootVerifier(RootTypes types = AllRoots);
 
   void excludes(RootTypes types);
   void oops_do(OopClosure* cl);
--- a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,7 @@
 #define SHARE_GC_SHENANDOAH_SHENANDOAHSHAREDVARIABLES_HPP
 
 #include "memory/allocation.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 typedef jbyte ShenandoahSharedValue;
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 #include "gc/shared/owstTaskTerminator.hpp"
 #include "gc/shared/taskqueue.hpp"
 #include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/thread.hpp"
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 
 #include "gc/shared/plab.hpp"
 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
+#include "gc/shenandoah/shenandoahCodeRoots.hpp"
 #include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/debug.hpp"
@@ -43,6 +44,7 @@
   size_t _gclab_size;
   uint  _worker_id;
   bool _force_satb_flush;
+  int  _disarmed_value;
 
   ShenandoahThreadLocalData() :
     _gc_state(0),
@@ -125,6 +127,7 @@
     assert(data(thread)->_gclab == NULL, "Only initialize once");
     data(thread)->_gclab = new PLAB(PLAB::min_size());
     data(thread)->_gclab_size = 0;
+    data(thread)->_disarmed_value = ShenandoahCodeRoots::disarmed_value();
   }
 
   static PLAB* gclab(Thread* thread) {
@@ -139,6 +142,10 @@
     data(thread)->_gclab_size = v;
   }
 
+  static void set_disarmed_value(Thread* thread, int value) {
+    data(thread)->_disarmed_value = value;
+  }
+
 #ifdef ASSERT
   static void set_evac_allowed(Thread* thread, bool evac_allowed) {
     if (evac_allowed) {
@@ -170,6 +177,9 @@
     return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _gc_state);
   }
 
+  static ByteSize disarmed_value_offset() {
+    return Thread::gc_data_offset() + byte_offset_of(ShenandoahThreadLocalData, _disarmed_value);
+  }
 };
 
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "classfile/classLoaderDataGraph.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "code/codeBehaviours.hpp"
+#include "code/codeCache.hpp"
+#include "code/dependencyContext.hpp"
+#include "gc/shared/gcBehaviours.hpp"
+#include "gc/shared/suspendibleThreadSet.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
+#include "gc/shenandoah/shenandoahCodeRoots.hpp"
+#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
+#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
+#include "gc/shenandoah/shenandoahLock.hpp"
+#include "gc/shenandoah/shenandoahRootProcessor.hpp"
+#include "gc/shenandoah/shenandoahUnload.hpp"
+#include "gc/shenandoah/shenandoahVerifier.hpp"
+#include "memory/iterator.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/access.inline.hpp"
+
+class ShenandoahIsUnloadingOopClosure : public OopClosure {
+private:
+  ShenandoahMarkingContext*    _marking_context;
+  bool                         _is_unloading;
+
+public:
+  ShenandoahIsUnloadingOopClosure() :
+    _marking_context(ShenandoahHeap::heap()->marking_context()),
+    _is_unloading(false) {
+  }
+
+  virtual void do_oop(oop* p) {
+    if (_is_unloading) {
+      return;
+    }
+
+    const oop o = RawAccess<>::oop_load(p);
+    if (!CompressedOops::is_null(o) &&
+        _marking_context->is_complete() &&
+        !_marking_context->is_marked(o)) {
+      _is_unloading = true;
+    }
+  }
+
+  virtual void do_oop(narrowOop* p) {
+    ShouldNotReachHere();
+  }
+
+  bool is_unloading() const {
+    return _is_unloading;
+  }
+};
+
+class ShenandoahIsUnloadingBehaviour : public IsUnloadingBehaviour {
+public:
+  virtual bool is_unloading(CompiledMethod* method) const {
+    nmethod* const nm = method->as_nmethod();
+    guarantee(ShenandoahHeap::heap()->is_evacuation_in_progress(), "Only this phase");
+    ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
+    ShenandoahReentrantLocker locker(data->lock());
+    ShenandoahIsUnloadingOopClosure cl;
+    data->oops_do(&cl);
+    return  cl.is_unloading();
+  }
+};
+
+class ShenandoahCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour {
+public:
+  virtual bool lock(CompiledMethod* method) {
+    nmethod* const nm = method->as_nmethod();
+    ShenandoahReentrantLock* const lock = ShenandoahNMethod::lock_for_nmethod(nm);
+    assert(lock != NULL, "Not yet registered?");
+    lock->lock();
+    return true;
+  }
+
+  virtual void unlock(CompiledMethod* method) {
+    nmethod* const nm = method->as_nmethod();
+    ShenandoahReentrantLock* const lock = ShenandoahNMethod::lock_for_nmethod(nm);
+    assert(lock != NULL, "Not yet registered?");
+    lock->unlock();
+  }
+
+  virtual bool is_safe(CompiledMethod* method) {
+    if (SafepointSynchronize::is_at_safepoint()) {
+      return true;
+    }
+
+    nmethod* const nm = method->as_nmethod();
+    ShenandoahReentrantLock* const lock = ShenandoahNMethod::lock_for_nmethod(nm);
+    assert(lock != NULL, "Not yet registered?");
+    return lock->owned_by_self();
+  }
+};
+
+ShenandoahUnload::ShenandoahUnload() {
+  if (ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
+    static ShenandoahIsUnloadingBehaviour is_unloading_behaviour;
+    IsUnloadingBehaviour::set_current(&is_unloading_behaviour);
+
+    static ShenandoahCompiledICProtectionBehaviour ic_protection_behaviour;
+    CompiledICProtectionBehaviour::set_current(&ic_protection_behaviour);
+  }
+}
+
+void ShenandoahUnload::prepare() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
+  assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(), "Sanity");
+  CodeCache::increment_unloading_cycle();
+  DependencyContext::cleaning_start();
+}
+
+void ShenandoahUnload::unlink() {
+  SuspendibleThreadSetJoiner sts;
+  bool unloading_occurred;
+  ShenandoahHeap* const heap = ShenandoahHeap::heap();
+  {
+    MutexLocker cldg_ml(ClassLoaderDataGraph_lock);
+    unloading_occurred = SystemDictionary::do_unloading(heap->gc_timer());
+  }
+
+  Klass::clean_weak_klass_links(unloading_occurred);
+  ShenandoahCodeRoots::unlink(ShenandoahHeap::heap()->workers(), unloading_occurred);
+  DependencyContext::cleaning_end();
+}
+
+void ShenandoahUnload::purge() {
+  {
+    SuspendibleThreadSetJoiner sts;
+    ShenandoahCodeRoots::purge(ShenandoahHeap::heap()->workers());
+  }
+
+  ClassLoaderDataGraph::purge();
+  CodeCache::purge_exception_caches();
+}
+
+class ShenandoahUnloadRendezvousClosure : public ThreadClosure {
+public:
+  void do_thread(Thread* thread) {}
+};
+
+void ShenandoahUnload::unload() {
+  assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(), "Why we here?");
+  if (!ShenandoahHeap::heap()->is_evacuation_in_progress()) {
+    return;
+  }
+
+  // Unlink stale metadata and nmethods
+  unlink();
+
+  // Make sure stale metadata and nmethods are no longer observable
+  ShenandoahUnloadRendezvousClosure cl;
+  Handshake::execute(&cl);
+
+  // Purge stale metadata and nmethods that were unlinked
+  purge();
+}
+
+void ShenandoahUnload::finish() {
+  MetaspaceGC::compute_new_size();
+  MetaspaceUtils::verify_metrics();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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_SHENANDOAH_SHENANDOAHCLASSUNLOAD_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHCLASSUNLOAD_HPP
+
+#include "memory/allocation.hpp"
+
+class ShenandoahHeap;
+
+class ShenandoahUnload {
+public:
+  ShenandoahUnload();
+  void prepare();
+  void unload();
+  void finish();
+private:
+  void unlink();
+  void purge();
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLASSUNLOAD_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,8 @@
 #include "memory/iterator.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
 
 // Avoid name collision on verify_oop (defined in macroAssembler_arm.hpp)
@@ -1007,6 +1009,13 @@
   verifier.oops_do(&cl);
 }
 
+void ShenandoahVerifier::verify_roots_in_to_space_except(ShenandoahRootVerifier::RootTypes types) {
+  ShenandoahRootVerifier verifier;
+  verifier.excludes(types);
+  ShenandoahVerifyInToSpaceClosure cl;
+  verifier.oops_do(&cl);
+}
+
 void ShenandoahVerifier::verify_roots_no_forwarded() {
   ShenandoahRootVerifier verifier;
   ShenandoahVerifyNoForwared cl;
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -190,6 +190,8 @@
 
   // Roots should only contain to-space oops
   void verify_roots_in_to_space();
+  void verify_roots_in_to_space_except(ShenandoahRootVerifier::RootTypes types);
+
   void verify_roots_no_forwarded();
   void verify_roots_no_forwarded_except(ShenandoahRootVerifier::RootTypes types);
 };
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -86,7 +86,7 @@
           "References get processed at every Nth GC cycle. Set to zero "    \
           "to disable reference processing.")                               \
                                                                             \
-  experimental(uintx, ShenandoahUnloadClassesFrequency, 5,                  \
+  experimental(uintx, ShenandoahUnloadClassesFrequency, 1,                  \
           "How often should classes get unloaded. "                         \
           "Class unloading is performed at every Nth GC cycle. "            \
           "Set to zero to disable class unloading during concurrent GC.")   \
--- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -61,12 +61,10 @@
   return true;
 }
 
-int ZBarrierSetNMethod::disarmed_value() const {
-  // We override the default BarrierSetNMethod::disarmed_value() since
-  // this can be called by GC threads, which doesn't keep an up to date
-  // address_bad_mask.
-  const uintptr_t disarmed_addr = ((uintptr_t)&ZAddressBadMask) + ZNMethodDisarmedOffset;
-  return *((int*)disarmed_addr);
+int* ZBarrierSetNMethod::disarmed_value_address() const {
+  const uintptr_t mask_addr = reinterpret_cast<uintptr_t>(&ZAddressBadMask);
+  const uintptr_t disarmed_addr = mask_addr + ZNMethodDisarmedOffset;
+  return reinterpret_cast<int*>(disarmed_addr);
 }
 
 ByteSize ZBarrierSetNMethod::thread_disarmed_offset() const {
--- a/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -31,11 +31,11 @@
 
 class ZBarrierSetNMethod : public BarrierSetNMethod {
 protected:
-  virtual int disarmed_value() const;
   virtual bool nmethod_entry_barrier(nmethod* nm);
 
 public:
   virtual ByteSize thread_disarmed_offset() const;
+  virtual int* disarmed_value_address() const;
 };
 
 #endif // SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP
--- a/src/hotspot/share/gc/z/zLiveMap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zLiveMap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,7 +28,6 @@
 #include "gc/z/zThread.inline.hpp"
 #include "logging/log.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/debug.hpp"
 
 static const ZStatCounter ZCounterMarkSeqNumResetContention("Contention", "Mark SeqNum Reset Contention", ZStatUnitOpsPerSecond);
--- a/src/hotspot/share/gc/z/zLiveMap.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zLiveMap.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,7 +30,6 @@
 #include "gc/z/zOop.inline.hpp"
 #include "gc/z/zUtils.inline.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/bitMap.inline.hpp"
 #include "utilities/debug.hpp"
 
--- a/src/hotspot/share/gc/z/zMark.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zMark.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -44,7 +44,6 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handshake.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/align.hpp"
--- a/src/hotspot/share/gc/z/zMarkTerminate.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zMarkTerminate.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,6 @@
 #define SHARE_GC_Z_ZMARKTERMINATE_INLINE_HPP
 
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 
 inline ZMarkTerminate::ZMarkTerminate() :
     _nworkers(0),
--- a/src/hotspot/share/gc/z/zNMethod.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethod.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -41,7 +41,6 @@
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/debug.hpp"
 
 static ZNMethodData* gc_data(const nmethod* nm) {
--- a/src/hotspot/share/gc/z/zNMethodData.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodData.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,6 @@
 #include "gc/z/zNMethodData.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/growableArray.hpp"
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -42,8 +42,6 @@
 #include "memory/allocation.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/debug.hpp"
 
 ZNMethodTableEntry* ZNMethodTable::_table = NULL;
--- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,6 +34,7 @@
 #include "gc/z/zUtils.inline.hpp"
 #include "gc/z/zValue.inline.hpp"
 #include "memory/universe.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
 
--- a/src/hotspot/share/interpreter/oopMapCache.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/interpreter/oopMapCache.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,6 +29,7 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/signature.hpp"
 
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -46,7 +46,6 @@
 #include "jfr/utilities/jfrTypes.hpp"
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/orderAccess.hpp"
--- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -39,7 +39,6 @@
 #include "jfr/writers/jfrNativeEventWriter.hpp"
 #include "logging/log.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
--- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,8 +33,8 @@
 #include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp"
 #include "jfr/utilities/jfrTypes.hpp"
 #include "logging/log.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
 
--- a/src/hotspot/share/jfr/utilities/jfrHashtable.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jfr/utilities/jfrHashtable.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
 #define SHARE_JFR_UTILITIES_JFRHASHTABLE_HPP
 
 #include "jfr/utilities/jfrAllocation.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/macros.hpp"
 
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
 #define SHARE_JVMCI_JVMCICOMPILER_HPP
 
 #include "compiler/abstractCompiler.hpp"
+#include "runtime/atomic.hpp"
 
 class JVMCICompiler : public AbstractCompiler {
 private:
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -42,6 +42,7 @@
 #include "oops/method.inline.hpp"
 #include "oops/typeArrayOop.inline.hpp"
 #include "prims/nativeLookup.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/frame.inline.hpp"
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,6 +34,7 @@
 #include "oops/method.inline.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
--- a/src/hotspot/share/jvmci/metadataHandleBlock.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/jvmci/metadataHandleBlock.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,6 +23,7 @@
 
 #include "precompiled.hpp"
 #include "jvmci/metadataHandleBlock.hpp"
+#include "runtime/atomic.hpp"
 
 MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
 intptr_t             MetadataHandleBlock::_free_list = 0;
--- a/src/hotspot/share/logging/logDecorations.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/logging/logDecorations.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,6 @@
 #include "logging/logConfiguration.hpp"
 #include "logging/logDecorations.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/management.hpp"
--- a/src/hotspot/share/memory/allocation.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/allocation.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -28,7 +28,6 @@
 #include "memory/arena.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "runtime/task.hpp"
 #include "runtime/threadCritical.hpp"
--- a/src/hotspot/share/memory/arena.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/arena.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,6 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "runtime/task.hpp"
 #include "runtime/threadCritical.hpp"
@@ -325,7 +324,7 @@
 // change the size
 void Arena::set_size_in_bytes(size_t size) {
   if (_size_in_bytes != size) {
-    long delta = (long)(size - size_in_bytes());
+    ssize_t delta = size - size_in_bytes();
     _size_in_bytes = size;
     MemTracker::record_arena_size_change(delta, _flags);
   }
--- a/src/hotspot/share/memory/filemap.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/filemap.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1385,14 +1385,6 @@
 
   }
 
-  DEBUG_ONLY(if (addr_delta == 0 && ArchiveRelocationMode == 1) {
-      // This is for simulating mmap failures at the requested address. We do it here (instead
-      // of MetaspaceShared::map_archives) so we can thoroughly test the code for failure handling
-      // (releasing all allocated resource, etc).
-      log_info(cds)("ArchiveRelocationMode == 1: always map archive(s) at an alternative address");
-      return MAP_ARCHIVE_MMAP_FAILURE;
-    });
-
   header()->set_mapped_base_address(header()->requested_base_address() + addr_delta);
   if (addr_delta != 0 && !relocate_pointers(addr_delta)) {
     return MAP_ARCHIVE_OTHER_FAILURE;
@@ -1446,12 +1438,14 @@
     MemTracker::record_virtual_memory_type((address)requested_addr, mtClassShared);
   }
 
-  if (MetaspaceShared::use_windows_memory_mapping() && addr_delta != 0) {
+  if (MetaspaceShared::use_windows_memory_mapping() && rs.is_reserved()) {
     // This is the second time we try to map the archive(s). We have already created a ReservedSpace
     // that covers all the FileMapRegions to ensure all regions can be mapped. However, Windows
     // can't mmap into a ReservedSpace, so we just os::read() the data. We're going to patch all the
     // regions anyway, so there's no benefit for mmap anyway.
     if (!read_region(i, requested_addr, size)) {
+      log_info(cds)("Failed to read %s shared space into reserved space at " INTPTR_FORMAT,
+                    shared_region_name[i], p2i(requested_addr));
       return MAP_ARCHIVE_OTHER_FAILURE; // oom or I/O error.
     }
   } else {
@@ -1459,7 +1453,8 @@
                                 requested_addr, size, si->read_only(),
                                 si->allow_exec());
     if (base != requested_addr) {
-      log_info(cds)("Unable to map %s shared space at required address.", shared_region_name[i]);
+      log_info(cds)("Unable to map %s shared space at " INTPTR_FORMAT,
+                    shared_region_name[i], p2i(requested_addr));
       _memory_mapping_failed = true;
       return MAP_ARCHIVE_MMAP_FAILURE;
     }
@@ -1468,7 +1463,7 @@
   si->set_mapped_base(requested_addr);
 
   if (!rs.is_reserved()) {
-    // When mapping on Windows with (addr_delta == 0), we don't reserve the address space for the regions
+    // When mapping on Windows for the first attempt, we don't reserve the address space for the regions
     // (Windows can't mmap into a ReservedSpace). In this case, NMT requires we call it after
     // os::map_memory has succeeded.
     assert(MetaspaceShared::use_windows_memory_mapping(), "Windows memory mapping only");
--- a/src/hotspot/share/memory/metaspace.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/metaspace.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -40,8 +40,8 @@
 #include "memory/metaspaceTracer.hpp"
 #include "memory/universe.hpp"
 #include "oops/compressedOops.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/init.hpp"
-#include "runtime/orderAccess.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/debug.hpp"
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,7 @@
 #include "memory/metaspace/metaspaceCommon.hpp"
 #include "memory/metaspace/virtualSpaceList.hpp"
 #include "memory/metaspace/virtualSpaceNode.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
@@ -444,4 +445,3 @@
 #endif // ASSERT
 
 } // namespace metaspace
-
--- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -34,6 +34,7 @@
 #include "memory/metaspace/occupancyMap.hpp"
 #include "memory/metaspace/virtualSpaceNode.hpp"
 #include "memory/virtualspace.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/copy.hpp"
@@ -585,4 +586,3 @@
 }
 
 } // namespace metaspace
-
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -2147,6 +2147,19 @@
     MapArchiveResult dynamic_result = (static_result == MAP_ARCHIVE_SUCCESS) ?
                                      map_archive(dynamic_mapinfo, mapped_base_address, archive_space_rs) : MAP_ARCHIVE_OTHER_FAILURE;
 
+    DEBUG_ONLY(if (ArchiveRelocationMode == 1 && use_requested_addr) {
+      // This is for simulating mmap failures at the requested address. In debug builds, we do it
+      // here (after all archives have possibly been mapped), so we can thoroughly test the code for
+      // failure handling (releasing all allocated resource, etc).
+      log_info(cds)("ArchiveRelocationMode == 1: always map archive(s) at an alternative address");
+      if (static_result == MAP_ARCHIVE_SUCCESS) {
+        static_result = MAP_ARCHIVE_MMAP_FAILURE;
+      }
+      if (dynamic_result == MAP_ARCHIVE_SUCCESS) {
+        dynamic_result = MAP_ARCHIVE_MMAP_FAILURE;
+      }
+    });
+
     if (static_result == MAP_ARCHIVE_SUCCESS) {
       if (dynamic_result == MAP_ARCHIVE_SUCCESS) {
         result = MAP_ARCHIVE_SUCCESS;
@@ -2298,7 +2311,7 @@
 MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped_base_address, ReservedSpace rs) {
   assert(UseSharedSpaces, "must be runtime");
   if (mapinfo == NULL) {
-    return MAP_ARCHIVE_SUCCESS; // no error has happeed -- trivially succeeded.
+    return MAP_ARCHIVE_SUCCESS; // The dynamic archive has not been specified. No error has happened -- trivially succeeded.
   }
 
   mapinfo->set_is_mapped(false);
--- a/src/hotspot/share/memory/resourceArea.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/memory/resourceArea.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -31,8 +31,11 @@
 
 void ResourceArea::bias_to(MEMFLAGS new_flags) {
   if (new_flags != _flags) {
+    size_t size = size_in_bytes();
+    MemTracker::record_arena_size_change(-ssize_t(size), _flags);
     MemTracker::record_arena_free(_flags);
     MemTracker::record_new_arena(new_flags);
+    MemTracker::record_arena_size_change(ssize_t(size), new_flags);
     _flags = new_flags;
   }
 }
--- a/src/hotspot/share/oops/accessBackend.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/accessBackend.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,6 +29,8 @@
 #include "oops/accessBackend.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oopsHierarchy.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 
 template <DecoratorSet decorators>
 template <DecoratorSet idecorators, typename T>
--- a/src/hotspot/share/oops/arrayKlass.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/arrayKlass.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,7 @@
 #ifndef SHARE_OOPS_ARRAYKLASS_INLINE_HPP
 #define SHARE_OOPS_ARRAYKLASS_INLINE_HPP
 
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "oops/arrayKlass.hpp"
 
 inline Klass* ArrayKlass::higher_dimension_acquire() const {
--- a/src/hotspot/share/oops/constantPool.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/constantPool.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -49,6 +49,7 @@
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayOop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/fieldType.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
--- a/src/hotspot/share/oops/constantPool.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/constantPool.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,7 @@
 
 #include "oops/constantPool.hpp"
 #include "oops/cpCache.inline.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 inline CPSlot ConstantPool::slot_at(int which) const {
   assert(is_within_bounds(which), "index out of bounds");
--- a/src/hotspot/share/oops/cpCache.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/cpCache.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -44,7 +44,6 @@
 #include "prims/methodHandles.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/macros.hpp"
 
 // Implementation of ConstantPoolCacheEntry
--- a/src/hotspot/share/oops/cpCache.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/cpCache.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,7 @@
 
 #include "oops/cpCache.hpp"
 #include "oops/oopHandle.inline.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 inline int ConstantPoolCacheEntry::indices_ord() const { return Atomic::load_acquire(&_indices); }
 
--- a/src/hotspot/share/oops/instanceKlass.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -29,7 +29,7 @@
 #include "oops/instanceKlass.hpp"
 #include "oops/klass.hpp"
 #include "oops/oop.inline.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
--- a/src/hotspot/share/oops/klass.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/klass.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -47,7 +47,6 @@
 #include "oops/oopHandle.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
 
--- a/src/hotspot/share/oops/method.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/method.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -58,6 +58,7 @@
 #include "prims/methodHandles.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
--- a/src/hotspot/share/oops/method.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/method.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
 #define SHARE_OOPS_METHOD_INLINE_HPP
 
 #include "oops/method.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 inline address Method::from_compiled_entry() const {
   return Atomic::load_acquire(&_from_compiled_entry);
--- a/src/hotspot/share/oops/methodData.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/methodData.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
 #include "oops/methodData.inline.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/orderAccess.hpp"
--- a/src/hotspot/share/oops/methodData.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/methodData.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
 #define SHARE_OOPS_METHODDATA_INLINE_HPP
 
 #include "oops/methodData.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 
 inline void DataLayout::release_set_cell_at(int index, intptr_t value) {
   Atomic::release_store(&_cells[index], value);
--- a/src/hotspot/share/oops/oop.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/oops/oop.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,7 +35,6 @@
 #include "oops/markWord.inline.hpp"
 #include "oops/oop.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
--- a/src/hotspot/share/opto/cfgnode.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/opto/cfgnode.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -308,6 +308,8 @@
   Node* Ideal_common(PhaseGVN *phase, bool can_reshape);
   Node* search_identical(int dist);
 
+  Node* simple_subsuming(PhaseIterGVN* igvn);
+
 public:
 
   // Degrees of branch prediction probability by order of magnitude:
--- a/src/hotspot/share/opto/ifnode.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/opto/ifnode.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -599,7 +599,7 @@
 
 //------------------------------filtered_int_type--------------------------------
 // Return a possibly more restrictive type for val based on condition control flow for an if
-const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj) {
+const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node* val, Node* if_proj) {
   assert(if_proj &&
          (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection");
   if (if_proj->in(0) && if_proj->in(0)->is_If()) {
@@ -1239,8 +1239,7 @@
 
   if (cmpi_folds(igvn)) {
     Node* ctrl = in(0);
-    if (is_ctrl_folds(ctrl, igvn) &&
-        ctrl->outcnt() == 1) {
+    if (is_ctrl_folds(ctrl, igvn) && ctrl->outcnt() == 1) {
       // A integer comparison immediately dominated by another integer
       // comparison
       ProjNode* success = NULL;
@@ -1392,41 +1391,36 @@
   // Check for people making a useless boolean: things like
   // if( (x < y ? true : false) ) { ... }
   // Replace with if( x < y ) { ... }
-  Node *bol2 = remove_useless_bool(this, phase);
-  if( bol2 ) return bol2;
+  Node* bol2 = remove_useless_bool(this, phase);
+  if (bol2) return bol2;
 
   if (in(0) == NULL) return NULL;     // Dead loop?
 
-  PhaseIterGVN *igvn = phase->is_IterGVN();
+  PhaseIterGVN* igvn = phase->is_IterGVN();
   Node* result = fold_compares(igvn);
   if (result != NULL) {
     return result;
   }
 
   // Scan for an equivalent test
-  Node *cmp;
-  int dist = 0;               // Cutoff limit for search
-  int op = Opcode();
-  if( op == Op_If &&
-      (cmp=in(1)->in(1))->Opcode() == Op_CmpP ) {
-    if( cmp->in(2) != NULL && // make sure cmp is not already dead
-        cmp->in(2)->bottom_type() == TypePtr::NULL_PTR ) {
+  int dist = 4;               // Cutoff limit for search
+  if (is_If() && in(1)->is_Bool()) {
+    Node* cmp = in(1)->in(1);
+    if (cmp->Opcode() == Op_CmpP &&
+        cmp->in(2) != NULL && // make sure cmp is not already dead
+        cmp->in(2)->bottom_type() == TypePtr::NULL_PTR) {
       dist = 64;              // Limit for null-pointer scans
-    } else {
-      dist = 4;               // Do not bother for random pointer tests
     }
-  } else {
-    dist = 4;                 // Limit for random junky scans
   }
 
   Node* prev_dom = search_identical(dist);
 
-  if (prev_dom == NULL) {
-    return NULL;
+  if (prev_dom != NULL) {
+    // Replace dominated IfNode
+    return dominated_by(prev_dom, igvn);
   }
 
-  // Replace dominated IfNode
-  return dominated_by(prev_dom, igvn);
+  return simple_subsuming(igvn);
 }
 
 //------------------------------dominated_by-----------------------------------
@@ -1523,6 +1517,114 @@
   return prev_dom;
 }
 
+
+static int subsuming_bool_test_encode(Node*);
+
+// Check if dominating test is subsuming 'this' one.
+//
+//              cmp
+//              / \
+//     (r1)  bool  \
+//            /    bool (r2)
+//    (dom) if       \
+//            \       )
+//    (pre)  if[TF]  /
+//               \  /
+//                if (this)
+//   \r1
+//  r2\  eqT  eqF  neT  neF  ltT  ltF  leT  leF  gtT  gtF  geT  geF
+//  eq    t    f    f    t    f    -    -    f    f    -    -    f
+//  ne    f    t    t    f    t    -    -    t    t    -    -    t
+//  lt    f    -    -    f    t    f    -    f    f    -    f    t
+//  le    t    -    -    t    t    -    t    f    f    t    -    t
+//  gt    f    -    -    f    f    -    f    t    t    f    -    f
+//  ge    t    -    -    t    f    t    -    t    t    -    t    f
+//
+Node* IfNode::simple_subsuming(PhaseIterGVN* igvn) {
+  // Table encoding: N/A (na), True-branch (tb), False-branch (fb).
+  static enum { na, tb, fb } s_short_circuit_map[6][12] = {
+  /*rel: eq+T eq+F ne+T ne+F lt+T lt+F le+T le+F gt+T gt+F ge+T ge+F*/
+  /*eq*/{ tb,  fb,  fb,  tb,  fb,  na,  na,  fb,  fb,  na,  na,  fb },
+  /*ne*/{ fb,  tb,  tb,  fb,  tb,  na,  na,  tb,  tb,  na,  na,  tb },
+  /*lt*/{ fb,  na,  na,  fb,  tb,  fb,  na,  fb,  fb,  na,  fb,  tb },
+  /*le*/{ tb,  na,  na,  tb,  tb,  na,  tb,  fb,  fb,  tb,  na,  tb },
+  /*gt*/{ fb,  na,  na,  fb,  fb,  na,  fb,  tb,  tb,  fb,  na,  fb },
+  /*ge*/{ tb,  na,  na,  tb,  fb,  tb,  na,  tb,  tb,  na,  tb,  fb }};
+
+  Node* pre = in(0);
+  if (!pre->is_IfTrue() && !pre->is_IfFalse()) {
+    return NULL;
+  }
+  Node* dom = pre->in(0);
+  if (!dom->is_If()) {
+    return NULL;
+  }
+  Node* bol = in(1);
+  if (!bol->is_Bool()) {
+    return NULL;
+  }
+  Node* cmp = in(1)->in(1);
+  if (!cmp->is_Cmp()) {
+    return NULL;
+  }
+
+  if (!dom->in(1)->is_Bool()) {
+    return NULL;
+  }
+  if (dom->in(1)->in(1) != cmp) {  // Not same cond?
+    return NULL;
+  }
+
+  int drel = subsuming_bool_test_encode(dom->in(1));
+  int trel = subsuming_bool_test_encode(bol);
+  int bout = pre->is_IfFalse() ? 1 : 0;
+
+  if (drel < 0 || trel < 0) {
+    return NULL;
+  }
+  int br = s_short_circuit_map[trel][2*drel+bout];
+  if (br == na) {
+    return NULL;
+  }
+#ifndef PRODUCT
+  if (TraceIterativeGVN) {
+    tty->print("   Subsumed IfNode: "); dump();
+  }
+#endif
+  // Replace condition with constant True(1)/False(0).
+  set_req(1, igvn->intcon(br == tb ? 1 : 0));
+
+  if (bol->outcnt() == 0) {
+    igvn->remove_dead_node(bol);    // Kill the BoolNode.
+  }
+  return this;
+}
+
+// Map BoolTest to local table ecoding. The BoolTest (e)numerals
+//   { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1 }
+// are mapped to table indices, while the remaining (e)numerals in BoolTest
+//   { overflow = 2, no_overflow = 6, never = 8, illegal = 9 }
+// are ignored (these are not modelled in the table).
+//
+static int subsuming_bool_test_encode(Node* node) {
+  precond(node->is_Bool());
+  BoolTest::mask x = node->as_Bool()->_test._test;
+  switch (x) {
+    case BoolTest::eq: return 0;
+    case BoolTest::ne: return 1;
+    case BoolTest::lt: return 2;
+    case BoolTest::le: return 3;
+    case BoolTest::gt: return 4;
+    case BoolTest::ge: return 5;
+    case BoolTest::overflow:
+    case BoolTest::no_overflow:
+    case BoolTest::never:
+    case BoolTest::illegal:
+    default:
+      return -1;
+  }
+}
+
 //------------------------------Identity---------------------------------------
 // If the test is constant & we match, then we are the input Control
 Node* IfProjNode::Identity(PhaseGVN* phase) {
@@ -1668,7 +1770,7 @@
     // checks.
 
     // The top 3 range checks seen
-    const int NRC =3;
+    const int NRC = 3;
     RangeCheck prev_checks[NRC];
     int nb_checks = 0;
 
--- a/src/hotspot/share/opto/parse3.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/opto/parse3.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -55,8 +55,9 @@
     return;
   }
 
-  // Deoptimize on putfield writes to call site target field.
-  if (!is_get && field->is_call_site_target()) {
+  // Deoptimize on putfield writes to call site target field outside of CallSite ctor.
+  if (!is_get && field->is_call_site_target() &&
+      !(method()->holder() == field_holder && method()->is_object_initializer())) {
     uncommon_trap(Deoptimization::Reason_unhandled,
                   Deoptimization::Action_reinterpret,
                   NULL, "put to call site target field");
--- a/src/hotspot/share/prims/jni.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/jni.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -72,7 +72,6 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/jfieldIDWorkaround.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/sharedRuntime.hpp"
--- a/src/hotspot/share/prims/jvm.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/jvm.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -70,7 +70,6 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/jfieldIDWorkaround.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/perfData.hpp"
 #include "runtime/reflection.hpp"
--- a/src/hotspot/share/prims/jvmtiEnvBase.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -30,9 +30,9 @@
 #include "prims/jvmtiEventController.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "oops/oopHandle.hpp"
+#include "runtime/atomic.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"
--- a/src/hotspot/share/prims/jvmtiImpl.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -38,7 +38,6 @@
 #include "prims/jvmtiEventController.inline.hpp"
 #include "prims/jvmtiImpl.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
 #include "oops/oop.inline.hpp"
 #include "oops/weakHandle.inline.hpp"
 #include "prims/resolvedMethodTable.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/mutexLocker.hpp"
--- a/src/hotspot/share/prims/unsafe.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/unsafe.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,7 +37,6 @@
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayOop.inline.hpp"
 #include "prims/unsafe.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
--- a/src/hotspot/share/prims/whitebox.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/prims/whitebox.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -59,6 +59,7 @@
 #include "prims/wbtestmethods/parserTests.hpp"
 #include "prims/whitebox.inline.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/flags/jvmFlag.hpp"
@@ -797,6 +798,21 @@
   assert(hash_size > 0, "NMT hash_size should be > 0");
   return (jint)hash_size;
 WB_END
+
+WB_ENTRY(jlong, WB_NMTNewArena(JNIEnv* env, jobject o, jlong init_size))
+  Arena* arena =  new (mtTest) Arena(mtTest, size_t(init_size));
+  return (jlong)arena;
+WB_END
+
+WB_ENTRY(void, WB_NMTFreeArena(JNIEnv* env, jobject o, jlong arena))
+  Arena* a = (Arena*)arena;
+  delete a;
+WB_END
+
+WB_ENTRY(void, WB_NMTArenaMalloc(JNIEnv* env, jobject o, jlong arena, jlong size))
+  Arena* a = (Arena*)arena;
+  a->Amalloc(size_t(size));
+WB_END
 #endif // INCLUDE_NMT
 
 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
@@ -2244,6 +2260,9 @@
   {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
   {CC"NMTChangeTrackingLevel", CC"()Z",               (void*)&WB_NMTChangeTrackingLevel},
   {CC"NMTGetHashSize",      CC"()I",                  (void*)&WB_NMTGetHashSize     },
+  {CC"NMTNewArena",         CC"(J)J",                 (void*)&WB_NMTNewArena        },
+  {CC"NMTFreeArena",        CC"(J)V",                 (void*)&WB_NMTFreeArena       },
+  {CC"NMTArenaMalloc",      CC"(JJ)V",                (void*)&WB_NMTArenaMalloc     },
 #endif // INCLUDE_NMT
   {CC"deoptimizeFrames",   CC"(Z)I",                  (void*)&WB_DeoptimizeFrames  },
   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
--- a/src/hotspot/share/runtime/arguments.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -528,6 +528,7 @@
   { "CompactFields",                JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) },
   { "MonitorBound",                 JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) },
   { "G1RSetScanBlockSize",          JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) },
+  { "UseParallelOldGC",             JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) },
 
   // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
   { "DefaultMaxRAMFraction",        JDK_Version::jdk(8),  JDK_Version::undefined(), JDK_Version::undefined() },
--- a/src/hotspot/share/runtime/deoptimization.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -1,3 +1,5 @@
+
+
 /*
  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -48,6 +50,7 @@
 #include "oops/typeArrayOop.inline.hpp"
 #include "oops/verifyOopClosure.hpp"
 #include "prims/jvmtiThreadState.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.hpp"
--- a/src/hotspot/share/runtime/handshake.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/handshake.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,9 +26,9 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/resourceArea.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handshake.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/semaphore.inline.hpp"
 #include "runtime/task.hpp"
@@ -289,20 +289,24 @@
 void HandshakeState::process_self_inner(JavaThread* thread) {
   assert(Thread::current() == thread, "should call from thread");
   assert(!thread->is_terminated(), "should not be a terminated thread");
+  assert(thread->thread_state() != _thread_blocked, "should not be in a blocked state");
+  assert(thread->thread_state() != _thread_in_native, "should not be in native");
 
-  ThreadInVMForHandshake tivm(thread);
-  if (!_semaphore.trywait()) {
-    _semaphore.wait_with_safepoint_check(thread);
-  }
-  HandshakeOperation* op = Atomic::load_acquire(&_operation);
-  if (op != NULL) {
-    HandleMark hm(thread);
-    CautiouslyPreserveExceptionMark pem(thread);
-    // Disarm before execute the operation
-    clear_handshake(thread);
-    op->do_handshake(thread);
-  }
-  _semaphore.signal();
+  do {
+    ThreadInVMForHandshake tivm(thread);
+    if (!_semaphore.trywait()) {
+      _semaphore.wait_with_safepoint_check(thread);
+    }
+    HandshakeOperation* op = Atomic::load_acquire(&_operation);
+    if (op != NULL) {
+      HandleMark hm(thread);
+      CautiouslyPreserveExceptionMark pem(thread);
+      // Disarm before execute the operation
+      clear_handshake(thread);
+      op->do_handshake(thread);
+    }
+    _semaphore.signal();
+  } while (has_operation());
 }
 
 bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) {
--- a/src/hotspot/share/runtime/init.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/init.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,11 +35,11 @@
 #include "logging/logTag.hpp"
 #include "memory/universe.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/flags/jvmFlag.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/icache.hpp"
 #include "runtime/init.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "services/memTracker.hpp"
--- a/src/hotspot/share/runtime/interfaceSupport.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/interfaceSupport.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -33,7 +33,6 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/safepointVerifiers.hpp"
--- a/src/hotspot/share/runtime/perfMemory.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/perfMemory.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,10 +27,10 @@
 #include "logging/log.hpp"
 #include "memory/allocation.inline.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/java.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
 #include "runtime/perfMemory.hpp"
--- a/src/hotspot/share/runtime/safepointMechanism.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/safepointMechanism.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "logging/log.hpp"
 #include "runtime/globals.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepointMechanism.inline.hpp"
 #include "services/memTracker.hpp"
--- a/src/hotspot/share/runtime/sweeper.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/sweeper.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -37,7 +37,6 @@
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "oops/method.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/handshake.hpp"
 #include "runtime/mutexLocker.hpp"
--- a/src/hotspot/share/runtime/threadHeapSampler.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/threadHeapSampler.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,8 +24,8 @@
  */
 
 #include "precompiled.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/threadHeapSampler.hpp"
 
--- a/src/hotspot/share/runtime/threadSMR.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/threadSMR.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,9 @@
 #include "precompiled.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/jniHandles.inline.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadSMR.inline.hpp"
--- a/src/hotspot/share/runtime/vmThread.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/verifyOopClosure.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/mutexLocker.hpp"
--- a/src/hotspot/share/services/lowMemoryDetector.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/lowMemoryDetector.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 #define SHARE_SERVICES_LOWMEMORYDETECTOR_HPP
 
 #include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
 #include "services/memoryPool.hpp"
 #include "services/memoryService.hpp"
 #include "services/memoryUsage.hpp"
--- a/src/hotspot/share/services/mallocSiteTable.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/mallocSiteTable.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,8 @@
 #ifndef SHARE_SERVICES_MALLOCSITETABLE_HPP
 #define SHARE_SERVICES_MALLOCSITETABLE_HPP
 
+#include "utilities/macros.hpp"
+
 #if INCLUDE_NMT
 
 #include "memory/allocation.hpp"
--- a/src/hotspot/share/services/mallocTracker.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/mallocTracker.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,6 @@
  */
 #include "precompiled.hpp"
 
-#include "runtime/atomic.hpp"
 #include "services/mallocSiteTable.hpp"
 #include "services/mallocTracker.hpp"
 #include "services/mallocTracker.inline.hpp"
@@ -153,5 +152,3 @@
   header->release();
   return (void*)header;
 }
-
-
--- a/src/hotspot/share/services/mallocTracker.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/mallocTracker.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -70,8 +70,9 @@
     }
   }
 
-  inline void resize(long sz) {
+  inline void resize(ssize_t sz) {
     if (sz != 0) {
+      assert(sz >= 0 || _size >= size_t(-sz), "Must be");
       Atomic::add(&_size, size_t(sz));
       DEBUG_ONLY(_peak_size = MAX2(_size, _peak_size);)
     }
@@ -113,7 +114,7 @@
     _arena.deallocate(0);
   }
 
-  inline void record_arena_size_change(long sz) {
+  inline void record_arena_size_change(ssize_t sz) {
     _arena.resize(sz);
   }
 
@@ -207,7 +208,7 @@
      as_snapshot()->by_type(flag)->record_arena_free();
    }
 
-   static inline void record_arena_size_change(long size, MEMFLAGS flag) {
+   static inline void record_arena_size_change(ssize_t size, MEMFLAGS flag) {
      as_snapshot()->by_type(flag)->record_arena_size_change(size);
    }
 
@@ -361,7 +362,7 @@
     MallocMemorySummary::record_arena_free(flags);
   }
 
-  static inline void record_arena_size_change(int size, MEMFLAGS flags) {
+  static inline void record_arena_size_change(ssize_t size, MEMFLAGS flags) {
     MallocMemorySummary::record_arena_size_change(size, flags);
   }
  private:
--- a/src/hotspot/share/services/memTracker.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/memTracker.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 #include "jvm.h"
 
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vmOperations.hpp"
--- a/src/hotspot/share/services/memTracker.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/memTracker.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -63,7 +63,7 @@
 
   static inline void record_new_arena(MEMFLAGS flag) { }
   static inline void record_arena_free(MEMFLAGS flag) { }
-  static inline void record_arena_size_change(int diff, MEMFLAGS flag) { }
+  static inline void record_arena_size_change(ssize_t diff, MEMFLAGS flag) { }
   static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
                        MEMFLAGS flag = mtNone) { }
   static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
@@ -203,7 +203,7 @@
 
   // Record arena size change. Arena size is the size of all arena
   // chuncks that backing up the arena.
-  static inline void record_arena_size_change(int diff, MEMFLAGS flag) {
+  static inline void record_arena_size_change(ssize_t diff, MEMFLAGS flag) {
     if (tracking_level() < NMT_summary) return;
     MallocTracker::record_arena_size_change(diff, flag);
   }
--- a/src/hotspot/share/services/memoryManager.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/memoryManager.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,9 +27,9 @@
 #include "classfile/vmSymbols.hpp"
 #include "memory/allocation.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/orderAccess.hpp"
 #include "services/lowMemoryDetector.hpp"
 #include "services/management.hpp"
 #include "services/memoryManager.hpp"
--- a/src/hotspot/share/services/memoryPool.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/memoryPool.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -27,9 +27,9 @@
 #include "classfile/vmSymbols.hpp"
 #include "memory/metaspace.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/orderAccess.hpp"
 #include "services/lowMemoryDetector.hpp"
 #include "services/management.hpp"
 #include "services/memoryManager.hpp"
--- a/src/hotspot/share/services/threadIdTable.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/threadIdTable.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,6 +24,7 @@
 */
 
 #include "precompiled.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadSMR.hpp"
@@ -32,7 +33,6 @@
 #include "utilities/concurrentHashTable.inline.hpp"
 #include "utilities/concurrentHashTableTasks.inline.hpp"
 
-
 typedef ConcurrentHashTable<ThreadIdTableConfig, mtInternal> ThreadIdTableHash;
 
 // 2^24 is max size
--- a/src/hotspot/share/services/threadStackTracker.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/threadStackTracker.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,6 @@
 
 #include "precompiled.hpp"
 
-#include "runtime/atomic.hpp"
 #include "runtime/threadCritical.hpp"
 #include "services/mallocTracker.hpp"
 #include "services/memTracker.hpp"
--- a/src/hotspot/share/services/virtualMemoryTracker.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/services/virtualMemoryTracker.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,6 @@
 
 #include "logging/log.hpp"
 #include "memory/metaspace.hpp"
-#include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "runtime/threadCritical.hpp"
 #include "services/memTracker.hpp"
--- a/src/hotspot/share/utilities/bitMap.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/utilities/bitMap.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,6 @@
 #define SHARE_UTILITIES_BITMAP_INLINE_HPP
 
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "utilities/bitMap.hpp"
 #include "utilities/count_trailing_zeros.hpp"
 
--- a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
 #ifndef SHARE_UTILITIES_CONCURRENTHASHTABLETASKS_INLINE_HPP
 #define SHARE_UTILITIES_CONCURRENTHASHTABLETASKS_INLINE_HPP
 
+#include "runtime/atomic.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/concurrentHashTable.inline.hpp"
 
--- a/src/hotspot/share/utilities/globalCounter.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/utilities/globalCounter.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "utilities/globalCounter.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadSMR.inline.hpp"
 #include "runtime/vmThread.hpp"
--- a/src/hotspot/share/utilities/globalCounter.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/utilities/globalCounter.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,6 @@
 #define SHARE_UTILITIES_GLOBALCOUNTER_INLINE_HPP
 
 #include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/globalCounter.hpp"
 
--- a/src/hotspot/share/utilities/hashtable.inline.hpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/hotspot/share/utilities/hashtable.inline.hpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
 #define SHARE_UTILITIES_HASHTABLE_INLINE_HPP
 
 #include "memory/allocation.inline.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/atomic.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/dtrace.hpp"
 
--- a/src/java.base/share/classes/java/io/InvalidClassException.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/io/InvalidClassException.java	Fri Nov 29 10:02:07 2019 +0000
@@ -33,6 +33,10 @@
  *      descriptor read from the stream
  * <LI> The class contains unknown datatypes
  * <LI> The class does not have an accessible no-arg constructor
+ * <LI> The ObjectStreamClass of an enum constant does not represent
+ *      an enum type
+ * <LI> Other conditions given in the <cite>Java Object Serialization
+ *      Specification</cite>
  * </UL>
  *
  * @author  unascribed
--- a/src/java.base/share/classes/java/lang/Class.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/lang/Class.java	Fri Nov 29 10:02:07 2019 +0000
@@ -3503,7 +3503,9 @@
      * Returns true if and only if this class was declared as an enum in the
      * source code.
      *
-     * Note that if an enum constant is declared with a class body,
+     * Note that {@link java.lang.Enum} is not itself an enum type.
+     *
+     * Also note that if an enum constant is declared with a class body,
      * the class of that enum constant object is an anonymous class
      * and <em>not</em> the class of the declaring enum type. The
      * {@link Enum#getDeclaringClass} method of an enum constant can
--- a/src/java.base/share/classes/java/lang/invoke/CallSite.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/CallSite.java	Fri Nov 29 10:02:07 2019 +0000
@@ -87,9 +87,10 @@
 abstract
 public class CallSite {
 
-    // The actual payload of this call site:
+    // The actual payload of this call site.
+    // Can be modified using {@link MethodHandleNatives#setCallSiteTargetNormal} or {@link MethodHandleNatives#setCallSiteTargetVolatile}.
     /*package-private*/
-    MethodHandle target;    // Note: This field is known to the JVM.  Do not change.
+    final MethodHandle target;  // Note: This field is known to the JVM.
 
     /**
      * Make a blank call site object with the given method type.
@@ -129,11 +130,11 @@
      */
     /*package-private*/
     CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
-        this(targetType);
+        this(targetType); // need to initialize target to make CallSite.type() work in createTargetHook
         ConstantCallSite selfCCS = (ConstantCallSite) this;
         MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS);
-        checkTargetChange(this.target, boundTarget);
-        this.target = boundTarget;
+        setTargetNormal(boundTarget); // ConstantCallSite doesn't publish CallSite.target
+        UNSAFE.storeStoreFence(); // barrier between target and isFrozen updates
     }
 
     /**
@@ -190,11 +191,12 @@
      */
     public abstract void setTarget(MethodHandle newTarget);
 
-    void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
-        MethodType oldType = oldTarget.type();
+    private void checkTargetChange(MethodHandle newTarget) {
+        MethodType oldType = target.type(); // target is always present
         MethodType newType = newTarget.type();  // null check!
-        if (!newType.equals(oldType))
+        if (newType != oldType) {
             throw wrongTargetType(newTarget, oldType);
+        }
     }
 
     private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
@@ -217,7 +219,7 @@
      */
     public abstract MethodHandle dynamicInvoker();
 
-    /*non-public*/
+    /*package-private*/
     MethodHandle makeDynamicInvoker() {
         MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this);
         MethodHandle invoker = MethodHandles.exactInvoker(this.type());
@@ -283,19 +285,24 @@
     }
 
     /*package-private*/
-    void setTargetNormal(MethodHandle newTarget) {
+    final void setTargetNormal(MethodHandle newTarget) {
+        checkTargetChange(newTarget);
         MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
     }
+
     /*package-private*/
-    MethodHandle getTargetVolatile() {
+    final MethodHandle getTargetVolatile() {
         return (MethodHandle) UNSAFE.getReferenceVolatile(this, getTargetOffset());
     }
+
     /*package-private*/
-    void setTargetVolatile(MethodHandle newTarget) {
+    final void setTargetVolatile(MethodHandle newTarget) {
+        checkTargetChange(newTarget);
         MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
     }
 
     // this implements the upcall from the JVM, MethodHandleNatives.linkCallSite:
+    /*package-private*/
     static CallSite makeSite(MethodHandle bootstrapMethod,
                              // Callee information:
                              String name, MethodType type,
--- a/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,9 @@
 
 package java.lang.invoke;
 
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.Stable;
+
 /**
  * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
  * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
@@ -33,7 +36,10 @@
  * @since 1.7
  */
 public class ConstantCallSite extends CallSite {
-    private final boolean isFrozen;
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+    @Stable // should NOT be constant folded during instance initialization (isFrozen == false)
+    /*final*/ private boolean isFrozen;
 
     /**
      * Creates a call site with a permanent target.
@@ -43,6 +49,7 @@
     public ConstantCallSite(MethodHandle target) {
         super(target);
         isFrozen = true;
+        UNSAFE.storeStoreFence(); // properly publish isFrozen update
     }
 
     /**
@@ -79,8 +86,9 @@
      * @throws Throwable anything else thrown by the hook function
      */
     protected ConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
-        super(targetType, createTargetHook);
+        super(targetType, createTargetHook); // "this" instance leaks into createTargetHook
         isFrozen = true;
+        UNSAFE.storeStoreFence(); // properly publish isFrozen
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java	Fri Nov 29 10:02:07 2019 +0000
@@ -152,7 +152,6 @@
      * @see #getTarget
      */
     @Override public void setTarget(MethodHandle newTarget) {
-        checkTargetChange(this.target, newTarget);
         setTargetNormal(newTarget);
     }
 
--- a/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java	Fri Nov 29 10:02:07 2019 +0000
@@ -96,7 +96,6 @@
      * @see #getTarget
      */
     @Override public void setTarget(MethodHandle newTarget) {
-        checkTargetChange(getTargetVolatile(), newTarget);
         setTargetVolatile(newTarget);
     }
 
--- a/src/java.base/share/classes/java/net/MulticastSocket.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/net/MulticastSocket.java	Fri Nov 29 10:02:07 2019 +0000
@@ -576,7 +576,7 @@
     public NetworkInterface getNetworkInterface() throws SocketException {
         NetworkInterface ni
             = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
-        if ((ni.getIndex() == 0) || (ni.getIndex() == -1)) {
+        if (ni == null) {
             InetAddress[] addrs = new InetAddress[1];
             addrs[0] = InetAddress.anyLocalAddress();
             return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
--- a/src/java.base/share/classes/java/util/Arrays.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/java/util/Arrays.java	Fri Nov 29 10:02:07 2019 +0000
@@ -7117,10 +7117,10 @@
      * and proper prefix.)
      *
      * <p>A {@code null} array reference is considered lexicographically less
-     * than a non-{@code null} array reference.  Two {@code null} array
+     * than a non-{@code null} array reference. Two {@code null} array
      * references are considered equal.
-     * A {@code null} array element is considered lexicographically than a
-     * non-{@code null} array element.  Two {@code null} array elements are
+     * A {@code null} array element is considered lexicographically less than a
+     * non-{@code null} array element. Two {@code null} array elements are
      * considered equal.
      *
      * <p>The comparison is consistent with {@link #equals(Object[], Object[]) equals},
--- a/src/java.base/share/classes/jdk/internal/PreviewFeature.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/share/classes/jdk/internal/PreviewFeature.java	Fri Nov 29 10:02:07 2019 +0000
@@ -54,6 +54,8 @@
     public boolean essentialAPI() default false;
 
     public enum Feature {
-        TEXT_BLOCKS;
+        PATTERN_MATCHING_IN_INSTANCEOF,
+        TEXT_BLOCKS,
+        ;
     }
 }
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Fri Nov 29 10:02:07 2019 +0000
@@ -1494,25 +1494,7 @@
         if (ni) {
             return ni;
         }
-
-        /*
-         * The address doesn't appear to be bound at any known
-         * NetworkInterface. Therefore we construct a NetworkInterface
-         * with this address.
-         */
-        ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-        CHECK_NULL_RETURN(ni, NULL);
-
-        (*env)->SetIntField(env, ni, ni_indexID, -1);
-        addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL);
-        CHECK_NULL_RETURN(addrArray, NULL);
-        (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-        (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        ni_name = (*env)->NewStringUTF(env, "");
-        if (ni_name != NULL) {
-            (*env)->SetObjectField(env, ni, ni_nameID, ni_name);
-        }
-        return ni;
+        return NULL;
     }
 
 
@@ -1619,19 +1601,6 @@
         if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
             return addr;
         }
-
-        ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-        CHECK_NULL_RETURN(ni, NULL);
-        (*env)->SetIntField(env, ni, ni_indexID, -1);
-        addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL);
-        CHECK_NULL_RETURN(addrArray, NULL);
-        (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-        (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        ni_name = (*env)->NewStringUTF(env, "");
-        if (ni_name != NULL) {
-            (*env)->SetObjectField(env, ni, ni_nameID, ni_name);
-        }
-        return ni;
     }
     return NULL;
 }
--- a/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Fri Nov 29 10:02:07 2019 +0000
@@ -1691,7 +1691,6 @@
         static jfieldID ni_indexID;
         static jfieldID ni_addrsID;
 
-        jobjectArray addrArray;
         jobject addr;
         jobject ni;
 
@@ -1749,19 +1748,7 @@
         if (ni) {
             return ni;
         }
-        if (ipv4Mode) {
-            ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-            CHECK_NULL_RETURN(ni, NULL);
-
-            (*env)->SetIntField(env, ni, ni_indexID, -1);
-            addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL);
-            CHECK_NULL_RETURN(addrArray, NULL);
-            (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-            (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        } else {
-            ni = NULL;
-        }
-        return ni;
+        return NULL;
 }
 
 /*
@@ -1898,26 +1885,6 @@
                 return netObject;
             }
         }
-
-        /*
-         * Multicast to any address - return anyLocalAddress
-         * or a NetworkInterface with addrs[0] set to anyLocalAddress
-         */
-
-        addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID,
-                                              NULL);
-        if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
-            return addr;
-        }
-
-        ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-        CHECK_NULL_RETURN(ni, NULL);
-        (*env)->SetIntField(env, ni, ni_indexID, -1);
-        addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL);
-        CHECK_NULL_RETURN(addrArray, NULL);
-        (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-        (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        return ni;
     }
     return NULL;
 }
--- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java	Fri Nov 29 10:02:07 2019 +0000
@@ -209,7 +209,10 @@
      * Close the connection.  */
     public void close() throws IOException
     {
-        TCPTransport.tcpLog.log(Log.BRIEF, "close connection");
+        if (TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {
+            TCPTransport.tcpLog.log(Log.BRIEF,
+                    "close connection, socket: " + socket);
+        }
 
         if (socket != null)
             socket.close();
--- a/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Fri Nov 29 10:02:07 2019 +0000
@@ -273,12 +273,23 @@
     private void decrementExportCount() {
         assert Thread.holdsLock(this);
         exportCount--;
+        if (tcpLog.isLoggable(Log.VERBOSE)) {
+            tcpLog.log(Log.VERBOSE,
+                    "server socket: " + server + ", exportCount: " + exportCount);
+        }
         if (exportCount == 0 && getEndpoint().getListenPort() != 0) {
             ServerSocket ss = server;
             server = null;
             try {
+                if (tcpLog.isLoggable(Log.BRIEF)) {
+                    tcpLog.log(Log.BRIEF, "server socket close: " + ss);
+                }
                 ss.close();
             } catch (IOException e) {
+                if (tcpLog.isLoggable(Log.BRIEF)) {
+                    tcpLog.log(Log.BRIEF,
+                            "server socket close throws: " + e);
+                }
             }
         }
     }
@@ -366,6 +377,10 @@
                 executeAcceptLoop();
             } finally {
                 try {
+                    if (tcpLog.isLoggable(Log.BRIEF)) {
+                        tcpLog.log(Log.BRIEF,
+                                "server socket close: " + serverSocket);
+                    }
                     /*
                      * Only one accept loop is started per server
                      * socket, so after no more connections will be
@@ -374,6 +389,10 @@
                      */
                     serverSocket.close();
                 } catch (IOException e) {
+                    if (tcpLog.isLoggable(Log.BRIEF)) {
+                        tcpLog.log(Log.BRIEF,
+                                "server socket close throws: " + e);
+                    }
                 }
             }
         }
@@ -524,9 +543,15 @@
     /** close socket and eat exception */
     private static void closeSocket(Socket sock) {
         try {
+            if (tcpLog.isLoggable(Log.BRIEF)) {
+                tcpLog.log(Log.BRIEF, "socket close: " + sock);
+            }
             sock.close();
         } catch (IOException ex) {
             // eat exception
+            if (tcpLog.isLoggable(Log.BRIEF)) {
+                tcpLog.log(Log.BRIEF, "socket close throws: " + ex);
+            }
         }
     }
 
@@ -591,6 +616,9 @@
                 conn.close();
             } catch (IOException ex) {
                 // eat exception
+                if (tcpLog.isLoggable(Log.BRIEF)) {
+                    tcpLog.log(Log.BRIEF, "Connection close throws " + ex);
+                }
             }
         }
     }
@@ -723,6 +751,10 @@
                     // just close socket: this would recurse if we marshal an
                     // exception to the client and the protocol at other end
                     // doesn't match.
+                    if (tcpLog.isLoggable(Log.BRIEF)) {
+                        tcpLog.log(Log.BRIEF, "magic or version not match: "
+                                                  + magic + ", " + version);
+                    }
                     closeSocket(socket);
                     return;
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/BindingPatternTree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,58 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+import javax.lang.model.element.Name;
+
+/**
+ * {@preview Associated with pattern matching for instanceof, a preview feature of
+ *           the Java language.
+ *
+ *           This interface is associated with <i>pattern matching for instanceof</i>, a preview
+ *           feature of the Java language. Preview features
+ *           may be removed in a future release, or upgraded to permanent
+ *           features of the Java language.}
+ *
+ * A binding pattern tree
+ *
+ * @since 14
+ */
+public interface BindingPatternTree extends PatternTree {
+
+    /**
+     * Returns the type of the bind variable.
+     * @return the type
+     */
+    Tree getType();
+
+    /**
+     * A binding variable name.
+     * @return the name of the binding variable
+     */
+    Name getBinding();
+
+}
+
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/InstanceOfTree.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/InstanceOfTree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, 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
@@ -51,4 +51,33 @@
      * @return the type
      */
     Tree getType();
+
+    /**
+     * {@preview Associated with pattern matching for instanceof, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>pattern matching for instanceof</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * Returns the tested pattern, or null if this instanceof does not use
+     * a pattern.
+     *
+     * <p>For instanceof with a pattern, i.e. in the following form:
+     * <pre>
+     *   <em>expression</em> instanceof <em>type</em> <em>variable name</em>
+     * </pre>
+     * returns the pattern.
+     *
+     * <p>For instanceof without a pattern, i.e. in the following form:
+     * <pre>
+     *   <em>expression</em> instanceof <em>type</em>
+     * </pre>
+     * returns null.
+     *
+     * @return the tested pattern, or null if this instanceof does not use a pattern.
+     * @since 14
+     */
+    PatternTree getPattern();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,42 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * {@preview Associated with pattern matching for instanceof, a preview feature of
+ *           the Java language.
+ *
+ *           This interface is associated with <i>pattern matching for instanceof</i>, a preview
+ *           feature of the Java language. Preview features
+ *           may be removed in a future release, or upgraded to permanent
+ *           features of the Java language.}
+ *
+ * A tree node used as the base class for the different kinds of
+ * statements.
+ *
+ * @since 14
+ */
+public interface PatternTree extends Tree {}
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -220,6 +220,21 @@
         PARENTHESIZED(ParenthesizedTree.class),
 
         /**
+         * {@preview Associated with pattern matching for instanceof, a preview feature of
+         *           the Java language.
+         *
+         *           This enum constant is associated with <i>pattern matching for instanceof</i>, a preview
+         *           feature of the Java language. Preview features
+         *           may be removed in a future release, or upgraded to permanent
+         *           features of the Java language.}
+         *
+         * Used for instances of {@link BindingPatternTree}.
+         *
+         * @since 14
+         */
+        BINDING_PATTERN(BindingPatternTree.class),
+
+        /**
          * Used for instances of {@link PrimitiveTypeTree}.
          */
         PRIMITIVE_TYPE(PrimitiveTypeTree.class),
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Fri Nov 29 10:02:07 2019 +0000
@@ -258,6 +258,23 @@
     R visitLiteral(LiteralTree node, P p);
 
     /**
+     * {@preview Associated with pattern matching for instanceof, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>pattern matching for instanceof</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * Visits an BindingPattern node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     * @since 14
+     */
+    R visitBindingPattern(BindingPatternTree node, P p);
+
+    /**
      * Visits a MethodTree node.
      * @param node the node being visited
      * @param p a parameter value
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Fri Nov 29 10:02:07 2019 +0000
@@ -557,6 +557,19 @@
      * @param node {@inheritDoc}
      * @param p {@inheritDoc}
      * @return  the result of {@code defaultAction}
+     * @since 14
+     */
+    @Override
+    public R visitBindingPattern(BindingPatternTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    /**
+     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     *
+     * @param node {@inheritDoc}
+     * @param p {@inheritDoc}
+     * @return  the result of {@code defaultAction}
      */
     @Override
     public R visitArrayAccess(ArrayAccessTree node, P p) {
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Fri Nov 29 10:02:07 2019 +0000
@@ -667,7 +667,11 @@
     @Override
     public R visitInstanceOf(InstanceOfTree node, P p) {
         R r = scan(node.getExpression(), p);
-        r = scanAndReduce(node.getType(), p, r);
+        if (node.getPattern() != null) {
+            r = scanAndReduce(node.getPattern(), p, r);
+        } else {
+            r = scanAndReduce(node.getType(), p, r);
+        }
         return r;
     }
 
@@ -677,6 +681,19 @@
      * @param node  {@inheritDoc}
      * @param p  {@inheritDoc}
      * @return the result of scanning
+     * @since 14
+     */
+    @Override
+    public R visitBindingPattern(BindingPatternTree node, P p) {
+        return scan(node.getType(), p);
+    }
+
+    /**
+     * {@inheritDoc} This implementation scans the children in left to right order.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of scanning
      */
     @Override
     public R visitArrayAccess(ArrayAccessTree node, P p) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Fri Nov 29 10:02:07 2019 +0000
@@ -334,6 +334,16 @@
      */
     public static final long PREVIEW_ESSENTIAL_API = 1L<<58; //any Symbol kind
 
+    /**
+     * Flag to indicate the given variable is a match binding variable.
+     */
+    public static final long MATCH_BINDING = 1L<<59;
+
+    /**
+     * A flag to indicate a match binding variable whose scope extends after the current statement.
+     */
+    public static final long MATCH_BINDING_TO_OUTER = 1L<<60;
+
     /** Modifier masks.
      */
     public static final int
@@ -453,7 +463,9 @@
         ANONCONSTR_BASED(Flags.ANONCONSTR_BASED),
         NAME_FILLED(Flags.NAME_FILLED),
         PREVIEW_API(Flags.PREVIEW_API),
-        PREVIEW_ESSENTIAL_API(Flags.PREVIEW_ESSENTIAL_API);
+        PREVIEW_ESSENTIAL_API(Flags.PREVIEW_ESSENTIAL_API),
+        MATCH_BINDING(Flags.MATCH_BINDING),
+        MATCH_BINDING_TO_OUTER(Flags.MATCH_BINDING_TO_OUTER);
 
         Flag(long flag) {
             this.value = flag;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -165,7 +165,9 @@
      * @return true, if given feature is a preview feature.
      */
     public boolean isPreview(Feature feature) {
-        if (feature == Feature.TEXT_BLOCKS)
+        if (feature == Feature.PATTERN_MATCHING_IN_INSTANCEOF ||
+            feature == Feature.REIFIABLE_TYPES_INSTANCEOF ||
+            feature == Feature.TEXT_BLOCKS)
             return true;
         //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
         //When real preview features will be added, this method can be implemented to return 'true'
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Fri Nov 29 10:02:07 2019 +0000
@@ -198,7 +198,10 @@
         SWITCH_MULTIPLE_CASE_LABELS(JDK14, Fragments.FeatureMultipleCaseLabels, DiagKind.PLURAL),
         SWITCH_RULE(JDK14, Fragments.FeatureSwitchRules, DiagKind.PLURAL),
         SWITCH_EXPRESSION(JDK14, Fragments.FeatureSwitchExpressions, DiagKind.PLURAL),
-        TEXT_BLOCKS(JDK14, Fragments.FeatureTextBlocks, DiagKind.PLURAL);
+        TEXT_BLOCKS(JDK14, Fragments.FeatureTextBlocks, DiagKind.PLURAL),
+        PATTERN_MATCHING_IN_INSTANCEOF(JDK14, Fragments.FeaturePatternMatchingInstanceof, DiagKind.NORMAL),
+        REIFIABLE_TYPES_INSTANCEOF(JDK14, Fragments.FeatureReifiableTypesInstanceof, DiagKind.PLURAL),
+        ;
 
         enum DiagKind {
             NORMAL,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -390,22 +390,26 @@
                 sym.getKind() == ElementKind.LOCAL_VARIABLE ||
                 sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
                 sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
-                // Make sure all type annotations from the symbol are also
-                // on the owner. If the owner is an initializer block, propagate
-                // to the type.
-                final long ownerFlags = sym.owner.flags();
-                if ((ownerFlags & Flags.BLOCK) != 0) {
-                    // Store init and clinit type annotations with the ClassSymbol
-                    // to allow output in Gen.normalizeDefs.
-                    ClassSymbol cs = (ClassSymbol) sym.owner.owner;
-                    if ((ownerFlags & Flags.STATIC) != 0) {
-                        cs.appendClassInitTypeAttributes(typeAnnotations);
-                    } else {
-                        cs.appendInitTypeAttributes(typeAnnotations);
-                    }
+                appendTypeAnnotationsToOwner(sym, typeAnnotations);
+            }
+        }
+
+        private void appendTypeAnnotationsToOwner(Symbol sym, List<Attribute.TypeCompound> typeAnnotations) {
+            // Make sure all type annotations from the symbol are also
+            // on the owner. If the owner is an initializer block, propagate
+            // to the type.
+            final long ownerFlags = sym.owner.flags();
+            if ((ownerFlags & Flags.BLOCK) != 0) {
+                // Store init and clinit type annotations with the ClassSymbol
+                // to allow output in Gen.normalizeDefs.
+                ClassSymbol cs = (ClassSymbol) sym.owner.owner;
+                if ((ownerFlags & Flags.STATIC) != 0) {
+                    cs.appendClassInitTypeAttributes(typeAnnotations);
                 } else {
-                    sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes());
+                    cs.appendInitTypeAttributes(typeAnnotations);
                 }
+            } else {
+                sym.owner.appendUniqueTypeAttributes(typeAnnotations);
             }
         }
 
@@ -943,10 +947,11 @@
                                                  " within frame " + frame);
                     }
 
+                case BINDING_PATTERN:
                 case VARIABLE:
-                    VarSymbol v = ((JCVariableDecl)frame).sym;
+                    VarSymbol v = frame.hasTag(Tag.BINDINGPATTERN) ? ((JCBindingPattern) frame).symbol : ((JCVariableDecl) frame).sym;
                     if (v.getKind() != ElementKind.FIELD) {
-                        v.owner.appendUniqueTypeAttributes(v.getRawTypeAttributes());
+                        appendTypeAnnotationsToOwner(v, v.getRawTypeAttributes());
                     }
                     switch (v.getKind()) {
                         case LOCAL_VARIABLE:
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1122,6 +1122,13 @@
         }
 
         @Override
+        public void visitBindingPattern(JCTree.JCBindingPattern tree) {
+            //type binding pattern's type will be annotated separatelly, avoid
+            //adding its annotations into the owning method here (would clash
+            //with repeatable annotations).
+        }
+
+        @Override
         public void visitClassDef(JCClassDecl tree) {
             // We can only hit a classdef if it is declared within
             // a method. Ignore it - the class will be visited
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 29 10:02:07 2019 +0000
@@ -49,6 +49,7 @@
 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
 import com.sun.tools.javac.comp.Check.CheckContext;
 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
+import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol;
 import com.sun.tools.javac.jvm.*;
 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond;
 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg;
@@ -110,6 +111,7 @@
     final Enter enter;
     final Target target;
     final Types types;
+    final Preview preview;
     final JCDiagnostic.Factory diags;
     final TypeAnnotations typeAnnotations;
     final DeferredLintHandler deferredLintHandler;
@@ -117,6 +119,7 @@
     final Dependencies dependencies;
     final Annotate annotate;
     final ArgumentAttr argumentAttr;
+    final MatchBindingsComputer matchBindingsComputer;
 
     public static Attr instance(Context context) {
         Attr instance = context.get(attrKey);
@@ -145,6 +148,7 @@
         cfolder = ConstFold.instance(context);
         target = Target.instance(context);
         types = Types.instance(context);
+        preview = Preview.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         annotate = Annotate.instance(context);
         typeAnnotations = TypeAnnotations.instance(context);
@@ -152,6 +156,7 @@
         typeEnvs = TypeEnvs.instance(context);
         dependencies = Dependencies.instance(context);
         argumentAttr = ArgumentAttr.instance(context);
+        matchBindingsComputer = MatchBindingsComputer.instance(context);
 
         Options options = Options.instance(context);
 
@@ -161,6 +166,9 @@
         allowLambda = Feature.LAMBDA.allowedInSource(source);
         allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source);
         allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source);
+        allowReifiableTypesInInstanceof =
+                Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source) &&
+                (!preview.isPreview(Feature.REIFIABLE_TYPES_INSTANCEOF) || preview.isEnabled());
         sourceName = source.name;
         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
 
@@ -193,6 +201,10 @@
      */
     boolean allowStaticInterfaceMethods;
 
+    /** Switch: reifiable types in instanceof enabled?
+     */
+    boolean allowReifiableTypesInInstanceof;
+
     /**
      * Switch: warn about use of variable before declaration?
      * RFE: 6425594
@@ -292,6 +304,8 @@
                isAssignableAsBlankFinal(v, env)))) {
             if (v.isResourceVariable()) { //TWR resource
                 log.error(pos, Errors.TryResourceMayNotBeAssigned(v));
+            } else if ((v.flags() & MATCH_BINDING) != 0) {
+                log.error(pos, Errors.PatternBindingMayNotBeAssigned(v));
             } else {
                 log.error(pos, Errors.CantAssignValToFinalVar(v));
             }
@@ -1298,29 +1312,73 @@
     public void visitDoLoop(JCDoWhileLoop tree) {
         attribStat(tree.body, env.dup(tree));
         attribExpr(tree.cond, env, syms.booleanType);
+        if (!breaksOutOf(tree, tree.body)) {
+            //include condition's body when false after the while, if cannot get out of the loop
+            List<BindingSymbol> bindings = matchBindingsComputer.getMatchBindings(tree.cond, false);
+
+            bindings.forEach(env.info.scope::enter);
+            bindings.forEach(BindingSymbol::preserveBinding);
+        }
         result = null;
     }
 
     public void visitWhileLoop(JCWhileLoop tree) {
         attribExpr(tree.cond, env, syms.booleanType);
-        attribStat(tree.body, env.dup(tree));
+        // include condition's bindings when true in the body:
+        Env<AttrContext> whileEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, true));
+        try {
+            attribStat(tree.body, whileEnv.dup(tree));
+        } finally {
+            whileEnv.info.scope.leave();
+        }
+        if (!breaksOutOf(tree, tree.body)) {
+            //include condition's bindings when false after the while, if cannot get out of the loop
+            List<BindingSymbol> bindings =
+                    matchBindingsComputer.getMatchBindings(tree.cond, false);
+
+            bindings.forEach(env.info.scope::enter);
+            bindings.forEach(BindingSymbol::preserveBinding);
+        }
         result = null;
     }
 
+    private boolean breaksOutOf(JCTree loop, JCTree body) {
+        preFlow(body);
+        return flow.breaksOutOf(env, loop, body, make);
+    }
+
     public void visitForLoop(JCForLoop tree) {
         Env<AttrContext> loopEnv =
             env.dup(env.tree, env.info.dup(env.info.scope.dup()));
         try {
             attribStats(tree.init, loopEnv);
-            if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType);
-            loopEnv.tree = tree; // before, we were not in loop!
-            attribStats(tree.step, loopEnv);
-            attribStat(tree.body, loopEnv);
+            List<BindingSymbol> matchBindings = List.nil();
+            if (tree.cond != null) {
+                attribExpr(tree.cond, loopEnv, syms.booleanType);
+                // include condition's bindings when true in the body and step:
+                matchBindings = matchBindingsComputer.getMatchBindings(tree.cond, true);
+            }
+            Env<AttrContext> bodyEnv = bindingEnv(loopEnv, matchBindings);
+            try {
+                bodyEnv.tree = tree; // before, we were not in loop!
+                attribStats(tree.step, bodyEnv);
+                attribStat(tree.body, bodyEnv);
+            } finally {
+                bodyEnv.info.scope.leave();
+            }
             result = null;
         }
         finally {
             loopEnv.info.scope.leave();
         }
+        if (!breaksOutOf(tree, tree.body)) {
+            //include condition's body when false after the while, if cannot get out of the loop
+            List<BindingSymbol> bindings =
+                    matchBindingsComputer.getMatchBindings(tree.cond, false);
+
+            bindings.forEach(env.info.scope::enter);
+            bindings.forEach(BindingSymbol::preserveBinding);
+        }
     }
 
     public void visitForeachLoop(JCEnhancedForLoop tree) {
@@ -1673,8 +1731,26 @@
                 unknownExprInfo :
                 resultInfo.dup(conditionalContext(resultInfo.checkContext));
 
-        Type truetype = attribTree(tree.truepart, env, condInfo);
-        Type falsetype = attribTree(tree.falsepart, env, condInfo);
+
+        // x ? y : z
+        // include x's bindings when true in y
+        // include x's bindings when false in z
+
+        Type truetype;
+        Env<AttrContext> trueEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, true));
+        try {
+            truetype = attribTree(tree.truepart, trueEnv, condInfo);
+        } finally {
+            trueEnv.info.scope.leave();
+        }
+
+        Type falsetype;
+        Env<AttrContext> falseEnv = bindingEnv(env, matchBindingsComputer.getMatchBindings(tree.cond, false));
+        try {
+            falsetype = attribTree(tree.falsepart, falseEnv, condInfo);
+        } finally {
+            falseEnv.info.scope.leave();
+        }
 
         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ?
                 condType(List.of(tree.truepart.pos(), tree.falsepart.pos()),
@@ -1829,15 +1905,77 @@
         BOOLEAN,
     };
 
+    Env<AttrContext> bindingEnv(Env<AttrContext> env, List<BindingSymbol> bindings) {
+        Env<AttrContext> env1 = env.dup(env.tree, env.info.dup(env.info.scope.dup()));
+        bindings.forEach(env1.info.scope::enter);
+        return env1;
+    }
+
     public void visitIf(JCIf tree) {
         attribExpr(tree.cond, env, syms.booleanType);
-        attribStat(tree.thenpart, env);
-        if (tree.elsepart != null)
-            attribStat(tree.elsepart, env);
+
+        // if (x) { y } [ else z ]
+        // include x's bindings when true in y
+        // include x's bindings when false in z
+
+        List<BindingSymbol> thenBindings = matchBindingsComputer.getMatchBindings(tree.cond, true);
+        Env<AttrContext> thenEnv = bindingEnv(env, thenBindings);
+
+        try {
+            attribStat(tree.thenpart, thenEnv);
+        } finally {
+            thenEnv.info.scope.leave();
+        }
+
+        preFlow(tree.thenpart);
+        boolean aliveAfterThen = flow.aliveAfter(env, tree.thenpart, make);
+        boolean aliveAfterElse;
+        List<BindingSymbol> elseBindings = matchBindingsComputer.getMatchBindings(tree.cond, false);
+
+        if (tree.elsepart != null) {
+            Env<AttrContext> elseEnv = bindingEnv(env, elseBindings);
+            try {
+                attribStat(tree.elsepart, elseEnv);
+            } finally {
+                elseEnv.info.scope.leave();
+            }
+            preFlow(tree.elsepart);
+            aliveAfterElse = flow.aliveAfter(env, tree.elsepart, make);
+        } else {
+            aliveAfterElse = true;
+        }
+
         chk.checkEmptyIf(tree);
+
+        List<BindingSymbol> afterIfBindings = List.nil();
+
+        if (aliveAfterThen && !aliveAfterElse) {
+            afterIfBindings = thenBindings;
+        } else if (aliveAfterElse && !aliveAfterThen) {
+            afterIfBindings = elseBindings;
+        }
+
+        afterIfBindings.forEach(env.info.scope::enter);
+        afterIfBindings.forEach(BindingSymbol::preserveBinding);
+
         result = null;
     }
 
+        void preFlow(JCTree tree) {
+            new PostAttrAnalyzer() {
+                @Override
+                public void scan(JCTree tree) {
+                    if (tree == null ||
+                            (tree.type != null &&
+                            tree.type == Type.stuckType)) {
+                        //don't touch stuck expressions!
+                        return;
+                    }
+                    super.scan(tree);
+                }
+            }.scan(tree);
+        }
+
     public void visitExec(JCExpressionStatement tree) {
         //a fresh environment is required for 292 inference to work properly ---
         //see Infer.instantiatePolymorphicSignatureInstance()
@@ -3521,7 +3659,32 @@
     public void visitBinary(JCBinary tree) {
         // Attribute arguments.
         Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env));
-        Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env));
+        // x && y
+        // include x's bindings when true in y
+
+        // x || y
+        // include x's bindings when false in y
+
+        List<BindingSymbol> matchBindings;
+        switch (tree.getTag()) {
+            case AND:
+                matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, true);
+                break;
+            case OR:
+                matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, false);
+                break;
+            default:
+                matchBindings = List.nil();
+                break;
+        }
+        Env<AttrContext> rhsEnv = bindingEnv(env, matchBindings);
+        Type right;
+        try {
+            right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, rhsEnv));
+        } finally {
+            rhsEnv.info.scope.leave();
+        }
+
         // Find operator.
         Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right);
         Type owntype = types.createErrorType(tree.type);
@@ -3587,19 +3750,63 @@
     public void visitTypeTest(JCInstanceOf tree) {
         Type exprtype = chk.checkNullOrRefType(
                 tree.expr.pos(), attribExpr(tree.expr, env));
-        Type clazztype = attribType(tree.clazz, env);
+        Type clazztype;
+        JCTree typeTree;
+        if (tree.pattern.getTag() == BINDINGPATTERN) {
+            attribTree(tree.pattern, env, unknownExprInfo);
+            clazztype = tree.pattern.type;
+            JCBindingPattern pattern = (JCBindingPattern) tree.pattern;
+            typeTree = pattern.vartype;
+            if (!clazztype.hasTag(TYPEVAR)) {
+                clazztype = chk.checkClassOrArrayType(pattern.vartype.pos(), clazztype);
+            }
+        } else {
+            clazztype = attribType(tree.pattern, env);
+            typeTree = tree.pattern;
+        }
         if (!clazztype.hasTag(TYPEVAR)) {
-            clazztype = chk.checkClassOrArrayType(tree.clazz.pos(), clazztype);
+            clazztype = chk.checkClassOrArrayType(typeTree.pos(), clazztype);
         }
         if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) {
-            log.error(tree.clazz.pos(), Errors.IllegalGenericTypeForInstof);
-            clazztype = types.createErrorType(clazztype);
-        }
-        chk.validate(tree.clazz, env, false);
+            boolean valid = false;
+            if (allowReifiableTypesInInstanceof) {
+                if (preview.isPreview(Feature.REIFIABLE_TYPES_INSTANCEOF)) {
+                    preview.warnPreview(tree.expr.pos(), Feature.REIFIABLE_TYPES_INSTANCEOF);
+                }
+                Warner warner = new Warner();
+                if (!types.isCastable(exprtype, clazztype, warner)) {
+                    chk.basicHandler.report(tree.expr.pos(),
+                                            diags.fragment(Fragments.InconvertibleTypes(exprtype, clazztype)));
+                } else if (warner.hasLint(LintCategory.UNCHECKED)) {
+                    log.error(tree.expr.pos(),
+                              Errors.InstanceofReifiableNotSafe(exprtype, clazztype));
+                } else {
+                    valid = true;
+                }
+            } else {
+                log.error(typeTree.pos(), Errors.IllegalGenericTypeForInstof);
+            }
+            if (!valid) {
+                clazztype = types.createErrorType(clazztype);
+            }
+        }
+        chk.validate(typeTree, env, false);
         chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
         result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo);
     }
 
+    public void visitBindingPattern(JCBindingPattern tree) {
+        ResultInfo varInfo = new ResultInfo(KindSelector.TYP, resultInfo.pt, resultInfo.checkContext);
+        tree.type = attribTree(tree.vartype, env, varInfo);
+        VarSymbol v = tree.symbol = new BindingSymbol(tree.name, tree.vartype.type, env.info.scope.owner);
+        if (chk.checkUnique(tree.pos(), v, env.info.scope)) {
+            chk.checkTransparentVar(tree.pos(), v, env.info.scope);
+        }
+        annotate.queueScanTreeAndTypeAnnotate(tree.vartype, env, v, tree.pos());
+        annotate.flush();
+        result = tree.type;
+    }
+
     public void visitIndexed(JCArrayAccess tree) {
         Type owntype = types.createErrorType(tree.type);
         Type atype = attribExpr(tree.indexed, env);
@@ -4991,8 +5198,8 @@
             super.visitTypeCast(tree);
         }
         public void visitTypeTest(JCInstanceOf tree) {
-            if (tree.clazz != null && tree.clazz.type != null)
-                validateAnnotatedType(tree.clazz, tree.clazz.type);
+            if (tree.pattern != null && !(tree.pattern instanceof JCPattern) && tree.pattern.type != null)
+                validateAnnotatedType(tree.pattern, tree.pattern.type);
             super.visitTypeTest(tree);
         }
         public void visitNewClass(JCNewClass tree) {
@@ -5253,6 +5460,15 @@
         }
 
         @Override
+        public void visitBindingPattern(JCBindingPattern that) {
+            if (that.symbol == null) {
+                that.symbol = new BindingSymbol(that.name, that.type, syms.noSymbol);
+                that.symbol.adr = 0;
+            }
+            super.visitBindingPattern(that);
+        }
+
+        @Override
         public void visitNewClass(JCNewClass that) {
             if (that.constructor == null) {
                 that.constructor = new MethodSymbol(0, names.init,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Nov 29 10:02:07 2019 +0000
@@ -3486,6 +3486,11 @@
                     duplicateErasureError(pos, sym, byName);
                     sym.flags_field |= CLASH;
                     return true;
+                } else if ((sym.flags() & MATCH_BINDING) != 0 &&
+                           (byName.flags() & MATCH_BINDING) != 0 &&
+                           (byName.flags() & MATCH_BINDING_TO_OUTER) == 0) {
+                    //this error will be reported separatelly in MatchBindingsComputer
+                    return false;
                 } else {
                     duplicateError(pos, byName);
                     return false;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java	Fri Nov 29 10:02:07 2019 +0000
@@ -59,9 +59,10 @@
         ATTR(4),
         FLOW(5),
         TRANSTYPES(6),
-        UNLAMBDA(7),
-        LOWER(8),
-        GENERATE(9);
+        TRANSPATTERNS(7),
+        UNLAMBDA(8),
+        LOWER(9),
+        GENERATE(10);
 
         CompileState(int value) {
             this.value = value;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Nov 29 10:02:07 2019 +0000
@@ -255,6 +255,41 @@
         }
     }
 
+    public boolean aliveAfter(Env<AttrContext> env, JCTree that, TreeMaker make) {
+        //we need to disable diagnostics temporarily; the problem is that if
+        //"that" contains e.g. an unreachable statement, an error
+        //message will be reported and will cause compilation to skip the flow analyis
+        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
+        //related errors, which will allow for more errors to be detected
+        Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
+        try {
+            SnippetAliveAnalyzer analyzer = new SnippetAliveAnalyzer();
+
+            analyzer.analyzeTree(env, that, make);
+            return analyzer.isAlive();
+        } finally {
+            log.popDiagnosticHandler(diagHandler);
+        }
+    }
+
+    public boolean breaksOutOf(Env<AttrContext> env, JCTree loop, JCTree body, TreeMaker make) {
+        //we need to disable diagnostics temporarily; the problem is that if
+        //"that" contains e.g. an unreachable statement, an error
+        //message will be reported and will cause compilation to skip the flow analyis
+        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
+        //related errors, which will allow for more errors to be detected
+        Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
+        try {
+            boolean[] breaksOut = new boolean[1];
+            SnippetBreakAnalyzer analyzer = new SnippetBreakAnalyzer(loop);
+
+            analyzer.analyzeTree(env, body, make);
+            return analyzer.breaksOut();
+        } finally {
+            log.popDiagnosticHandler(diagHandler);
+        }
+    }
+
     /**
      * Definite assignment scan mode
      */
@@ -1467,6 +1502,38 @@
     }
 
     /**
+     * Determine if alive after the given tree.
+     */
+    class SnippetAliveAnalyzer extends AliveAnalyzer {
+        @Override
+        public void visitClassDef(JCClassDecl tree) {
+            //skip
+        }
+        public boolean isAlive() {
+            return super.alive != Liveness.DEAD;
+        }
+    }
+
+    class SnippetBreakAnalyzer extends AliveAnalyzer {
+        private final JCTree loop;
+        private boolean breaksOut;
+
+        public SnippetBreakAnalyzer(JCTree loop) {
+            this.loop = loop;
+        }
+
+        @Override
+        public void visitBreak(JCBreak tree) {
+            breaksOut |= (super.alive == Liveness.ALIVE && tree.target == loop);
+            super.visitBreak(tree);
+        }
+
+        public boolean breaksOut() {
+            return breaksOut;
+        }
+    }
+
+    /**
      * Specialized pass that performs DA/DU on a lambda
      */
     class LambdaAssignAnalyzer extends AssignAnalyzer {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,216 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.comp;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCConditional;
+import com.sun.tools.javac.tree.JCTree.JCUnary;
+import com.sun.tools.javac.tree.JCTree.JCBindingPattern;
+import com.sun.tools.javac.tree.TreeScanner;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+
+
+public class MatchBindingsComputer extends TreeScanner {
+    protected static final Context.Key<MatchBindingsComputer> matchBindingsComputerKey = new Context.Key<>();
+
+    private final Log log;
+    private final Types types;
+    boolean whenTrue;
+    List<BindingSymbol> bindings;
+
+    public static MatchBindingsComputer instance(Context context) {
+        MatchBindingsComputer instance = context.get(matchBindingsComputerKey);
+        if (instance == null)
+            instance = new MatchBindingsComputer(context);
+        return instance;
+    }
+
+    protected MatchBindingsComputer(Context context) {
+        this.log = Log.instance(context);
+        this.types = Types.instance(context);
+    }
+
+    public List<BindingSymbol> getMatchBindings(JCTree expression, boolean whenTrue) {
+        this.whenTrue = whenTrue;
+        this.bindings = List.nil();
+        scan(expression);
+        return bindings;
+    }
+
+    @Override
+    public void visitBindingPattern(JCBindingPattern tree) {
+        bindings = whenTrue ? List.of(tree.symbol) : List.nil();
+    }
+
+    @Override
+    public void visitBinary(JCBinary tree) {
+        switch (tree.getTag()) {
+            case AND:
+                // e.T = union(x.T, y.T)
+                // e.F = intersection(x.F, y.F)
+                scan(tree.lhs);
+                List<BindingSymbol> lhsBindings = bindings;
+                scan(tree.rhs);
+                List<BindingSymbol> rhsBindings = bindings;
+                bindings = whenTrue ? union(tree, lhsBindings, rhsBindings) : intersection(tree, lhsBindings, rhsBindings);
+                break;
+            case OR:
+                // e.T = intersection(x.T, y.T)
+                // e.F = union(x.F, y.F)
+                scan(tree.lhs);
+                lhsBindings = bindings;
+                scan(tree.rhs);
+                rhsBindings = bindings;
+                bindings = whenTrue ? intersection(tree, lhsBindings, rhsBindings) : union(tree, lhsBindings, rhsBindings);
+                break;
+            default:
+                super.visitBinary(tree);
+                break;
+        }
+    }
+
+    @Override
+    public void visitUnary(JCUnary tree) {
+        switch (tree.getTag()) {
+            case NOT:
+                // e.T = x.F  // flip 'em
+                // e.F = x.T
+                whenTrue = !whenTrue;
+                scan(tree.arg);
+                whenTrue = !whenTrue;
+                break;
+            default:
+                super.visitUnary(tree);
+                break;
+        }
+    }
+
+    @Override
+    public void visitConditional(JCConditional tree) {
+        /* if e = "x ? y : z", then:
+               e.T = union(intersect(y.T, z.T), intersect(x.T, z.T), intersect(x.F, y.T))
+               e.F = union(intersect(y.F, z.F), intersect(x.T, z.F), intersect(x.F, y.F))
+        */
+        if (whenTrue) {
+            List<BindingSymbol> xT, yT, zT, xF;
+            scan(tree.cond);
+            xT = bindings;
+            scan(tree.truepart);
+            yT = bindings;
+            scan(tree.falsepart);
+            zT = bindings;
+            whenTrue = false;
+            scan(tree.cond);
+            xF = bindings;
+            whenTrue = true;
+            bindings = union(tree, intersection(tree, yT, zT), intersection(tree, xT, zT), intersection(tree, xF, yT));
+        } else {
+            List<BindingSymbol> xF, yF, zF, xT;
+            scan(tree.cond);
+            xF = bindings;
+            scan(tree.truepart);
+            yF = bindings;
+            scan(tree.falsepart);
+            zF = bindings;
+            whenTrue = true;
+            scan(tree.cond);
+            xT = bindings;
+            whenTrue = false;
+            bindings = union(tree, intersection(tree, yF, zF), intersection(tree, xT, zF), intersection(tree, xF, yF));
+        }
+    }
+
+    private List<BindingSymbol> intersection(JCTree tree, List<BindingSymbol> lhsBindings, List<BindingSymbol> rhsBindings) {
+        // It is an error if, for intersection(a,b), if a and b contain the same variable name (may be eventually relaxed to merge variables of same type)
+        List<BindingSymbol> list = List.nil();
+        for (BindingSymbol v1 : lhsBindings) {
+            for (BindingSymbol v2 : rhsBindings) {
+                if (v1.name == v2.name) {
+                    log.error(tree.pos(), Errors.MatchBindingExists);
+                    list = list.append(v2);
+                }
+            }
+        }
+        return list;
+    }
+
+    @SafeVarargs
+    private final List<BindingSymbol> union(JCTree tree, List<BindingSymbol> lhsBindings, List<BindingSymbol> ... rhsBindings_s) {
+        // It is an error if for union(a,b), a and b contain the same name (disjoint union).
+        List<BindingSymbol> list = lhsBindings;
+        for (List<BindingSymbol> rhsBindings : rhsBindings_s) {
+            for (BindingSymbol v : rhsBindings) {
+                for (BindingSymbol ov : list) {
+                    if (ov.name == v.name) {
+                        log.error(tree.pos(), Errors.MatchBindingExists);
+                    }
+                }
+                list = list.append(v);
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public void scan(JCTree tree) {
+        bindings = List.nil();
+        super.scan(tree);
+    }
+
+    public static class BindingSymbol extends VarSymbol {
+
+        public BindingSymbol(Name name, Type type, Symbol owner) {
+            super(Flags.FINAL | Flags.HASINIT | Flags.MATCH_BINDING, name, type, owner);
+        }
+
+        public boolean isAliasFor(BindingSymbol b) {
+            return aliases().containsAll(b.aliases());
+        }
+
+        List<BindingSymbol> aliases() {
+            return List.of(this);
+        }
+
+        public void preserveBinding() {
+            flags_field |= Flags.MATCH_BINDING_TO_OUTER;
+        }
+
+        public boolean isPreserved() {
+            return (flags_field & Flags.MATCH_BINDING_TO_OUTER) != 0;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,457 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.comp;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAssign;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCConditional;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCForLoop;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCIf;
+import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
+import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.JCBindingPattern;
+import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
+import com.sun.tools.javac.tree.JCTree.Tag;
+import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.tree.TreeTranslator;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.Options;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
+import static com.sun.tools.javac.code.TypeTag.BOT;
+import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol;
+import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.LetExpr;
+import com.sun.tools.javac.util.List;
+
+/**
+ * This pass translates pattern-matching constructs, such as instanceof <pattern>.
+ */
+public class TransPatterns extends TreeTranslator {
+
+    protected static final Context.Key<TransPatterns> transPatternsKey = new Context.Key<>();
+
+    public static TransPatterns instance(Context context) {
+        TransPatterns instance = context.get(transPatternsKey);
+        if (instance == null)
+            instance = new TransPatterns(context);
+        return instance;
+    }
+
+    private final Symtab syms;
+    private final Types types;
+    private final Operators operators;
+    private final Log log;
+    private final ConstFold constFold;
+    private final Names names;
+    private final Target target;
+    private final MatchBindingsComputer matchBindingsComputer;
+    private TreeMaker make;
+
+    BindingContext bindingContext = new BindingContext() {
+        @Override
+        VarSymbol getBindingFor(BindingSymbol varSymbol) {
+            return null;
+        }
+
+        @Override
+        JCStatement decorateStatement(JCStatement stat) {
+            return stat;
+        }
+
+        @Override
+        JCExpression decorateExpression(JCExpression expr) {
+            return expr;
+        }
+
+        @Override
+        BindingContext pop() {
+            //do nothing
+            return this;
+        }
+
+        @Override
+        boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) {
+            return false;
+        }
+    };
+
+    JCLabeledStatement pendingMatchLabel = null;
+
+    boolean debugTransPatterns;
+
+    private MethodSymbol currentMethodSym = null;
+
+    protected TransPatterns(Context context) {
+        context.put(transPatternsKey, this);
+        syms = Symtab.instance(context);
+        make = TreeMaker.instance(context);
+        types = Types.instance(context);
+        operators = Operators.instance(context);
+        log = Log.instance(context);
+        constFold = ConstFold.instance(context);
+        names = Names.instance(context);
+        target = Target.instance(context);
+        matchBindingsComputer = MatchBindingsComputer.instance(context);
+        debugTransPatterns = Options.instance(context).isSet("debug.patterns");
+    }
+
+    @Override
+    public void visitTypeTest(JCInstanceOf tree) {
+        if (tree.pattern.hasTag(Tag.BINDINGPATTERN)) {
+            //E instanceof T N
+            //=>
+            //(let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp))
+            JCBindingPattern patt = (JCBindingPattern)tree.pattern;
+            VarSymbol pattSym = patt.symbol;
+            Type tempType = tree.expr.type.hasTag(BOT) ?
+                    syms.objectType
+                    : tree.expr.type;
+            VarSymbol temp = new VarSymbol(pattSym.flags() | Flags.SYNTHETIC,
+                    names.fromString(pattSym.name.toString() + target.syntheticNameChar() + "temp"),
+                    tempType,
+                    patt.symbol.owner);
+            JCExpression translatedExpr = translate(tree.expr);
+            Type castTargetType = types.boxedTypeOrType(pattSym.erasure(types));
+
+            result = makeTypeTest(make.Ident(temp), make.Type(castTargetType));
+
+            VarSymbol bindingVar = bindingContext.getBindingFor(patt.symbol);
+            if (bindingVar != null) {
+                JCAssign fakeInit = (JCAssign)make.at(tree.pos).Assign(
+                        make.Ident(bindingVar), convert(make.Ident(temp), castTargetType)).setType(bindingVar.erasure(types));
+                result = makeBinary(Tag.AND, (JCExpression)result,
+                        makeBinary(Tag.EQ, fakeInit, convert(make.Ident(temp), castTargetType)));
+            }
+            result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType);
+            ((LetExpr) result).needsCond = true;
+        } else {
+            super.visitTypeTest(tree);
+        }
+    }
+
+    @Override
+    public void visitBinary(JCBinary tree) {
+        List<BindingSymbol> matchBindings;
+        switch (tree.getTag()) {
+            case AND:
+                matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, true);
+                break;
+            case OR:
+                matchBindings = matchBindingsComputer.getMatchBindings(tree.lhs, false);
+                break;
+            default:
+                matchBindings = List.nil();
+                break;
+        }
+
+        bindingContext = new BasicBindingContext(matchBindings);
+        try {
+            super.visitBinary(tree);
+            result = bindingContext.decorateExpression(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitConditional(JCConditional tree) {
+        bindingContext = new BasicBindingContext(
+                matchBindingsComputer.getMatchBindings(tree.cond, true)
+                        .appendList(matchBindingsComputer.getMatchBindings(tree.cond, false)));
+        try {
+            super.visitConditional(tree);
+            result = bindingContext.decorateExpression(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitIf(JCIf tree) {
+        bindingContext = new BasicBindingContext(getMatchBindings(tree.cond));
+        try {
+            super.visitIf(tree);
+            result = bindingContext.decorateStatement(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitForLoop(JCForLoop tree) {
+        bindingContext = new BasicBindingContext(getMatchBindings(tree.cond));
+        try {
+            super.visitForLoop(tree);
+            result = bindingContext.decorateStatement(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitWhileLoop(JCWhileLoop tree) {
+        bindingContext = new BasicBindingContext(getMatchBindings(tree.cond));
+        try {
+            super.visitWhileLoop(tree);
+            result = bindingContext.decorateStatement(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitDoLoop(JCDoWhileLoop tree) {
+        bindingContext = new BasicBindingContext(getMatchBindings(tree.cond));
+        try {
+            super.visitDoLoop(tree);
+            result = bindingContext.decorateStatement(tree);
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    @Override
+    public void visitMethodDef(JCMethodDecl tree) {
+        MethodSymbol prevMethodSym = currentMethodSym;
+        try {
+            currentMethodSym = tree.sym;
+            super.visitMethodDef(tree);
+        } finally {
+            currentMethodSym = prevMethodSym;
+        }
+    }
+
+    @Override
+    public void visitIdent(JCIdent tree) {
+        VarSymbol bindingVar = null;
+        if ((tree.sym.flags() & Flags.MATCH_BINDING) != 0) {
+            bindingVar = bindingContext.getBindingFor((BindingSymbol)tree.sym);
+        }
+        if (bindingVar == null) {
+            super.visitIdent(tree);
+        } else {
+            result = make.at(tree.pos).Ident(bindingVar);
+        }
+    }
+
+    @Override
+    public void visitBlock(JCBlock tree) {
+        ListBuffer<JCStatement> statements = new ListBuffer<>();
+        bindingContext = new BasicBindingContext(List.nil()) {
+            boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) {
+                //{
+                //    if (E instanceof T N) {
+                //        return ;
+                //    }
+                //    //use of N:
+                //}
+                //=>
+                //{
+                //    T N;
+                //    if ((let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp))) {
+                //        return ;
+                //    }
+                //    //use of N:
+                //}
+                hoistedVarMap.put(binding, var.sym);
+                statements.append(var);
+                return true;
+            }
+        };
+        try {
+            for (List<JCStatement> l = tree.stats; l.nonEmpty(); l = l.tail) {
+                statements.append(translate(l.head));
+            }
+
+            tree.stats = statements.toList();
+            result = tree;
+        } finally {
+            bindingContext.pop();
+        }
+    }
+
+    public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
+        try {
+            this.make = make;
+            translate(cdef);
+        } finally {
+            // note that recursive invocations of this method fail hard
+            this.make = null;
+        }
+
+        return cdef;
+    }
+
+    /** Make an instanceof expression.
+     *  @param lhs      The expression.
+     *  @param type     The type to be tested.
+     */
+
+    JCInstanceOf makeTypeTest(JCExpression lhs, JCExpression type) {
+        JCInstanceOf tree = make.TypeTest(lhs, type);
+        tree.type = syms.booleanType;
+        return tree;
+    }
+
+    /** Make an attributed binary expression (copied from Lower).
+     *  @param optag    The operators tree tag.
+     *  @param lhs      The operator's left argument.
+     *  @param rhs      The operator's right argument.
+     */
+    JCBinary makeBinary(JCTree.Tag optag, JCExpression lhs, JCExpression rhs) {
+        JCBinary tree = make.Binary(optag, lhs, rhs);
+        tree.operator = operators.resolveBinary(tree, optag, lhs.type, rhs.type);
+        tree.type = tree.operator.type.getReturnType();
+        return tree;
+    }
+
+    JCExpression convert(JCExpression expr, Type target) {
+        JCExpression result = make.at(expr.pos()).TypeCast(make.Type(target), expr);
+        result.type = target;
+        return result;
+    }
+
+    private List<BindingSymbol> getMatchBindings(JCExpression cond) {
+        return matchBindingsComputer.getMatchBindings(cond, true)
+                        .appendList(matchBindingsComputer.getMatchBindings(cond, false));
+    }
+    abstract class BindingContext {
+        abstract VarSymbol getBindingFor(BindingSymbol varSymbol);
+        abstract JCStatement decorateStatement(JCStatement stat);
+        abstract JCExpression decorateExpression(JCExpression expr);
+        abstract BindingContext pop();
+        abstract boolean tryPrepend(BindingSymbol binding, JCVariableDecl var);
+    }
+
+    class BasicBindingContext extends BindingContext {
+        List<BindingSymbol> matchBindings;
+        Map<BindingSymbol, VarSymbol> hoistedVarMap;
+        BindingContext parent;
+
+        public BasicBindingContext(List<BindingSymbol> matchBindings) {
+            this.matchBindings = matchBindings;
+            this.parent = bindingContext;
+            this.hoistedVarMap = matchBindings.stream()
+                    .filter(v -> parent.getBindingFor(v) == null)
+                    .collect(Collectors.toMap(v -> v, v -> {
+                        VarSymbol res = new VarSymbol(v.flags(), v.name, v.type, v.owner);
+                        res.setTypeAttributes(v.getRawTypeAttributes());
+                        return res;
+                    }));
+        }
+
+        @Override
+        VarSymbol getBindingFor(BindingSymbol varSymbol) {
+            VarSymbol res = parent.getBindingFor(varSymbol);
+            if (res != null) {
+                return res;
+            }
+            return hoistedVarMap.entrySet().stream()
+                    .filter(e -> e.getKey().isAliasFor(varSymbol))
+                    .findFirst()
+                    .map(e -> e.getValue()).orElse(null);
+        }
+
+        @Override
+        JCStatement decorateStatement(JCStatement stat) {
+            if (hoistedVarMap.isEmpty()) return stat;
+            //if (E instanceof T N) {
+            //     //use N
+            //}
+            //=>
+            //{
+            //    T N;
+            //    if ((let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp))) {
+            //        //use N
+            //    }
+            //}
+            ListBuffer<JCStatement> stats = new ListBuffer<>();
+            for (Entry<BindingSymbol, VarSymbol> e : hoistedVarMap.entrySet()) {
+                JCVariableDecl decl = makeHoistedVarDecl(stat.pos, e.getValue());
+                if (!e.getKey().isPreserved() ||
+                    !parent.tryPrepend(e.getKey(), decl)) {
+                    stats.add(decl);
+                }
+            }
+            if (stats.nonEmpty()) {
+                stats.add(stat);
+                stat = make.at(stat.pos).Block(0, stats.toList());
+            }
+            return stat;
+        }
+
+        @Override
+        JCExpression decorateExpression(JCExpression expr) {
+            //E instanceof T N && /*use of N*/
+            //=>
+            //(let T N; (let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp)) && /*use of N*/)
+            for (VarSymbol vsym : hoistedVarMap.values()) {
+                expr = make.at(expr.pos).LetExpr(makeHoistedVarDecl(expr.pos, vsym), expr).setType(expr.type);
+            }
+            return expr;
+        }
+
+        @Override
+        BindingContext pop() {
+            return bindingContext = parent;
+        }
+
+        @Override
+        boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) {
+            return false;
+        }
+
+        private JCVariableDecl makeHoistedVarDecl(int pos, VarSymbol varSymbol) {
+            return make.at(pos).VarDef(varSymbol, null);
+        }
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Nov 29 10:02:07 2019 +0000
@@ -567,6 +567,13 @@
         result = tree;
     }
 
+    public void visitBindingPattern(JCBindingPattern tree) {
+        if (tree.vartype != null) {
+            tree.vartype = translate(tree.vartype, null);
+        }
+        result = tree;
+    }
+
     public void visitSwitchExpression(JCSwitchExpression tree) {
         Type selsuper = types.supertype(tree.selector.type);
         boolean enumSwitch = selsuper != null &&
@@ -780,7 +787,7 @@
 
     public void visitTypeTest(JCInstanceOf tree) {
         tree.expr = translate(tree.expr, null);
-        tree.clazz = translate(tree.clazz, null);
+        tree.pattern = translate(tree.pattern, null);
         result = tree;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
 import com.sun.tools.javac.tree.JCTree.JCAssign;
 import com.sun.tools.javac.tree.JCTree.JCAssignOp;
 import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCBindingPattern;
 import com.sun.tools.javac.tree.JCTree.JCBlock;
 import com.sun.tools.javac.tree.JCTree.JCBreak;
 import com.sun.tools.javac.tree.JCTree.JCCase;
@@ -253,6 +254,18 @@
     }
 
     @Override
+    public void visitBindingPattern(JCBindingPattern tree) {
+        JCBindingPattern that = (JCBindingPattern) parameter;
+        result =
+                scan(tree.vartype, that.vartype)
+                        && tree.name == that.name;
+        if (!result) {
+            return;
+        }
+        equiv.put(tree.symbol, that.symbol);
+    }
+
+    @Override
     public void visitBlock(JCBlock tree) {
         JCBlock that = (JCBlock) parameter;
         result = tree.flags == that.flags && scan(tree.stats, that.stats);
@@ -591,7 +604,7 @@
     @Override
     public void visitTypeTest(JCInstanceOf tree) {
         JCInstanceOf that = (JCInstanceOf) parameter;
-        result = scan(tree.expr, that.expr) && scan(tree.clazz, that.clazz);
+        result = scan(tree.expr, that.expr) && scan(tree.pattern, that.pattern);
     }
 
     @Override
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeHasher.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeHasher.java	Fri Nov 29 10:02:07 2019 +0000
@@ -106,6 +106,12 @@
     }
 
     @Override
+    public void visitBindingPattern(JCTree.JCBindingPattern tree) {
+        symbolHashes.computeIfAbsent(tree.symbol, k -> symbolHashes.size());
+        super.visitBindingPattern(tree);
+    }
+
+    @Override
     public void visitVarDef(JCVariableDecl tree) {
         symbolHashes.computeIfAbsent(tree.sym, k -> symbolHashes.size());
         super.visitVarDef(tree);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java	Fri Nov 29 10:02:07 2019 +0000
@@ -473,7 +473,7 @@
         public void visitTypeTest(JCInstanceOf tree) {
             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
             sr.mergeWith(csp(tree.expr));
-            sr.mergeWith(csp(tree.clazz));
+            sr.mergeWith(csp(tree.pattern));
             result = sr;
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -50,6 +50,7 @@
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
 import static com.sun.tools.javac.jvm.UninitializedType.*;
 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
+import java.util.Arrays;
 
 /** An internal structure that corresponds to the code attribute of
  *  methods in a classfile. The class also provides some utility operations to
@@ -2075,6 +2076,7 @@
                 lvar[adr] = v.dup();
                 v.closeRange(length);
                 putVar(v);
+                fillLocalVarPosition(v);
             } else {
                 v.removeLastRange();
             }
@@ -2106,20 +2108,31 @@
     private void fillLocalVarPosition(LocalVar lv) {
         if (lv == null || lv.sym == null || lv.sym.isExceptionParameter()|| !lv.sym.hasTypeAnnotations())
             return;
-        LocalVar.Range widestRange = lv.getWidestRange();
+        LocalVar.Range[] validRanges = lv.aliveRanges.stream().filter(r -> r.closed() && r.length > 0).toArray(s -> new LocalVar.Range[s]);
+        if (validRanges.length == 0)
+            return ;
+        int[] lvarOffset = Arrays.stream(validRanges).mapToInt(r -> r.start_pc).toArray();
+        int[] lvarLength = Arrays.stream(validRanges).mapToInt(r -> r.length).toArray();
+        int[] lvarIndex = Arrays.stream(validRanges).mapToInt(r -> lv.reg).toArray();
         for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
             TypeAnnotationPosition p = ta.position;
-            if (widestRange.closed() && widestRange.length > 0) {
-                p.lvarOffset = new int[] { (int)widestRange.start_pc };
-                p.lvarLength = new int[] { (int)widestRange.length };
-                p.lvarIndex = new int[] { (int)lv.reg };
-                p.isValidOffset = true;
-            } else {
-                p.isValidOffset = false;
-            }
+            p.lvarOffset = appendArray(p.lvarOffset, lvarOffset);
+            p.lvarLength = appendArray(p.lvarLength, lvarLength);
+            p.lvarIndex = appendArray(p.lvarIndex, lvarIndex);
+            p.isValidOffset = true;
         }
     }
 
+    private int[] appendArray(int[] source, int[] append) {
+        if (source == null || source.length == 0) return append;
+
+        int[] result = new int[source.length + append.length];
+
+        System.arraycopy(source, 0, result, 0, source.length);
+        System.arraycopy(append, 0, result, source.length, append.length);
+        return result;
+    }
+
     // Method to be called after compressCatchTable to
     // fill in the exception table index for type
     // annotations on exception parameters.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Nov 29 10:02:07 2019 +0000
@@ -2216,7 +2216,7 @@
     public void visitTypeTest(JCInstanceOf tree) {
         genExpr(tree.expr, tree.expr.type).load();
         setTypeAnnotationPositions(tree.pos);
-        code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
+        code.emitop2(instanceof_, makeRef(tree.pos(), tree.pattern.type));
         result = items.makeStackItem(syms.booleanType);
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -1558,6 +1558,12 @@
             env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
             compileStates.put(env, CompileState.TRANSTYPES);
 
+            if (shouldStop(CompileState.TRANSPATTERNS))
+                return;
+
+            env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
+            compileStates.put(env, CompileState.TRANSPATTERNS);
+
             if (Feature.LAMBDA.allowedInSource(source) && scanner.hasLambdas) {
                 if (shouldStop(CompileState.UNLAMBDA))
                     return;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Nov 29 10:02:07 2019 +0000
@@ -893,6 +893,7 @@
 
     /*  Expression2Rest = {infixop Expression3}
      *                  | Expression3 instanceof Type
+     *                  | Expression3 instanceof Pattern
      *  infixop         = "||"
      *                  | "&&"
      *                  | "|"
@@ -915,13 +916,24 @@
         Token topOp = Tokens.DUMMY;
         while (prec(token.kind) >= minprec) {
             opStack[top] = topOp;
-            top++;
-            topOp = token;
-            nextToken();
-            odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
+
+            if (token.kind == INSTANCEOF) {
+                int pos = token.pos;
+                nextToken();
+                JCTree pattern = parseType();
+                if (token.kind == IDENTIFIER) {
+                    checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
+                    pattern = toP(F.at(token.pos).BindingPattern(ident(), pattern));
+                }
+                odStack[top] = F.at(pos).TypeTest(odStack[top], pattern);
+            } else {
+                topOp = token;
+                nextToken();
+                top++;
+                odStack[top] = term3();
+            }
             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
-                odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
-                                        odStack[top]);
+                odStack[top - 1] = F.at(topOp.pos).Binary(optag(topOp.kind), odStack[top - 1], odStack[top]);
                 top--;
                 topOp = opStack[top];
             }
@@ -938,19 +950,6 @@
         return t;
     }
     //where
-        /** Construct a binary or type test node.
-         */
-        private JCExpression makeOp(int pos,
-                                    TokenKind topOp,
-                                    JCExpression od1,
-                                    JCExpression od2)
-        {
-            if (topOp == INSTANCEOF) {
-                return F.at(pos).TypeTest(od1, od2);
-            } else {
-                return F.at(pos).Binary(optag(topOp), od1, od2);
-            }
-        }
         /** If tree is a concatenation of string literals, replace it
          *  by a single literal representing the concatenated string.
          */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Nov 29 10:02:07 2019 +0000
@@ -546,6 +546,10 @@
     auto-closeable resource {0} may not be assigned
 
 # 0: symbol
+compiler.err.pattern.binding.may.not.be.assigned=\
+    pattern binding {0} may not be assigned
+
+# 0: symbol
 compiler.err.multicatch.parameter.may.not.be.assigned=\
     multi-catch parameter {0} may not be assigned
 
@@ -1416,6 +1420,10 @@
 compiler.misc.varargs.trustme.on.reifiable.varargs=\
     Varargs element type {0} is reifiable.
 
+# 0: type, 1: type
+compiler.err.instanceof.reifiable.not.safe=\
+    {0} cannot be safely cast to {1}
+
 # 0: symbol
 compiler.misc.varargs.trustme.on.non.varargs.meth=\
     Method {0} is not a varargs method.
@@ -2909,6 +2917,12 @@
 compiler.misc.feature.var.syntax.in.implicit.lambda=\
     var syntax in implicit lambdas
 
+compiler.misc.feature.pattern.matching.instanceof=\
+    pattern matching in instanceof
+
+compiler.misc.feature.reifiable.types.instanceof=\
+    reifiable types in instanceof
+
 compiler.warn.underscore.as.identifier=\
     as of release 9, ''_'' is a keyword, and may not be used as an identifier
 
@@ -3399,6 +3413,9 @@
 compiler.err.illegal.argument.for.option=\
     illegal argument for {0}: {1}
 
+compiler.err.match.binding.exists=\
+    illegal attempt to redefine an existing match binding
+
 compiler.err.switch.null.not.allowed=\
     null label in case is not allowed
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.MatchBindingsComputer.BindingSymbol;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -238,6 +239,10 @@
          */
         TYPETEST,
 
+        /** Patterns.
+         */
+        BINDINGPATTERN,
+
         /** Indexed array expressions, of type Indexed.
          */
         INDEXED,
@@ -2135,10 +2140,10 @@
      */
     public static class JCInstanceOf extends JCExpression implements InstanceOfTree {
         public JCExpression expr;
-        public JCTree clazz;
-        protected JCInstanceOf(JCExpression expr, JCTree clazz) {
+        public JCTree pattern;
+        protected JCInstanceOf(JCExpression expr, JCTree pattern) {
             this.expr = expr;
-            this.clazz = clazz;
+            this.pattern = pattern;
         }
         @Override
         public void accept(Visitor v) { v.visitTypeTest(this); }
@@ -2146,7 +2151,13 @@
         @DefinedBy(Api.COMPILER_TREE)
         public Kind getKind() { return Kind.INSTANCE_OF; }
         @DefinedBy(Api.COMPILER_TREE)
-        public JCTree getType() { return clazz; }
+        public JCTree getType() { return pattern instanceof JCPattern ? pattern.hasTag(BINDINGPATTERN) ? ((JCBindingPattern) pattern).vartype : null : pattern; }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public JCPattern getPattern() {
+            return pattern instanceof JCPattern ? (JCPattern) pattern : null;
+        }
+
         @DefinedBy(Api.COMPILER_TREE)
         public JCExpression getExpression() { return expr; }
         @Override @DefinedBy(Api.COMPILER_TREE)
@@ -2160,6 +2171,60 @@
     }
 
     /**
+     * Pattern matching forms.
+     */
+    public static abstract class JCPattern extends JCTree
+            implements PatternTree {
+        public JCExpression constExpression() {
+            return null;
+        }
+    }
+
+    public static class JCBindingPattern extends JCPattern
+            implements BindingPatternTree {
+        public Name name;
+        public BindingSymbol symbol;
+        public JCTree vartype;
+
+        protected JCBindingPattern(Name name, BindingSymbol symbol, JCTree vartype) {
+            this.name = name;
+            this.symbol = symbol;
+            this.vartype = vartype;
+        }
+
+        @DefinedBy(Api.COMPILER_TREE)
+        public Name getBinding() {
+            return name;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Tree getType() {
+            return vartype;
+        }
+
+        @Override
+        public void accept(Visitor v) {
+            v.visitBindingPattern(this);
+        }
+
+        @DefinedBy(Api.COMPILER_TREE)
+        public Kind getKind() {
+            return Kind.BINDING_PATTERN;
+        }
+
+        @Override
+        @DefinedBy(Api.COMPILER_TREE)
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitBindingPattern(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return BINDINGPATTERN;
+        }
+    }
+
+    /**
      * An array selection
      */
     public static class JCArrayAccess extends JCExpression implements ArrayAccessTree {
@@ -3133,6 +3198,7 @@
         JCBinary Binary(Tag opcode, JCExpression lhs, JCExpression rhs);
         JCTypeCast TypeCast(JCTree expr, JCExpression type);
         JCInstanceOf TypeTest(JCExpression expr, JCTree clazz);
+        JCBindingPattern BindingPattern(Name name, JCTree vartype);
         JCArrayAccess Indexed(JCExpression indexed, JCExpression index);
         JCFieldAccess Select(JCExpression selected, Name selector);
         JCIdent Ident(Name idname);
@@ -3197,6 +3263,7 @@
         public void visitBinary(JCBinary that)               { visitTree(that); }
         public void visitTypeCast(JCTypeCast that)           { visitTree(that); }
         public void visitTypeTest(JCInstanceOf that)         { visitTree(that); }
+        public void visitBindingPattern(JCBindingPattern that) { visitTree(that); }
         public void visitIndexed(JCArrayAccess that)         { visitTree(that); }
         public void visitSelect(JCFieldAccess that)          { visitTree(that); }
         public void visitReference(JCMemberReference that)   { visitTree(that); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Fri Nov 29 10:02:07 2019 +0000
@@ -234,6 +234,14 @@
         printExprs(trees, ", ");
     }
 
+
+    /** Derived visitor method: print pattern.
+     */
+
+    public void printPattern(JCTree tree) throws IOException {
+        printExpr(tree);
+    }
+
     /** Derived visitor method: print list of statements, each on a separate line.
      */
     public void printStats(List<? extends JCTree> trees) throws IOException {
@@ -877,6 +885,16 @@
         }
     }
 
+    public void visitBindingPattern(JCBindingPattern patt) {
+        try {
+            printExpr(patt.vartype);
+            print(" ");
+            print(patt.name);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
     public void visitSynchronized(JCSynchronized tree) {
         try {
             print("synchronized ");
@@ -1283,7 +1301,11 @@
             open(prec, TreeInfo.ordPrec);
             printExpr(tree.expr, TreeInfo.ordPrec);
             print(" instanceof ");
-            printExpr(tree.clazz, TreeInfo.ordPrec + 1);
+            if (tree.pattern instanceof JCPattern) {
+                printPattern(tree.pattern);
+            } else {
+                printExpr(tree.getType(), TreeInfo.ordPrec + 1);
+            }
             close(prec, TreeInfo.ordPrec);
         } catch (IOException e) {
             throw new UncheckedIOException(e);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,6 @@
 package com.sun.tools.javac.tree;
 
 import com.sun.source.tree.*;
-import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
@@ -481,8 +480,15 @@
     public JCTree visitInstanceOf(InstanceOfTree node, P p) {
         JCInstanceOf t = (JCInstanceOf) node;
         JCExpression expr = copy(t.expr, p);
-        JCTree clazz = copy(t.clazz, p);
-        return M.at(t.pos).TypeTest(expr, clazz);
+        JCTree pattern = copy(t.pattern, p);
+        return M.at(t.pos).TypeTest(expr, pattern);
+    }
+
+    @DefinedBy(Api.COMPILER_TREE)
+    public JCTree visitBindingPattern(BindingPatternTree node, P p) {
+        JCBindingPattern t = (JCBindingPattern) node;
+        JCTree vartype = copy(t.vartype, p);
+        return M.at(t.pos).BindingPattern(t.name, vartype);
     }
 
     @DefinedBy(Api.COMPILER_TREE)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -490,6 +490,10 @@
                     return getStartPos(node.vartype);
                 }
             }
+            case BINDINGPATTERN: {
+                JCBindingPattern node = (JCBindingPattern)tree;
+                return getStartPos(node.vartype);
+            }
             case ERRONEOUS: {
                 JCErroneous node = (JCErroneous)tree;
                 if (node.errs != null && node.errs.nonEmpty())
@@ -574,7 +578,7 @@
             case TYPECAST:
                 return getEndPos(((JCTypeCast) tree).expr, endPosTable);
             case TYPETEST:
-                return getEndPos(((JCInstanceOf) tree).clazz, endPosTable);
+                return getEndPos(((JCInstanceOf) tree).pattern, endPosTable);
             case WHILELOOP:
                 return getEndPos(((JCWhileLoop) tree).body, endPosTable);
             case ANNOTATED_TYPE:
@@ -847,6 +851,8 @@
             if (node.type != null)
                 return node.type.tsym;
             return null;
+        case BINDINGPATTERN:
+            return ((JCBindingPattern) node).symbol;
         default:
             return null;
         }
@@ -1225,4 +1231,5 @@
     public static boolean isPackageInfo(JCCompilationUnit tree) {
         return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
     }
+
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Fri Nov 29 10:02:07 2019 +0000
@@ -29,7 +29,6 @@
 
 import com.sun.source.tree.CaseTree;
 import com.sun.source.tree.ModuleTree.ModuleKind;
-import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.UnresolvedClass;
 import com.sun.tools.javac.code.Symbol.*;
@@ -465,6 +464,12 @@
         return tree;
     }
 
+    public JCBindingPattern BindingPattern(Name name, JCTree vartype) {
+        JCBindingPattern tree = new JCBindingPattern(name, null, vartype);
+        tree.pos = pos;
+        return tree;
+    }
+
     public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) {
         JCArrayAccess tree = new JCArrayAccess(indexed, index);
         tree.pos = pos;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Fri Nov 29 10:02:07 2019 +0000
@@ -299,7 +299,12 @@
 
     public void visitTypeTest(JCInstanceOf tree) {
         scan(tree.expr);
-        scan(tree.clazz);
+        scan(tree.pattern);
+    }
+
+    public void visitBindingPattern(JCBindingPattern tree) {
+        if (tree.vartype != null)
+            scan(tree.vartype);
     }
 
     public void visitIndexed(JCArrayAccess tree) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Fri Nov 29 10:02:07 2019 +0000
@@ -354,7 +354,12 @@
 
     public void visitTypeTest(JCInstanceOf tree) {
         tree.expr = translate(tree.expr);
-        tree.clazz = translate(tree.clazz);
+        tree.pattern = translate(tree.pattern);
+        result = tree;
+    }
+
+    public void visitBindingPattern(JCBindingPattern tree) {
+        tree.vartype = translate(tree.vartype);
         result = tree;
     }
 
--- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -210,7 +210,7 @@
         if (timer1Enabled) {
             timer1.cancel();
         }
-        if (dispatcherThread != null) {
+        if (dispatcherThread != null && dispatcherThread != Thread.currentThread()) {
             try {
                 dispatcherThread.join();
             } catch (InterruptedException e) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -92,7 +92,7 @@
                                   IndexBuilder indexbuilder) {
         super(configuration, path);
         this.indexbuilder = indexbuilder;
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.INDEX, path);
+        this.navBar = new Navigation(null, configuration, PageMode.INDEX, path);
     }
 
     /**
@@ -419,7 +419,7 @@
      * @return a content tree for the marker anchor
      */
     public Content getMarkerAnchorForIndex(String anchorNameForIndex) {
-        return links.createAnchor(getNameForIndex(anchorNameForIndex), null);
+        return links.createAnchor(getNameForIndex(anchorNameForIndex));
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -57,12 +59,12 @@
     public AbstractOverviewIndexWriter(HtmlConfiguration configuration,
                                       DocPath filename) {
         super(configuration, filename);
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
+        this.navBar = new Navigation(null, configuration, PageMode.OVERVIEW, path);
     }
 
     /**
      * Adds the top text (from the -top option), the upper
-     * navigation bar, and then the title (from the"-title"
+     * navigation bar, and then the title (from the"-header"
      * option), at the top of page.
      *
      * @param header the documentation tree to which the navigation bar header will be added
@@ -126,16 +128,18 @@
             throws DocFileIOException {
         String windowOverview = resources.getText(title);
         Content body = getBody(getWindowTitle(windowOverview));
-        Content header = HtmlTree.HEADER();
+        Content header = new ContentBuilder();
         addNavigationBarHeader(header);
-        Content main = HtmlTree.MAIN();
+        Content main = new ContentBuilder();
         addOverviewHeader(main);
         addIndex(main);
         Content footer = HtmlTree.FOOTER();
         addNavigationBarFooter(footer);
-        body.add(header);
-        body.add(main);
-        body.add(footer);
+        body.add(new BodyContents()
+                .setHeader(header)
+                .addMainContent(main)
+                .setFooter(footer)
+                .toContent());
         printHtmlDocument(
                 configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
                 description, body);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -31,6 +31,7 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -56,13 +57,6 @@
     protected IndexBuilder indexbuilder;
 
     /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    private final Navigation navBar;
-
-    /**
      * Construct AllClassesIndexWriter object. Also initializes the indexbuilder variable in this
      * class.
      *
@@ -74,7 +68,6 @@
             DocPath filename, IndexBuilder indexbuilder) {
         super(configuration, filename);
         this.indexbuilder = indexbuilder;
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.ALLCLASSES, path);
     }
 
     /**
@@ -101,21 +94,25 @@
      */
     protected void buildAllClassesFile() throws DocFileIOException {
         String label = resources.getText("doclet.All_Classes");
-        HtmlTree bodyTree = getBody(getWindowTitle(label));
-        HtmlTree header = HtmlTree.HEADER();
+        Content header = new ContentBuilder();
         addTop(header);
+        Navigation navBar = new Navigation(null, configuration, PageMode.ALLCLASSES, path);
         navBar.setUserHeader(getUserHeaderFooter(true));
         header.add(navBar.getContent(true));
-        bodyTree.add(header);
         Content allClassesContent = new ContentBuilder();
         addContents(allClassesContent);
-        mainTree.add(allClassesContent);
-        bodyTree.add(mainTree);
+        Content mainContent = new ContentBuilder();
+        mainContent.add(allClassesContent);
         Content footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        bodyTree.add(footer);
+        HtmlTree bodyTree = getBody(getWindowTitle(label));
+        bodyTree.add(new BodyContents()
+                .setHeader(header)
+                .addMainContent(mainContent)
+                .setFooter(footer)
+                .toContent());
         printHtmlDocument(null, "class index", bodyTree);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,7 @@
 
 import javax.lang.model.element.PackageElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -46,13 +47,6 @@
 public class AllPackagesIndexWriter extends HtmlDocletWriter {
 
     /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    private final Navigation navBar;
-
-    /**
      * Construct AllPackagesIndexWriter object.
      *
      * @param configuration The current configuration
@@ -60,7 +54,6 @@
      */
     public AllPackagesIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.ALLPACKAGES, path);
     }
 
     /**
@@ -83,12 +76,11 @@
      */
     protected void buildAllPackagesFile() throws DocFileIOException {
         String label = resources.getText("doclet.All_Packages");
-        HtmlTree bodyTree = getBody(getWindowTitle(label));
-        HtmlTree header = HtmlTree.HEADER();
-        addTop(header);
+        Content headerContent = new ContentBuilder();
+        Navigation navBar = new Navigation(null, configuration, PageMode.ALLPACKAGES, path);
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        header.add(navBar.getContent(true));
-        bodyTree.add(header);
+        headerContent.add(navBar.getContent(true));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.allPackagesContainer);
         addPackages(div);
@@ -96,14 +88,17 @@
         Content pHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
                 HtmlStyle.title, titleContent);
         Content headerDiv = HtmlTree.DIV(HtmlStyle.header, pHeading);
-        mainTree.add(headerDiv);
-        mainTree.add(div);
-        bodyTree.add(mainTree);
         Content footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        bodyTree.add(footer);
+        HtmlTree bodyTree = getBody(getWindowTitle(label));
+        bodyTree.add(new BodyContents()
+                .setHeader(headerContent)
+                .addMainContent(headerDiv)
+                .addMainContent(div)
+                .setFooter(footer)
+                .toContent());
         printHtmlDocument(null, "package index", bodyTree);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,7 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -78,7 +79,7 @@
         super(configuration, configuration.docPaths.forClass(annotationType));
         this.annotationType = annotationType;
         configuration.currentTypeElement = annotationType;
-        this.navBar = new Navigation(annotationType, configuration, fixedNavDiv, PageMode.CLASS, path);
+        this.navBar = new Navigation(annotationType, configuration, PageMode.CLASS, path);
     }
 
     /**
@@ -86,17 +87,15 @@
      */
     @Override
     public Content getHeader(String header) {
-        HtmlTree bodyTree = getBody(getWindowTitle(utils.getSimpleName(annotationType)));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(annotationType),
                 contents.moduleLabel);
         navBar.setNavLinkModule(linkContent);
         navBar.setMemberSummaryBuilder(configuration.getBuilderFactory().getMemberSummaryBuilder(this));
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
-        bodyTree.add(MarkerComments.START_OF_CLASS_DATA);
+        headerContent.add(navBar.getContent(true));
+
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
@@ -118,13 +117,14 @@
         }
         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
                 LinkInfoImpl.Kind.CLASS_HEADER, annotationType);
-        Content headerContent = new StringContent(header);
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
-                HtmlStyle.title, headerContent);
+                HtmlStyle.title, new StringContent(header));
         heading.add(getTypeParameterLinks(linkInfo));
         div.add(heading);
-        mainTree.add(div);
-        return bodyTree;
+        bodyContents.setHeader(headerContent)
+                .addMainContent(MarkerComments.START_OF_CLASS_DATA)
+                .addMainContent(div);
+        return getBody(getWindowTitle(utils.getSimpleName(annotationType)));
     }
 
     /**
@@ -139,13 +139,13 @@
      * {@inheritDoc}
      */
     @Override
-    public void addFooter(Content contentTree) {
-        contentTree.add(MarkerComments.END_OF_CLASS_DATA);
+    public void addFooter() {
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        contentTree.add(htmlTree);
+        bodyContents.addMainContent(MarkerComments.END_OF_CLASS_DATA)
+                    .setFooter(htmlTree);
     }
 
     /**
@@ -156,6 +156,7 @@
         String description = getDescription("declaration", annotationType);
         PackageElement pkg = utils.containingPackage(this.annotationType);
         List<DocPath> localStylesheets = getLocalStylesheets(pkg);
+        contentTree.add(bodyContents.toContent());
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(annotationType),
                 description, localStylesheets, contentTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -100,11 +100,6 @@
     private final Navigation navBar;
 
     /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
      * Constructor.
      *
      * @param filename the file to be generated.
@@ -154,7 +149,7 @@
         constrSubWriter = new ConstructorWriterImpl(this);
         fieldSubWriter = new FieldWriterImpl(this);
         classSubWriter = new NestedClassWriterImpl(this);
-        this.navBar = new Navigation(typeElement, configuration, fixedNavDiv, PageMode.USE, path);
+        this.navBar = new Navigation(typeElement, configuration, PageMode.USE, path);
     }
 
     /**
@@ -232,13 +227,13 @@
             div.add(contents.getContent("doclet.ClassUse_No.usage.of.0",
                     utils.getFullyQualifiedName(typeElement)));
         }
-        mainTree.add(div);
-        body.add(mainTree);
+        bodyContents.addMainContent(div);
         HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        body.add(footer);
+        bodyContents.setFooter(footer);
+        body.add(bodyContents.toContent());
         String description = getDescription("use", typeElement);
         printHtmlDocument(null, description, body);
     }
@@ -432,8 +427,8 @@
         String title = resources.getText("doclet.Window_ClassUse_Header",
                 cltype, clname);
         HtmlTree bodyTree = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content mdleLinkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
                 contents.moduleLabel);
         navBar.setNavLinkModule(mdleLinkContent);
@@ -442,16 +437,15 @@
                 .label(resources.getText("doclet.Class")));
         navBar.setNavLinkClass(classLinkContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
-        ContentBuilder headContent = new ContentBuilder();
-        headContent.add(contents.getContent("doclet.ClassUse_Title", cltype));
-        headContent.add(new HtmlTree(HtmlTag.BR));
-        headContent.add(clname);
+        headerContent.add(navBar.getContent(true));
+        ContentBuilder headingContent = new ContentBuilder();
+        headingContent.add(contents.getContent("doclet.ClassUse_Title", cltype));
+        headingContent.add(new HtmlTree(HtmlTag.BR));
+        headingContent.add(clname);
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
-                true, HtmlStyle.title, headContent);
+                true, HtmlStyle.title, headingContent);
         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent).addMainContent(div);
         return bodyTree;
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -105,7 +105,7 @@
         this.typeElement = typeElement;
         configuration.currentTypeElement = typeElement;
         this.classtree = classTree;
-        this.navBar = new Navigation(typeElement, configuration, fixedNavDiv, PageMode.CLASS, path);
+        this.navBar = new Navigation(typeElement, configuration, PageMode.CLASS, path);
     }
 
     /**
@@ -114,16 +114,14 @@
     @Override
     public Content getHeader(String header) {
         HtmlTree bodyTree = getBody(getWindowTitle(utils.getSimpleName(typeElement)));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
                 contents.moduleLabel);
         navBar.setNavLinkModule(linkContent);
         navBar.setMemberSummaryBuilder(configuration.getBuilderFactory().getMemberSummaryBuilder(this));
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
-        bodyTree.add(MarkerComments.START_OF_CLASS_DATA);
+        headerContent.add(navBar.getContent(true));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
@@ -149,12 +147,13 @@
                 LinkInfoImpl.Kind.CLASS_HEADER, typeElement);
         //Let's not link to ourselves in the header.
         linkInfo.linkToSelf = false;
-        Content headerContent = new StringContent(header);
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
-                HtmlStyle.title, headerContent);
+                HtmlStyle.title, new StringContent(header));
         heading.add(getTypeParameterLinks(linkInfo));
         div.add(heading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent)
+                .addMainContent(MarkerComments.START_OF_CLASS_DATA)
+                .addMainContent(div);
         return bodyTree;
     }
 
@@ -170,13 +169,13 @@
      * {@inheritDoc}
      */
     @Override
-    public void addFooter(Content contentTree) {
-        contentTree.add(MarkerComments.END_OF_CLASS_DATA);
+    public void addFooter() {
+        bodyContents.addMainContent(MarkerComments.END_OF_CLASS_DATA);
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        contentTree.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
     }
 
     /**
@@ -187,6 +186,7 @@
         String description = getDescription("declaration", typeElement);
         PackageElement pkg = utils.containingPackage(typeElement);
         List<DocPath> localStylesheets = getLocalStylesheets(pkg);
+        contentTree.add(bodyContents.toContent());
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement),
                 description, localStylesheets, contentTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -33,6 +33,7 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
@@ -76,17 +77,14 @@
     private final TableHeader constantsTableHeader;
 
     /**
-     * The HTML tree for main tag.
-     */
-    private final HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
      * The HTML tree for constant values summary.
      */
     private HtmlTree summaryTree;
 
     private final Navigation navBar;
 
+    private final BodyContents bodyContents = new BodyContents();
+
     /**
      * Construct a ConstantsSummaryWriter.
      * @param configuration the configuration used in this run
@@ -97,7 +95,7 @@
         this.configuration = configuration;
         constantsTableHeader = new TableHeader(
                 contents.modifierAndTypeLabel, contents.constantFieldLabel, contents.valueLabel);
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.CONSTANTVALUES, path);
+        this.navBar = new Navigation(null, configuration, PageMode.CONSTANTVALUES, path);
     }
 
     /**
@@ -107,11 +105,11 @@
     public Content getHeader() {
         String label = resources.getText("doclet.Constants_Summary");
         HtmlTree bodyTree = getBody(getWindowTitle(label));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
+        bodyContents.setHeader(headerContent);
         return bodyTree;
     }
 
@@ -150,7 +148,7 @@
      * {@inheritDoc}
      */
     @Override
-    public void addContentsList(Content contentTree, Content contentListTree) {
+    public void addContentsList(Content contentListTree) {
         Content titleContent = contents.constantsSummaryTitle;
         Content pHeading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
                 HtmlStyle.title, titleContent);
@@ -161,7 +159,7 @@
         HtmlTree section = HtmlTree.SECTION(HtmlStyle.packages, heading);
         section.add(contentListTree);
         div.add(section);
-        mainTree.add(div);
+        bodyContents.addMainContent(div);
     }
 
     /**
@@ -303,24 +301,23 @@
      * {@inheritDoc}
      */
     @Override
-    public void addConstantSummaries(Content contentTree, Content summariesTree) {
+    public void addConstantSummaries(Content summariesTree) {
         if (summaryTree != null) {
             summariesTree.add(summaryTree);
         }
-        mainTree.add(summariesTree);
-        contentTree.add(mainTree);
+        bodyContents.addMainContent(summariesTree);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void addFooter(Content contentTree) {
+    public void addFooter() {
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        contentTree.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
     }
 
     /**
@@ -328,6 +325,7 @@
      */
     @Override
     public void printDocument(Content contentTree) throws DocFileIOException {
+        contentTree.add(bodyContents.toContent());
         printHtmlDocument(null, "summary of constants", contentTree);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -222,7 +222,7 @@
     public DeprecatedListWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
         this.configuration = configuration;
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.DEPRECATED, path);
+        this.navBar = new Navigation(null, configuration, PageMode.DEPRECATED, path);
         NestedClassWriterImpl classW = new NestedClassWriterImpl(this);
         writerMap = new EnumMap<>(DeprElementKind.class);
         for (DeprElementKind kind : DeprElementKind.values()) {
@@ -283,8 +283,7 @@
     protected void generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi)
             throws DocFileIOException {
         HtmlTree body = getHeader();
-        HtmlTree htmlTree = HtmlTree.MAIN();
-        htmlTree.add(getContentsList(deprapi));
+        bodyContents.addMainContent(getContentsList(deprapi));
         String memberTableSummary;
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.contentContainer);
@@ -300,14 +299,14 @@
                             getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
             }
         }
-        htmlTree.add(div);
-        body.add(htmlTree);
-        htmlTree = HtmlTree.FOOTER();
+        bodyContents.addMainContent(div);
+        HtmlTree htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        body.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
         String description = "deprecated elements";
+        body.add(bodyContents.toContent());
         printHtmlDocument(null, description, body);
     }
 
@@ -315,7 +314,7 @@
      * Add the index link.
      *
      * @param builder the deprecated list builder
-     * @param type the type of list being documented
+     * @param kind the kind of list being documented
      * @param contentTree the content tree to which the index link will be added
      */
     private void addIndexLink(DeprecatedAPIListBuilder builder,
@@ -353,7 +352,7 @@
      * Add the anchor.
      *
      * @param builder the deprecated list builder
-     * @param type the type of list being documented
+     * @param kind the kind of list being documented
      * @param htmlTree the content tree to which the anchor will be added
      */
     private void addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree) {
@@ -370,11 +369,11 @@
     public HtmlTree getHeader() {
         String title = resources.getText("doclet.Window_Deprecated_List");
         HtmlTree bodyTree = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
+        bodyContents.setHeader(headerContent);
         return bodyTree;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -31,6 +31,9 @@
 import com.sun.source.doctree.TextTree;
 import com.sun.source.util.DocTreeFactory;
 import com.sun.tools.doclint.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -180,32 +183,31 @@
 
         String title = getWindowTitle(docletWriter, dfElement).trim();
         HtmlTree htmlContent = docletWriter.getBody(title);
-        docletWriter.addTop(htmlContent);
         PackageElement pkg = dfElement.getPackageElement();
-        this.navBar = new Navigation(element, configuration, docletWriter.fixedNavDiv,
-                PageMode.DOCFILE, docletWriter.path);
+        this.navBar = new Navigation(element, configuration, PageMode.DOCFILE, docletWriter.path);
+        Content headerContent = new ContentBuilder();
+        docletWriter.addTop(headerContent);
         Content mdleLinkContent = docletWriter.getModuleLink(utils.elementUtils.getModuleOf(pkg),
                 docletWriter.contents.moduleLabel);
         navBar.setNavLinkModule(mdleLinkContent);
         Content pkgLinkContent = docletWriter.getPackageLink(pkg, docletWriter.contents.packageLabel);
         navBar.setNavLinkPackage(pkgLinkContent);
         navBar.setUserHeader(docletWriter.getUserHeaderFooter(true));
-        Content header = HtmlTree.HEADER();
-        header.add(navBar.getContent(true));
-        htmlContent.add(header);
+        headerContent.add(navBar.getContent(true));
 
         List<? extends DocTree> fullBody = utils.getFullBody(dfElement);
-        Content bodyContent = docletWriter.commentTagsToContent(null, dfElement, fullBody, false);
-        docletWriter.addTagsInfo(dfElement, bodyContent);
-        Content main = HtmlTree.MAIN();
-        main.add(bodyContent);
-        htmlContent.add(main);
+        Content pageContent = docletWriter.commentTagsToContent(null, dfElement, fullBody, false);
+        docletWriter.addTagsInfo(dfElement, pageContent);
 
         navBar.setUserFooter(docletWriter.getUserHeaderFooter(false));
         Content footer = HtmlTree.FOOTER();
         footer.add(navBar.getContent(false));
         docletWriter.addBottom(footer);
-        htmlContent.add(footer);
+        htmlContent.add(new BodyContents()
+                .setHeader(headerContent)
+                .addMainContent(HtmlTree.DIV(HtmlStyle.contentContainer, pageContent))
+                .setFooter(footer)
+                .toContent());
         docletWriter.printHtmlDocument(Collections.emptyList(), null, localTagsContent, Collections.emptyList(), htmlContent);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -50,8 +52,6 @@
  */
 public class HelpWriter extends HtmlDocletWriter {
 
-    HtmlTree mainTree = HtmlTree.MAIN();
-
     private final Navigation navBar;
 
     /**
@@ -62,7 +62,7 @@
     public HelpWriter(HtmlConfiguration configuration,
                       DocPath filename) {
         super(configuration, filename);
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.HELP, path);
+        this.navBar = new Navigation(null, configuration, PageMode.HELP, path);
     }
 
     /**
@@ -88,17 +88,21 @@
     protected void generateHelpFile() throws DocFileIOException {
         String title = resources.getText("doclet.Window_Help_title");
         HtmlTree body = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        body.add(htmlTree);
-        addHelpFileContents(body);
-        htmlTree = HtmlTree.FOOTER();
+        headerContent.add(navBar.getContent(true));
+        ContentBuilder helpFileContent = new ContentBuilder();
+        addHelpFileContents(helpFileContent);
+        HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
-        htmlTree.add(navBar.getContent(false));
-        addBottom(htmlTree);
-        body.add(htmlTree);
+        footer.add(navBar.getContent(false));
+        addBottom(footer);
+        body.add(new BodyContents()
+                .setHeader(headerContent)
+                .addMainContent(helpFileContent)
+                .setFooter(footer)
+                .toContent());
         printHtmlDocument(null, "help", body);
     }
 
@@ -118,7 +122,7 @@
         Content intro = HtmlTree.DIV(HtmlStyle.subTitle,
                 contents.getContent("doclet.help.intro"));
         div.add(intro);
-        mainTree.add(div);
+        contentTree.add(div);
         HtmlTree htmlTree;
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         ul.setStyle(HtmlStyle.blockList);
@@ -332,7 +336,6 @@
         Content footnote = HtmlTree.SPAN(HtmlStyle.emphasizedPhrase,
                 contents.getContent("doclet.help.footnote"));
         divContent.add(footnote);
-        mainTree.add(divContent);
-        contentTree.add(mainTree);
+        contentTree.add(divContent);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -188,8 +188,6 @@
      */
     private boolean isContainerDocumented = false;
 
-    HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV);
-
     /**
      * The window title of this file.
      */
@@ -509,7 +507,7 @@
      */
     public void addTop(Content htmlTree) {
         Content top = new RawHtml(replaceDocRootDir(configuration.top));
-        fixedNavDiv.add(top);
+        htmlTree.add(top);
     }
 
     /**
@@ -2112,29 +2110,6 @@
     }
 
     /**
-     * Returns an HtmlTree for the SCRIPT tag.
-     *
-     * @return an HtmlTree for the SCRIPT tag
-     */
-    protected Script getWinTitleScript() {
-        Script script = new Script();
-        if (winTitle != null && winTitle.length() > 0) {
-            script.append("<!--\n" +
-                    "    try {\n" +
-                    "        if (location.href.indexOf('is-external=true') == -1) {\n" +
-                    "            parent.document.title=")
-                    .appendStringLiteral(winTitle)
-                    .append(";\n" +
-                    "        }\n" +
-                    "    }\n" +
-                    "    catch(err) {\n" +
-                    "    }\n" +
-                    "//-->\n");
-        }
-        return script;
-    }
-
-    /**
      * Returns an HtmlTree for the BODY tag.
      *
      * @param title title for the window
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -42,6 +42,7 @@
 
 import com.sun.source.doctree.DocTree;
 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
@@ -161,12 +162,9 @@
     private final Map<TypeElement, Content> providesTrees
             = new TreeMap<>(utils.makeAllClassesComparator());
 
-    /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
+    private final Navigation navBar;
 
-    private final Navigation navBar;
+    private final BodyContents bodyContents = new BodyContents();
 
     /**
      * Constructor to construct ModuleWriter object and to generate "moduleName-summary.html" file.
@@ -178,7 +176,7 @@
         super(configuration, configuration.docPaths.moduleSummary(mdle));
         this.mdle = mdle;
         this.moduleMode = configuration.docEnv.getModuleMode();
-        this.navBar = new Navigation(mdle, configuration, fixedNavDiv, PageMode.MODULE, path);
+        this.navBar = new Navigation(mdle, configuration, PageMode.MODULE, path);
         computeModulesData();
     }
 
@@ -190,16 +188,15 @@
     @Override
     public Content getModuleHeader(String heading) {
         HtmlTree bodyTree = getBody(getWindowTitle(mdle.getQualifiedName().toString()));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setDisplaySummaryModuleDescLink(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment);
         navBar.setDisplaySummaryModulesLink(display(requires) || display(indirectModules));
         navBar.setDisplaySummaryPackagesLink(display(packages) || display(indirectPackages)
                 || display(indirectOpenPackages));
         navBar.setDisplaySummaryServicesLink(displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees));
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.header);
         Content annotationContent = new HtmlTree(HtmlTag.P);
@@ -213,7 +210,8 @@
         Content moduleHead = new RawHtml(heading);
         tHeading.add(moduleHead);
         div.add(tHeading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent)
+                .addMainContent(div);
         return bodyTree;
     }
 
@@ -877,21 +875,20 @@
      * {@inheritDoc}
      */
     @Override
-    public void addModuleContent(Content contentTree, Content moduleContentTree) {
-        mainTree.add(moduleContentTree);
-        contentTree.add(mainTree);
+    public void addModuleContent(Content moduleContentTree) {
+        bodyContents.addMainContent(moduleContentTree);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void addModuleFooter(Content contentTree) {
+    public void addModuleFooter() {
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        contentTree.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
     }
 
     /**
@@ -901,6 +898,7 @@
      */
     @Override
     public void printDocument(Content contentTree) throws DocFileIOException {
+        contentTree.add(bodyContents.toContent());
         printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle),
                 getDescription("declaration", mdle), getLocalStylesheets(mdle), contentTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -27,6 +27,8 @@
 
 import javax.lang.model.element.PackageElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -60,6 +62,8 @@
 
     private final Navigation navBar;
 
+    private final BodyContents bodyContents = new BodyContents();
+
     /**
      * Constructor.
      * @param configuration the configuration
@@ -70,7 +74,7 @@
         super(configuration, path,
               new ClassTree(configuration.typeElementCatalog.allClasses(packageElement), configuration));
         this.packageElement = packageElement;
-        this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.TREE, path);
+        this.navBar = new Navigation(packageElement, configuration, PageMode.TREE, path);
     }
 
     /**
@@ -97,7 +101,7 @@
      */
     protected void generatePackageTreeFile() throws DocFileIOException {
         HtmlTree body = getPackageTreeHeader();
-        HtmlTree mainTree = HtmlTree.MAIN();
+        Content mainContent = new ContentBuilder();
         Content headContent = contents.getContent("doclet.Hierarchy_For_Package",
                 utils.getPackageName(packageElement));
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, false,
@@ -106,20 +110,21 @@
         if (configuration.packages.size() > 1) {
             addLinkToMainTree(div);
         }
-        mainTree.add(div);
+        mainContent.add(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
         divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
         addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree, true);
-        mainTree.add(divTree);
-        body.add(mainTree);
+        mainContent.add(divTree);
+        bodyContents.addMainContent(mainContent);
         HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        body.add(footer);
+        bodyContents.setFooter(footer);
+        body.add(bodyContents.toContent());
         printHtmlDocument(null, getDescription("tree", packageElement), body);
     }
 
@@ -132,14 +137,14 @@
         String packageName = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement);
         String title = packageName + " " + resources.getText("doclet.Window_Class_Hierarchy");
         HtmlTree bodyTree = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
                 contents.moduleLabel);
         navBar.setNavLinkModule(linkContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
+        bodyContents.setHeader(headerContent);
         return bodyTree;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -64,7 +64,6 @@
 
     final PackageElement packageElement;
     final SortedMap<String, Set<TypeElement>> usingPackageToUsedClasses = new TreeMap<>();
-    protected HtmlTree mainTree = HtmlTree.MAIN();
     final String packageUseTableSummary;
     private final Navigation navBar;
 
@@ -104,7 +103,7 @@
 
         packageUseTableSummary = resources.getText("doclet.Use_Table_Summary",
                 resources.getText("doclet.packages"));
-        this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.USE, path);
+        this.navBar = new Navigation(packageElement, configuration, PageMode.USE, path);
     }
 
     /**
@@ -136,13 +135,13 @@
         } else {
             addPackageUse(div);
         }
-        mainTree.add(div);
-        body.add(mainTree);
+        bodyContents.addMainContent(div);
         HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        body.add(footer);
+        bodyContents.setFooter(footer);
+        body.add(bodyContents.toContent());
         printHtmlDocument(null,
                 getDescription("use", packageElement),
                 body);
@@ -242,22 +241,22 @@
         String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement);
         String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name);
         HtmlTree bodyTree = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
                 contents.moduleLabel);
         navBar.setNavLinkModule(linkContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
-        ContentBuilder headContent = new ContentBuilder();
-        headContent.add(contents.getContent("doclet.ClassUse_Title", packageText));
-        headContent.add(new HtmlTree(HtmlTag.BR));
-        headContent.add(name);
+        headerContent.add(navBar.getContent(true));
+        ContentBuilder headingContent = new ContentBuilder();
+        headingContent.add(contents.getContent("doclet.ClassUse_Title", packageText));
+        headingContent.add(new HtmlTree(HtmlTag.BR));
+        headingContent.add(name);
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
-                HtmlStyle.title, headContent);
+                HtmlStyle.title, headingContent);
         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent)
+                .addMainContent(div);
         return bodyTree;
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -33,6 +33,7 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
@@ -72,17 +73,14 @@
     protected PackageElement packageElement;
 
     /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
      * The HTML tree for section tag.
      */
     protected HtmlTree sectionTree = HtmlTree.SECTION(HtmlStyle.packageDescription, new ContentBuilder());
 
     private final Navigation navBar;
 
+    private final BodyContents bodyContents = new BodyContents();
+
     /**
      * Constructor to construct PackageWriter object and to generate
      * "package-summary.html" file in the respective package directory.
@@ -99,7 +97,7 @@
                 configuration.docPaths.forPackage(packageElement)
                 .resolve(DocPaths.PACKAGE_SUMMARY));
         this.packageElement = packageElement;
-        this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.PACKAGE, path);
+        this.navBar = new Navigation(packageElement, configuration, PageMode.PACKAGE, path);
     }
 
     /**
@@ -108,14 +106,13 @@
     @Override
     public Content getPackageHeader(String heading) {
         HtmlTree bodyTree = getBody(getWindowTitle(utils.getPackageName(packageElement)));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement),
                 contents.moduleLabel);
         navBar.setNavLinkModule(linkContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
@@ -136,7 +133,8 @@
         Content packageHead = new StringContent(heading);
         tHeading.add(packageHead);
         div.add(tHeading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent)
+                .addMainContent(div);
         return bodyTree;
     }
 
@@ -295,21 +293,20 @@
      * {@inheritDoc}
      */
     @Override
-    public void addPackageContent(Content contentTree, Content packageContentTree) {
-        mainTree.add(packageContentTree);
-        contentTree.add(mainTree);
+    public void addPackageContent(Content packageContentTree) {
+        bodyContents.addMainContent(packageContentTree);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void addPackageFooter(Content contentTree) {
+    public void addPackageFooter() {
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        contentTree.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
     }
 
     /**
@@ -319,6 +316,7 @@
     public void printDocument(Content contentTree) throws DocFileIOException {
         String description = getDescription("declaration", packageElement);
         List<DocPath> localStylesheets = getLocalStylesheets(packageElement);
+        contentTree.add(bodyContents.toContent());
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
                 description, localStylesheets, contentTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Fri Nov 29 10:02:07 2019 +0000
@@ -29,6 +29,7 @@
 
 import javax.lang.model.element.TypeElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -56,11 +57,6 @@
 
     Set<TypeElement> visibleClasses;
 
-    /**
-     * HTML tree for main tag.
-     */
-    private HtmlTree mainTree = HtmlTree.MAIN();
-
     private final Navigation navBar;
 
     /**
@@ -69,7 +65,7 @@
     public SerializedFormWriterImpl(HtmlConfiguration configuration) {
         super(configuration, DocPaths.SERIALIZED_FORM);
         visibleClasses = configuration.getIncludedTypeElements();
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.SERIALIZEDFORM, path);
+        this.navBar = new Navigation(null, configuration, PageMode.SERIALIZEDFORM, path);
     }
 
     /**
@@ -80,16 +76,16 @@
      */
     public Content getHeader(String header) {
         HtmlTree bodyTree = getBody(getWindowTitle(header));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
         Content h1Content = new StringContent(header);
         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, true,
                 HtmlStyle.title, h1Content);
         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-        mainTree.add(div);
+        bodyContents.setHeader(headerContent)
+                .addMainContent(div);
         return bodyTree;
     }
 
@@ -216,16 +212,14 @@
     }
 
     /**
-     * Get the serialized content tree section.
+     * Add the serialized content tree section.
      *
      * @param serializedTreeContent the serialized content tree to be added
-     * @return a div content tree
      */
-    public Content getSerializedContent(Content serializedTreeContent) {
+    public void addSerializedContent(Content serializedTreeContent) {
         HtmlTree divContent = HtmlTree.DIV(HtmlStyle.serializedFormContainer,
                 serializedTreeContent);
-        mainTree.add(divContent);
-        return mainTree;
+        bodyContents.addMainContent(divContent);
     }
 
     /**
@@ -238,15 +232,13 @@
 
     /**
      * Add the footer.
-     *
-     * @param serializedTree the serialized tree to be added
      */
-    public void addFooter(Content serializedTree) {
+    public void addFooter() {
         Content htmlTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         htmlTree.add(navBar.getContent(false));
         addBottom(htmlTree);
-        serializedTree.add(htmlTree);
+        bodyContents.setFooter(htmlTree);
     }
 
     /**
@@ -254,6 +246,7 @@
      */
     @Override
     public void printDocument(Content serializedTree) throws DocFileIOException {
+        serializedTree.add(bodyContents.toContent());
         printHtmlDocument(null, "serialized forms", serializedTree);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -28,6 +28,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -95,15 +97,10 @@
     protected void generateIndexFile() throws DocFileIOException {
         String title = resources.getText("doclet.Window_Single_Index");
         HtmlTree body = getBody(getWindowTitle(title));
-        HtmlTree header = HtmlTree.HEADER();
-        addTop(header);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        header.add(navBar.getContent(true));
-        body.add(header);
-        HtmlTree main = HtmlTree.MAIN();
-        main.add(HtmlTree.DIV(HtmlStyle.header,
-                HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
-                        contents.getContent("doclet.Index"))));
+        headerContent.add(navBar.getContent(true));
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
         divTree.setStyle(HtmlStyle.contentContainer);
         elements = new TreeSet<>(indexbuilder.getIndexMap().keySet());
@@ -120,13 +117,18 @@
             }
         }
         addLinksForIndexes(divTree);
-        main.add(divTree);
-        body.add(main);
         HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        body.add(footer);
+        body.add(new BodyContents()
+                .setHeader(headerContent)
+                .addMainContent(HtmlTree.DIV(HtmlStyle.header,
+                        HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
+                                contents.getContent("doclet.Index"))))
+                .addMainContent(divTree)
+                .setFooter(footer)
+                .toContent());
         createSearchIndexFiles();
         printHtmlDocument(null, "index", body);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -32,6 +32,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -122,12 +124,11 @@
         String title = resources.getText("doclet.Window_Split_Index",
                 unicode.toString());
         HtmlTree body = getBody(getWindowTitle(title));
-        HtmlTree header = HtmlTree.HEADER();
-        addTop(header);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        header.add(navBar.getContent(true));
-        body.add(header);
-        HtmlTree main = HtmlTree.MAIN();
+        headerContent.add(navBar.getContent(true));
+        Content main = new ContentBuilder();
         main.add(HtmlTree.DIV(HtmlStyle.header,
                 HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
                         contents.getContent("doclet.Index"))));
@@ -144,12 +145,15 @@
         }
         addLinksForIndexes(divTree);
         main.add(divTree);
-        body.add(main);
         HtmlTree footer = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
         footer.add(navBar.getContent(false));
         addBottom(footer);
-        body.add(footer);
+        body.add(new BodyContents()
+                .setHeader(headerContent)
+                .addMainContent(main)
+                .setFooter(footer)
+                .toContent());
         String description = "index: " + unicode;
         printHtmlDocument(null, description, body);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -31,6 +31,7 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
 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;
@@ -60,9 +61,9 @@
 public abstract class SubWriterHolderWriter extends HtmlDocletWriter {
 
     /**
-     * The HTML tree for main tag.
+     * The HTML builder for the body contents.
      */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
+    protected BodyContents bodyContents = new BodyContents();
 
     public SubWriterHolderWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
@@ -191,22 +192,19 @@
     /**
      * Add the class content tree.
      *
-     * @param contentTree content tree to which the class content will be added
      * @param classContentTree class content tree which will be added to the content tree
      */
-    public void addClassContentTree(Content contentTree, Content classContentTree) {
-        mainTree.add(classContentTree);
-        contentTree.add(mainTree);
+    public void addClassContentTree(Content classContentTree) {
+        bodyContents.addMainContent(classContentTree);
     }
 
     /**
      * Add the annotation content tree.
      *
-     * @param contentTree content tree to which the annotation content will be added
      * @param annotationContentTree annotation content tree which will be added to the content tree
      */
-    public void addAnnotationContentTree(Content contentTree, Content annotationContentTree) {
-        addClassContentTree(contentTree, annotationContentTree);
+    public void addAnnotationContentTree(Content annotationContentTree) {
+        addClassContentTree(annotationContentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -29,6 +29,8 @@
 
 import javax.lang.model.element.PackageElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -70,6 +72,8 @@
 
     private final Navigation navBar;
 
+    protected BodyContents bodyContents;
+
     /**
      * Constructor to construct TreeWriter object.
      *
@@ -81,7 +85,8 @@
         super(configuration, filename, classtree);
         packages = configuration.packages;
         classesOnly = packages.isEmpty();
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.TREE, path);
+        this.navBar = new Navigation(null, configuration, PageMode.TREE, path);
+        this.bodyContents = new BodyContents();
     }
 
     /**
@@ -111,21 +116,23 @@
                 HtmlStyle.title, headContent);
         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
         addPackageTreeLinks(div);
-        HtmlTree htmlTree = HtmlTree.MAIN();
-        htmlTree.add(div);
+        Content mainContent = new ContentBuilder();
+        mainContent.add(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
         divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
         addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree, true);
-        htmlTree.add(divTree);
-        body.add(htmlTree);
-        htmlTree = HtmlTree.FOOTER();
+        mainContent.add(divTree);
+        HtmlTree footerTree = HtmlTree.FOOTER();
         navBar.setUserFooter(getUserHeaderFooter(false));
-        htmlTree.add(navBar.getContent(false));
-        addBottom(htmlTree);
-        body.add(htmlTree);
+        footerTree.add(navBar.getContent(false));
+        addBottom(footerTree);
+        body.add(bodyContents
+                .addMainContent(mainContent)
+                .setFooter(footerTree)
+                .toContent());
         printHtmlDocument(null, "class tree", body);
     }
 
@@ -176,11 +183,11 @@
     protected HtmlTree getTreeHeader() {
         String title = resources.getText("doclet.Window_Class_Hierarchy");
         HtmlTree bodyTree = getBody(getWindowTitle(title));
-        HtmlTree htmlTree = HtmlTree.HEADER();
-        addTop(htmlTree);
+        Content headerContent = new ContentBuilder();
+        addTop(headerContent);
         navBar.setUserHeader(getUserHeaderFooter(true));
-        htmlTree.add(navBar.getContent(true));
-        bodyTree.add(htmlTree);
+        headerContent.add(navBar.getContent(true));
+        bodyContents.setHeader(headerContent);
         return bodyTree;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/BodyContents.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A builder for the contents of the BODY element.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class BodyContents {
+
+    private List<Content> mainContents = new ArrayList<>();
+    private Content header = HtmlTree.EMPTY;
+    private Content footer = HtmlTree.EMPTY;
+
+    public BodyContents addMainContent(Content content) {
+        mainContents.add(content);
+        return this;
+    }
+
+    public BodyContents setHeader(Content header) {
+        this.header = header;
+        return this;
+    }
+
+    public BodyContents setFooter(Content footer) {
+        this.footer = footer;
+        return this;
+    }
+
+    /**
+     * Returns the HTML for the contents of the BODY element.
+     *
+     * @return the HTML
+     */
+    public Content toContent() {
+        HtmlTree mainTree = HtmlTree.MAIN();
+        mainContents.forEach(mainTree::add);
+        HtmlTree flexHeader = HtmlTree.HEADER().setStyle(HtmlStyle.flexHeader);
+        flexHeader.add(header);
+        HtmlTree flexBox = HtmlTree.DIV(HtmlStyle.flexBox, flexHeader);
+        HtmlTree flexContent = HtmlTree.DIV(HtmlStyle.flexContent, mainTree);
+        flexContent.add(footer);
+        flexBox.add(flexContent);
+        return flexBox;
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Fri Nov 29 10:02:07 2019 +0000
@@ -73,7 +73,9 @@
     externalLink,
     fieldDetails,
     fieldSummary,
-    fixedNav,
+    flexBox,
+    flexHeader,
+    flexContent,
     header,
     helpSection,
     hierarchy,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Fri Nov 29 10:02:07 2019 +0000
@@ -584,21 +584,6 @@
     }
 
     /**
-     * Generates a MAIN tag with role attribute, style attribute and some content.
-     *
-     * @param styleClass style of the MAIN tag
-     * @param body content of the MAIN tag
-     * @return an HtmlTree object for the MAIN tag
-     */
-    public static HtmlTree MAIN(HtmlStyle styleClass, Content body) {
-        HtmlTree htmltree = HtmlTree.MAIN(body);
-        if (styleClass != null) {
-            htmltree.setStyle(styleClass);
-        }
-        return htmltree;
-    }
-
-    /**
      * Generates a META tag with the http-equiv, content and charset attributes.
      *
      * @param httpEquiv http equiv attribute for the META tag
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Fri Nov 29 10:02:07 2019 +0000
@@ -70,7 +70,6 @@
     private final DocPath path;
     private final DocPath pathToRoot;
     private final Links links;
-    private final HtmlTree fixedNavDiv;
     private final PageMode documentedPage;
     private Content navLinkModule;
     private Content navLinkPackage;
@@ -85,9 +84,6 @@
     private Content userFooter;
     private final String rowListTitle;
     private final Content searchLabel;
-    private static final Script FIXED_NAV_SCRIPT = new Script("<!--\n"
-            + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-            + "//-->\n");
 
     public enum PageMode {
         ALLCLASSES,
@@ -133,15 +129,12 @@
      *
      * @param element element being documented. null if its not an element documentation page
      * @param configuration the configuration object
-     * @param fixedNavDiv the fixed navigation for the header navigation
      * @param page the kind of page being documented
      * @param path the DocPath object
      */
-    public Navigation(Element element, HtmlConfiguration configuration, HtmlTree fixedNavDiv,
-            PageMode page, DocPath path) {
+    public Navigation(Element element, HtmlConfiguration configuration, PageMode page, DocPath path) {
         this.configuration = configuration;
         this.element = element;
-        this.fixedNavDiv = fixedNavDiv;
         this.contents = configuration.contents;
         this.documentedPage = page;
         this.path = path;
@@ -941,10 +934,6 @@
         tree.add(searchDiv);
     }
 
-    private void addFixedNavScript(Content tree) {
-        tree.add(FIXED_NAV_SCRIPT.asContent());
-    }
-
     /**
      * Get the navigation content.
      *
@@ -952,69 +941,58 @@
      * @return the navigation contents
      */
     public Content getContent(boolean top) {
-        Content contentTree = new ContentBuilder();
-        if (!configuration.nonavbar) {
-            Deque<Content> queue;
-            Content tree = HtmlTree.NAV();
-            HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
-            if (top) {
-                queue = topBottomNavContents.get(Position.TOP);
-                fixedNavDiv.add(Position.TOP.startOfNav());
-                navDiv.setStyle(HtmlStyle.topNav);
-            } else {
-                queue = topBottomNavContents.get(Position.BOTTOM);
-                tree.add(Position.BOTTOM.startOfNav());
-                navDiv.setStyle(HtmlStyle.bottomNav);
-            }
-            navDiv.add(queue.poll());
-            HtmlTree skipLinkDiv = HtmlTree.DIV(HtmlStyle.skipNav, queue.poll());
-            navDiv.add(skipLinkDiv);
-            navDiv.add(queue.poll());
-            HtmlTree navList = new HtmlTree(HtmlTag.UL);
-            navList.setStyle(HtmlStyle.navList);
-            navList.put(HtmlAttr.TITLE, rowListTitle);
-            fixedNavDiv.setStyle(HtmlStyle.fixedNav);
-            addMainNavLinks(navList);
-            navDiv.add(navList);
-            Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, top ? userHeader : userFooter);
-            navDiv.add(aboutDiv);
-            if (top) {
-                fixedNavDiv.add(navDiv);
-            } else {
-                tree.add(navDiv);
-            }
-            HtmlTree subDiv = new HtmlTree(HtmlTag.DIV);
-            subDiv.setStyle(HtmlStyle.subNav);
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            // Add the summary links if present.
-            HtmlTree ulNavSummary = new HtmlTree(HtmlTag.UL);
-            ulNavSummary.setStyle(HtmlStyle.subNavList);
-            addSummaryLinks(ulNavSummary);
-            div.add(ulNavSummary);
-            // Add the detail links if present.
-            HtmlTree ulNavDetail = new HtmlTree(HtmlTag.UL);
-            ulNavDetail.setStyle(HtmlStyle.subNavList);
-            addDetailLinks(ulNavDetail);
-            div.add(ulNavDetail);
-            subDiv.add(div);
-            if (top && configuration.createindex) {
-                addSearch(subDiv);
-            }
-            if (top) {
-                fixedNavDiv.add(subDiv);
-                fixedNavDiv.add(queue.poll());
-                fixedNavDiv.add(Position.TOP.endOfNav());
-                tree.add(fixedNavDiv);
-                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Entity.NO_BREAK_SPACE);
-                tree.add(paddingDiv);
-                addFixedNavScript(tree);
-            } else {
-                tree.add(subDiv);
-                tree.add(queue.poll());
-                tree.add(Position.BOTTOM.endOfNav());
-            }
-            return tree;
+        if (configuration.nonavbar) {
+            return new ContentBuilder();
+        }
+        Deque<Content> queue;
+        Content tree = HtmlTree.NAV();
+        HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
+        if (top) {
+            queue = topBottomNavContents.get(Position.TOP);
+            tree.add(Position.TOP.startOfNav());
+            navDiv.setStyle(HtmlStyle.topNav);
+        } else {
+            queue = topBottomNavContents.get(Position.BOTTOM);
+            tree.add(Position.BOTTOM.startOfNav());
+            navDiv.setStyle(HtmlStyle.bottomNav);
         }
-        return contentTree;
+        navDiv.add(queue.poll());
+        HtmlTree skipLinkDiv = HtmlTree.DIV(HtmlStyle.skipNav, queue.poll());
+        navDiv.add(skipLinkDiv);
+        navDiv.add(queue.poll());
+        HtmlTree navList = new HtmlTree(HtmlTag.UL);
+        navList.setStyle(HtmlStyle.navList);
+        navList.put(HtmlAttr.TITLE, rowListTitle);
+        addMainNavLinks(navList);
+        navDiv.add(navList);
+        Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, top ? userHeader : userFooter);
+        navDiv.add(aboutDiv);
+        tree.add(navDiv);
+        HtmlTree subDiv = new HtmlTree(HtmlTag.DIV);
+        subDiv.setStyle(HtmlStyle.subNav);
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        // Add the summary links if present.
+        HtmlTree ulNavSummary = new HtmlTree(HtmlTag.UL);
+        ulNavSummary.setStyle(HtmlStyle.subNavList);
+        addSummaryLinks(ulNavSummary);
+        div.add(ulNavSummary);
+        // Add the detail links if present.
+        HtmlTree ulNavDetail = new HtmlTree(HtmlTag.UL);
+        ulNavDetail.setStyle(HtmlStyle.subNavList);
+        addDetailLinks(ulNavDetail);
+        div.add(ulNavDetail);
+        subDiv.add(div);
+        if (top && configuration.createindex) {
+            addSearch(subDiv);
+        }
+        tree.add(subDiv);
+        if (top) {
+            tree.add(Position.TOP.endOfNav());
+            tree.add(HtmlTree.DIV(HtmlStyle.skipNav, queue.poll()));
+        } else {
+            tree.add(queue.poll());
+            tree.add(Position.BOTTOM.endOfNav());
+        }
+        return tree;
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AnnotationTypeWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -112,10 +112,9 @@
     /**
      * Add the annotation content tree to the documentation content tree.
      *
-     * @param contentTree content tree to which the annotation content will be added
      * @param annotationContentTree annotation content tree which will be added to the content tree
      */
-    public void addAnnotationContentTree(Content contentTree, Content annotationContentTree);
+    public void addAnnotationContentTree(Content annotationContentTree);
 
     /**
      * Get the member tree.
@@ -143,10 +142,8 @@
 
     /**
      * Add the footer of the page.
-     *
-     * @param contentTree content tree to which the footer will be added
      */
-    public void addFooter(Content contentTree);
+    public void addFooter();
 
     /**
      * Print the document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ClassWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ClassWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -177,17 +177,14 @@
     /**
      * Add the class content tree.
      *
-     * @param contentTree content tree to which the class content will be added
      * @param classContentTree class content tree which will be added to the content tree
      */
-    public void addClassContentTree(Content contentTree, Content classContentTree);
+    public void addClassContentTree(Content classContentTree);
 
     /**
      * Add the footer of the page.
-     *
-     * @param contentTree content tree to which the footer will be added
      */
-    public void addFooter(Content contentTree);
+    public void addFooter();
 
     /**
      * Print the document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstantsSummaryWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ConstantsSummaryWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -75,10 +75,9 @@
     /**
      * Add the content list to the documentation tree.
      *
-     * @param contentTree the tree to which the contents list will be added
      * @param contentListTree the content that will be added to the list
      */
-    public abstract void addContentsList(Content contentTree, Content contentListTree);
+    public abstract void addContentsList(Content contentListTree);
 
     /**
      * Get the constant summaries for the document.
@@ -129,17 +128,14 @@
     /**
      * Add the summaries list to the content tree.
      *
-     * @param contentTree the tree to which the summaries list will be added
      * @param summariesTree the summaries content tree that will be added to the list
      */
-    public abstract void addConstantSummaries(Content contentTree, Content summariesTree);
+    public abstract void addConstantSummaries(Content summariesTree);
 
     /**
      * Adds the footer for the summary documentation.
-     *
-     * @param contentTree content tree to which the footer will be added
      */
-    public abstract void addFooter(Content contentTree);
+    public abstract void addFooter();
 
     /**
      * Print the constants summary document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -111,17 +111,14 @@
     /**
      * Adds the module content tree to the documentation tree.
      *
-     * @param contentTree the tree to which the module content tree will be added
      * @param moduleContentTree the content tree that will be added
      */
-    public abstract void addModuleContent(Content contentTree, Content moduleContentTree);
+    public abstract void addModuleContent(Content moduleContentTree);
 
     /**
      * Adds the footer to the documentation tree.
-     *
-     * @param contentTree the tree to which the footer will be added
      */
-    public abstract void addModuleFooter(Content contentTree);
+    public abstract void addModuleFooter();
 
     /**
      * Print the module summary document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PackageSummaryWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -143,17 +143,14 @@
      * Adds the tag information from the "packages.html" or "package-info.java" file to the
      * documentation tree.
      *
-     * @param contentTree the content tree to which the package content tree will be added
      * @param packageContentTree the package content tree to be added
      */
-    public abstract void addPackageContent(Content contentTree, Content packageContentTree);
+    public abstract void addPackageContent(Content packageContentTree);
 
     /**
      * Adds the footer to the documentation tree.
-     *
-     * @param contentTree the tree to which the footer will be added
      */
-    public abstract void addPackageFooter(Content contentTree);
+    public abstract void addPackageFooter();
 
     /**
      * Print the package summary document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/SerializedFormWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -140,19 +140,16 @@
     public SerialMethodWriter getSerialMethodWriter(TypeElement typeElement);
 
     /**
-     * Get the serialized content.
+     * Add the serialized content to the body content.
      *
      * @param serializedTreeContent content for serialized data
-     * @return a content tree for serialized information
      */
-    public Content getSerializedContent(Content serializedTreeContent);
+    public void addSerializedContent(Content serializedTreeContent);
 
     /**
      * Add the footer.
-     *
-     * @param serializedTree the serialized tree to be added
      */
-    public void addFooter(Content serializedTree);
+    public void addFooter();
 
     /**
      * Print the serialized form document.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -59,11 +59,6 @@
     private final AnnotationTypeWriter writer;
 
     /**
-     * The content tree for the annotation documentation.
-     */
-    private Content contentTree;
-
-    /**
      * Construct a new ClassBuilder.
      *
      * @param context           the build context.
@@ -97,17 +92,16 @@
      */
     @Override
     public void build() throws DocletException {
-        buildAnnotationTypeDoc(contentTree);
+        buildAnnotationTypeDoc();
     }
 
     /**
      * Build the annotation type documentation.
      *
-     * @param contentTree the content tree to which the documentation will be added
      * @throws DocletException if there is a problem building the documentation
      */
-    protected void buildAnnotationTypeDoc(Content contentTree) throws DocletException {
-        contentTree = writer.getHeader(resources.getText("doclet.AnnotationType") +
+    protected void buildAnnotationTypeDoc() throws DocletException {
+        Content contentTree = writer.getHeader(resources.getText("doclet.AnnotationType") +
                " " + utils.getSimpleName(annotationType));
         Content annotationContentTree = writer.getAnnotationContentHeader();
 
@@ -115,8 +109,8 @@
         buildMemberSummary(annotationContentTree);
         buildAnnotationTypeMemberDetails(annotationContentTree);
 
-        writer.addAnnotationContentTree(contentTree, annotationContentTree);
-        writer.addFooter(contentTree);
+        writer.addAnnotationContentTree(annotationContentTree);
+        writer.addFooter();
         writer.printDocument(contentTree);
         copyDocFiles();
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -69,11 +69,6 @@
      */
     private final boolean isEnum;
 
-    /**
-     * The content tree for the class documentation.
-     */
-    private Content contentTree;
-
     private final Utils utils;
 
     /**
@@ -118,16 +113,15 @@
      */
     @Override
     public void build() throws DocletException {
-        buildClassDoc(contentTree);
+        buildClassDoc();
     }
 
      /**
       * Handles the {@literal <TypeElement>} tag.
       *
-      * @param contentTree the content tree to which the documentation will be added
       * @throws DocletException if there is a problem while building the documentation
       */
-     protected void buildClassDoc(Content contentTree) throws DocletException {
+     protected void buildClassDoc() throws DocletException {
         String key;
         if (isInterface) {
             key = "doclet.Interface";
@@ -136,7 +130,7 @@
         } else {
             key = "doclet.Class";
         }
-        contentTree = writer.getHeader(resources.getText(key) + " "
+        Content contentTree = writer.getHeader(resources.getText(key) + " "
                 + utils.getSimpleName(typeElement));
         Content classContentTree = writer.getClassContentHeader();
 
@@ -145,8 +139,8 @@
         buildMemberSummary(classContentTree);
         buildMemberDetails(classContentTree);
 
-        writer.addClassContentTree(contentTree, classContentTree);
-        writer.addFooter(contentTree);
+        writer.addClassContentTree(classContentTree);
+        writer.addFooter();
         writer.printDocument(contentTree);
         copyDocFiles();
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -84,11 +84,6 @@
     private TypeElement currentClass;
 
     /**
-     * The content tree for the constant summary documentation.
-     */
-    private Content contentTree;
-
-    /**
      * True if first package is listed.
      */
     private boolean first = true;
@@ -129,31 +124,28 @@
             //Doclet does not support this output.
             return;
         }
-        buildConstantSummary(contentTree);
+        buildConstantSummary();
     }
 
     /**
      * Build the constant summary.
      *
-     * @param contentTree the content tree to which the documentation will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildConstantSummary(Content contentTree) throws DocletException {
-        contentTree = writer.getHeader();
+    protected void buildConstantSummary() throws DocletException {
+        Content contentTree = writer.getHeader();
 
-        buildContents(contentTree);
-        buildConstantSummaries(contentTree);
+        buildContents();
+        buildConstantSummaries();
 
-        writer.addFooter(contentTree);
+        writer.addFooter();
         writer.printDocument(contentTree);
     }
 
     /**
      * Build the list of packages.
-     *
-     * @param contentTree the content tree to which the content list will be added
      */
-    protected void buildContents(Content contentTree) {
+    protected void buildContents() {
         Content contentListTree = writer.getContentsHeader();
         printedPackageHeaders.clear();
         for (PackageElement pkg : configuration.packages) {
@@ -161,16 +153,15 @@
                 writer.addLinkToPackageContent(pkg, printedPackageHeaders, contentListTree);
             }
         }
-        writer.addContentsList(contentTree, contentListTree);
+        writer.addContentsList(contentListTree);
     }
 
     /**
      * Build the summary for each documented package.
      *
-     * @param contentTree the tree to which the summaries will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildConstantSummaries(Content contentTree) throws DocletException {
+    protected void buildConstantSummaries() throws DocletException {
         printedPackageHeaders.clear();
         Content summariesTree = writer.getConstantSummaries();
         for (PackageElement aPackage : configuration.packages) {
@@ -184,7 +175,7 @@
                 first = false;
             }
         }
-        writer.addConstantSummaries(contentTree, summariesTree);
+        writer.addConstantSummaries(summariesTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -56,11 +56,6 @@
     private final ModuleSummaryWriter moduleWriter;
 
     /**
-     * The content that will be added to the module summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
      * Construct a new ModuleSummaryBuilder.
      *
      * @param context  the build context.
@@ -101,21 +96,20 @@
             //Doclet does not support this output.
             return;
         }
-        buildModuleDoc(contentTree);
+        buildModuleDoc();
     }
 
     /**
      * Build the module documentation.
      *
-     * @param contentTree the content tree to which the documentation will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildModuleDoc(Content contentTree) throws DocletException {
-        contentTree = moduleWriter.getModuleHeader(mdle.getQualifiedName().toString());
+    protected void buildModuleDoc() throws DocletException {
+        Content contentTree = moduleWriter.getModuleHeader(mdle.getQualifiedName().toString());
 
-        buildContent(contentTree);
+        buildContent();
 
-        moduleWriter.addModuleFooter(contentTree);
+        moduleWriter.addModuleFooter();
         moduleWriter.printDocument(contentTree);
         DocFilesHandler docFilesHandler = configuration.getWriterFactory().getDocFilesHandler(mdle);
         docFilesHandler.copyDocFiles();
@@ -124,18 +118,16 @@
     /**
      * Build the content for the module doc.
      *
-     * @param contentTree the content tree to which the module contents
-     *                    will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildContent(Content contentTree) throws DocletException {
+    protected void buildContent() throws DocletException {
         Content moduleContentTree = moduleWriter.getContentHeader();
 
         buildModuleDescription(moduleContentTree);
         buildModuleTags(moduleContentTree);
         buildSummary(moduleContentTree);
 
-        moduleWriter.addModuleContent(contentTree, moduleContentTree);
+        moduleWriter.addModuleContent(moduleContentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -61,11 +61,6 @@
     private final PackageSummaryWriter packageWriter;
 
     /**
-     * The content that will be added to the package summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
      * Construct a new PackageSummaryBuilder.
      *
      * @param context  the build context.
@@ -107,21 +102,20 @@
             //Doclet does not support this output.
             return;
         }
-        buildPackageDoc(contentTree);
+        buildPackageDoc();
     }
 
     /**
      * Build the package documentation.
      *
-     * @param contentTree the content tree to which the documentation will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildPackageDoc(Content contentTree) throws DocletException {
-        contentTree = packageWriter.getPackageHeader(utils.getPackageName(packageElement));
+    protected void buildPackageDoc() throws DocletException {
+        Content contentTree = packageWriter.getPackageHeader(utils.getPackageName(packageElement));
 
-        buildContent(contentTree);
+        buildContent();
 
-        packageWriter.addPackageFooter(contentTree);
+        packageWriter.addPackageFooter();
         packageWriter.printDocument(contentTree);
         DocFilesHandler docFilesHandler = configuration
                 .getWriterFactory()
@@ -132,18 +126,16 @@
     /**
      * Build the content for the package.
      *
-     * @param contentTree the content tree to which the package contents
-     *                    will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildContent(Content contentTree) throws DocletException {
+    protected void buildContent() throws DocletException {
         Content packageContentTree = packageWriter.getContentHeader();
 
         buildPackageDescription(packageContentTree);
         buildPackageTags(packageContentTree);
         buildSummary(packageContentTree);
 
-        packageWriter.addPackageContent(contentTree, packageContentTree);
+        packageWriter.addPackageContent(packageContentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java	Fri Nov 29 10:02:07 2019 +0000
@@ -96,12 +96,6 @@
     protected Element currentMember;
 
     /**
-     * The content that will be added to the serialized form documentation tree.
-     */
-    private Content contentTree;
-
-
-    /**
      * Construct a new SerializedFormBuilder.
      * @param context  the build context.
      */
@@ -137,32 +131,30 @@
             //Doclet does not support this output.
             return;
         }
-        buildSerializedForm(contentTree);
+        buildSerializedForm();
     }
 
     /**
      * Build the serialized form.
      *
-     * @param serializedTree content tree to which the documentation will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildSerializedForm(Content serializedTree) throws DocletException {
-        serializedTree = writer.getHeader(resources.getText(
+    protected void buildSerializedForm() throws DocletException {
+        Content contentTree = writer.getHeader(resources.getText(
                 "doclet.Serialized_Form"));
 
-        buildSerializedFormSummaries(serializedTree);
+        buildSerializedFormSummaries();
 
-        writer.addFooter(serializedTree);
-        writer.printDocument(serializedTree);
+        writer.addFooter();
+        writer.printDocument(contentTree);
     }
 
     /**
      * Build the serialized form summaries.
      *
-     * @param serializedTree content tree to which the documentation will be added
      * @throws DocletException if there is a problem while building the documentation
      */
-    protected void buildSerializedFormSummaries(Content serializedTree)
+    protected void buildSerializedFormSummaries()
             throws DocletException {
         Content serializedSummariesTree = writer.getSerializedSummariesHeader();
         for (PackageElement pkg : configuration.packages) {
@@ -170,8 +162,7 @@
 
             buildPackageSerializedForm(serializedSummariesTree);
         }
-        serializedTree.add(writer.getSerializedContent(
-                serializedSummariesTree));
+        writer.addSerializedContent(serializedSummariesTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js	Fri Nov 29 10:02:07 2019 +0000
@@ -102,9 +102,6 @@
     if (!tagSearchIndex) {
         createElem(doc, tag, 'tag-search-index.js');
     }
-    $(window).resize(function() {
-        $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
-    });
 }
 
 function createElem(doc, tag, path) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Fri Nov 29 10:02:07 2019 +0000
@@ -40,13 +40,6 @@
 a[name] {
     color:#353833;
 }
-a[name]:before, a[name]:target, a[id]:before, a[id]:target {
-    content:"";
-    display:inline-block;
-    position:relative;
-    padding-top:129px;
-    margin-top:-129px;
-}
 pre {
     font-family:'DejaVu Sans Mono', monospace;
     font-size:14px;
@@ -131,14 +124,19 @@
 /*
  * Styles for navigation bar.
  */
-.navPadding {
-    padding-top: 107px;
+.flexBox {
+    position:fixed;
+    display:flex;
+    flex-direction:column;
+    height: 100%;
+    width: 100%;
 }
-.fixedNav {
-    position:fixed;
-    width:100%;
-    z-index:999;
-    background-color:#ffffff;
+.flexHeader {
+    flex: 0 0 auto;
+}
+.flexContent {
+    flex: 1 1 auto;
+    overflow-y: auto;
 }
 .topNav {
     background-color:#4D7A97;
@@ -632,7 +630,7 @@
     background-size:12px;
     border:0 none;
     width:16px;
-    height:17px;
+    height:16px;
     position:relative;
     left:-4px;
     top:-4px;
@@ -649,8 +647,8 @@
     font-style:italic;
     font-size:12px;
 }
-.searchTagResult:before, .searchTagResult:target {
-    color:red;
+.searchTagResult:target {
+    background-color:yellow;
 }
 .moduleGraph span {
     display:none;
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java	Fri Nov 29 10:02:07 2019 +0000
@@ -45,6 +45,7 @@
 import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -78,6 +79,17 @@
     private static Boolean SAVE_GENERATED;
 
 
+    private static final Duration MICRO_SECOND = Duration.ofNanos(1_000);
+    private static final Duration SECOND = Duration.ofSeconds(1);
+    private static final Duration MINUTE = Duration.ofMinutes(1);
+    private static final Duration HOUR = Duration.ofHours(1);
+    private static final Duration DAY = Duration.ofDays(1);
+    private static final int NANO_SIGNIFICANT_FIGURES = 9;
+    private static final int MILL_SIGNIFICANT_FIGURES = 3;
+    private static final int DISPLAY_NANO_DIGIT = 3;
+    private static final int BASE = 10;
+
+
     public static void checkAccessFlightRecorder() throws SecurityException {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -597,6 +609,90 @@
         return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr";
     }
 
+    public static String formatDuration(Duration d) {
+        Duration roundedDuration = roundDuration(d);
+        if (roundedDuration.equals(Duration.ZERO)) {
+            return "0 s";
+        } else if(roundedDuration.isNegative()){
+            return "-" + formatPositiveDuration(roundedDuration.abs());
+        } else {
+            return formatPositiveDuration(roundedDuration);
+        }
+    }
+
+    private static String formatPositiveDuration(Duration d){
+        if (d.compareTo(MICRO_SECOND) < 0) {
+            // 0.000001 ms - 0.000999 ms
+            double outputMs = (double) d.toNanosPart() / 1_000_000;
+            return String.format("%.6f ms",  outputMs);
+        } else if (d.compareTo(SECOND) < 0) {
+            // 0.001 ms - 999 ms
+            int valueLength = countLength(d.toNanosPart());
+            int outputDigit = NANO_SIGNIFICANT_FIGURES - valueLength;
+            double outputMs = (double) d.toNanosPart() / 1_000_000;
+            return String.format("%." + outputDigit + "f ms",  outputMs);
+        } else if (d.compareTo(MINUTE) < 0) {
+            // 1.00 s - 59.9 s
+            int valueLength = countLength(d.toSecondsPart());
+            int outputDigit = MILL_SIGNIFICANT_FIGURES - valueLength;
+            double outputSecond = d.toSecondsPart() + (double) d.toMillisPart() / 1_000;
+            return String.format("%." + outputDigit + "f s",  outputSecond);
+        } else if (d.compareTo(HOUR) < 0) {
+            // 1 m 0 s - 59 m 59 s
+            return String.format("%d m %d s",  d.toMinutesPart(), d.toSecondsPart());
+        } else if (d.compareTo(DAY) < 0) {
+            // 1 h 0 m - 23 h 59 m
+            return String.format("%d h %d m",  d.toHoursPart(), d.toMinutesPart());
+        } else {
+            // 1 d 0 h -
+            return String.format("%d d %d h",  d.toDaysPart(), d.toHoursPart());
+        }
+    }
+
+    private static int countLength(long value){
+        return (int) Math.log10(value) + 1;
+    }
+
+    private static Duration roundDuration(Duration d) {
+        if (d.equals(Duration.ZERO)) {
+            return d;
+        } else if(d.isNegative()){
+            Duration roundedPositiveDuration = roundPositiveDuration(d.abs());
+            return roundedPositiveDuration.negated();
+        } else {
+            return roundPositiveDuration(d);
+        }
+    }
+
+    private static Duration roundPositiveDuration(Duration d){
+        if (d.compareTo(MICRO_SECOND) < 0) {
+            // No round
+            return d;
+        } else if (d.compareTo(SECOND) < 0) {
+            // Round significant figures to three digits
+            int valueLength = countLength(d.toNanosPart());
+            int roundValue = (int) Math.pow(BASE, valueLength - DISPLAY_NANO_DIGIT);
+            long roundedNanos = Math.round((double) d.toNanosPart() / roundValue) * roundValue;
+            return d.truncatedTo(ChronoUnit.SECONDS).plusNanos(roundedNanos);
+        } else if (d.compareTo(MINUTE) < 0) {
+            // Round significant figures to three digits
+            int valueLength = countLength(d.toSecondsPart());
+            int roundValue = (int) Math.pow(BASE, valueLength);
+            long roundedMills = Math.round((double) d.toMillisPart() / roundValue) * roundValue;
+            return d.truncatedTo(ChronoUnit.SECONDS).plusMillis(roundedMills);
+        } else if (d.compareTo(HOUR) < 0) {
+            // Round for more than 500 ms or less
+            return d.plusMillis(SECOND.dividedBy(2).toMillisPart()).truncatedTo(ChronoUnit.SECONDS);
+        } else if (d.compareTo(DAY) < 0) {
+            // Round for more than 30 seconds or less
+            return d.plusSeconds(MINUTE.dividedBy(2).toSecondsPart()).truncatedTo(ChronoUnit.MINUTES);
+        } else {
+            // Round for more than 30 minutes or less
+            return d.plusMinutes(HOUR.dividedBy(2).toMinutesPart()).truncatedTo(ChronoUnit.HOURS);
+        }
+    }
+
+
     public static void takeNap(long millis) {
         try {
             Thread.sleep(millis);
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java	Fri Nov 29 10:02:07 2019 +0000
@@ -48,7 +48,7 @@
  * an event stream.
  */
 abstract class AbstractEventStream implements EventStream {
-    private final static AtomicLong counter = new AtomicLong(1);
+    private final static AtomicLong counter = new AtomicLong(0);
 
     private final Object terminated = new Object();
     private final Runnable flushOperation = () -> dispatcher().runFlushActions();
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java	Fri Nov 29 10:02:07 2019 +0000
@@ -292,4 +292,8 @@
     static long headerSize() {
         return HEADER_SIZE;
     }
+
+    public long getLastNanos() {
+        return getStartNanos() + getDurationNanos();
+    }
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java	Fri Nov 29 10:02:07 2019 +0000
@@ -106,6 +106,7 @@
 
     private Runnable flushOperation;
     private ParserConfiguration configuration;
+    private volatile boolean closed;
 
     public ChunkParser(RecordingInput input) throws IOException {
         this(input, new ParserConfiguration());
@@ -202,7 +203,7 @@
             long lastValid = absoluteChunkEnd;
             long metadataPoistion = chunkHeader.getMetataPosition();
             long contantPosition = chunkHeader.getConstantPoolPosition();
-            chunkFinished = awaitUpdatedHeader(absoluteChunkEnd);
+            chunkFinished = awaitUpdatedHeader(absoluteChunkEnd, configuration.filterEnd);
             if (chunkFinished) {
                 Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "At chunk end");
                 return null;
@@ -279,11 +280,17 @@
         }
     }
 
-    private boolean awaitUpdatedHeader(long absoluteChunkEnd) throws IOException {
+    private boolean awaitUpdatedHeader(long absoluteChunkEnd, long filterEnd) throws IOException {
         if (Logger.shouldLog(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO)) {
             Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Waiting for more data (streaming). Read so far: " + chunkHeader.getChunkSize() + " bytes");
         }
         while (true) {
+            if (closed) {
+                return true;
+            }
+            if (chunkHeader.getLastNanos() > filterEnd)  {
+              return true;
+            }
             chunkHeader.refresh();
             if (absoluteChunkEnd != chunkHeader.getEnd()) {
                 return false;
@@ -452,4 +459,9 @@
         return chunkHeader.isFinalChunk();
     }
 
+    public void close() {
+        this.closed = true;
+        Utils.notifyFlush();
+    }
+
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java	Fri Nov 29 10:02:07 2019 +0000
@@ -69,6 +69,9 @@
         setClosed(true);
         dispatcher().runCloseActions();
         repositoryFiles.close();
+        if (currentParser != null) {
+            currentParser.close();
+        }
     }
 
     @Override
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -57,9 +57,6 @@
  * This class is also used by {@link RecordedObject#toString()}
  */
 public final class PrettyWriter extends EventPrintWriter {
-    private static final Duration MILLSECOND = Duration.ofMillis(1);
-    private static final Duration SECOND = Duration.ofSeconds(1);
-    private static final Duration MINUTE = Duration.ofMinutes(1);
     private static final String TYPE_OLD_OBJECT = Type.TYPES_PREFIX + "OldObject";
     private final static DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
     private final static Long ZERO = 0L;
@@ -553,15 +550,7 @@
                 println("N/A");
                 return true;
             }
-            if(d.compareTo(MILLSECOND) < 0){
-                println(String.format("%.3f us", (double)d.toNanos() / 1_000));
-            } else if(d.compareTo(SECOND) < 0){
-                println(String.format("%.3f ms", (double)d.toNanos() / 1_000_000));
-            } else if(d.compareTo(MINUTE) < 0){
-                println(String.format("%.3f s", (double)d.toMillis() / 1_000));
-            } else {
-                println(String.format("%d s", d.toSeconds()));
-            }
+            println(Utils.formatDuration(d));
             return true;
         }
         if (value instanceof OffsetDateTime) {
--- a/test/hotspot/gtest/gc/g1/test_g1Predictions.cpp	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/gtest/gc/g1/test_g1Predictions.cpp	Fri Nov 29 10:02:07 2019 +0000
@@ -26,6 +26,8 @@
 #include "gc/g1/g1Predictions.hpp"
 #include "unittest.hpp"
 
+#include "utilities/ostream.hpp"
+
 static const double epsilon = 1e-6;
 
 // Some basic formula tests with confidence = 0.0
@@ -96,3 +98,51 @@
   double p4 = predictor.get_new_prediction(&s);
   ASSERT_GT(p4, p3) << "Fourth prediction must be greater than third";
 }
+
+// Some tests to verify bounding between [0 .. 1]
+TEST_VM(G1Predictions, unit_predictions) {
+  G1Predictions predictor(0.5);
+  TruncatedSeq s;
+
+  double p0 = predictor.get_new_unit_prediction(&s);
+  ASSERT_LT(p0, epsilon) << "Initial prediction of empty sequence must be 0.0";
+
+  s.add(100.0);
+  double p1 = predictor.get_new_unit_prediction(&s);
+  ASSERT_NEAR(p1, 1.0, epsilon);
+
+  // Feed the sequence additional positive values to test the high bound.
+  for (int i = 0; i < 3; i++) {
+    s.add(2.0);
+  }
+  ASSERT_NEAR(predictor.get_new_unit_prediction(&s), 1.0, epsilon);
+
+  // Feed the sequence additional large negative value to test the low bound.
+  for (int i = 0; i < 4; i++) {
+    s.add(-200.0);
+  }
+  ASSERT_NEAR(predictor.get_new_unit_prediction(&s), 0.0, epsilon);
+}
+
+// Some tests to verify bounding between [0 .. +inf]
+TEST_VM(G1Predictions, lower_bound_zero_predictions) {
+  G1Predictions predictor(0.5);
+  TruncatedSeq s;
+
+  double p0 = predictor.get_new_lower_zero_bound_prediction(&s);
+  ASSERT_LT(p0, epsilon) << "Initial prediction of empty sequence must be 0.0";
+
+  s.add(100.0);
+  // Feed the sequence additional positive values to see that the high bound is not
+  // bounded by e.g. 1.0
+  for (int i = 0; i < 3; i++) {
+    s.add(2.0);
+  }
+  ASSERT_GT(predictor.get_new_lower_zero_bound_prediction(&s), 1.0);
+
+  // Feed the sequence additional large negative value to test the low bound.
+  for (int i = 0; i < 4; i++) {
+    s.add(-200.0);
+  }
+  ASSERT_NEAR(predictor.get_new_lower_zero_bound_prediction(&s), 0.0, epsilon);
+}
--- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestEliminateLocksOffCrash.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestEliminateLocksOffCrash.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,6 +25,7 @@
  * @test
  * @bug 8227384
  * @summary C2 compilation fails with "graph should be schedulable" when running with -XX:-EliminateLocks
+ * @requires vm.compiler2.enabled & !vm.graal.enabled
  *
  * @run main/othervm -XX:-EliminateLocks TestEliminateLocksOffCrash
  */
--- a/test/hotspot/jtreg/compiler/loopopts/LoopRotateBadNodeBudget.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/LoopRotateBadNodeBudget.java	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,7 @@
  * @summary Node estimate for loop rotate is not correct/sufficient:
  *          assert(delta <= 2 * required) failed: Bad node estimate ...
  *
- * @requires !vm.graal.enabled
+ * @requires vm.compiler2.enabled & !vm.graal.enabled
  *
  * @run main/othervm -XX:PartialPeelNewPhiDelta=5 LoopRotateBadNodeBudget
  * @run main/othervm -Xbatch -XX:PartialPeelNewPhiDelta=5 LoopRotateBadNodeBudget
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -81,7 +81,7 @@
 
     public static void testShenandoah() throws Exception {
         testWith("Shenandoah GC should have class unloading enabled",
-                true, false,
+                true, true,
                 "-XX:+UnlockExperimentalVMOptions",
                 "-XX:+UseShenandoahGC");
 
--- a/test/hotspot/jtreg/gc/startup_warnings/TestParallelScavengeSerialOld.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/gc/startup_warnings/TestParallelScavengeSerialOld.java	Fri Nov 29 10:02:07 2019 +0000
@@ -28,7 +28,7 @@
 * @key gc
 * @bug 8006398
 * @requires vm.gc.Parallel
-* @summary Test that the ParallelScavenge+SerialOld combination does not print a warning message
+* @summary Test that the ParallelScavenge+SerialOld combination prints a deprecation message
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
 *          java.management
@@ -44,7 +44,7 @@
   public static void main(String args[]) throws Exception {
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParallelGC", "-XX:-UseParallelOldGC", "-version");
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldNotContain("deprecated");
+    output.shouldContain("deprecated");
     output.shouldNotContain("error");
     output.shouldHaveExitValue(0);
   }
--- a/test/hotspot/jtreg/gc/z/TestSmallHeap.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/gc/z/TestSmallHeap.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,7 @@
 
 /*
  * @test TestSmallHeap
- * @requires vm.gc.Z & !vm.graal.enabled
+ * @requires vm.gc.Z & !vm.graal.enabled & vm.compMode != "Xcomp"
  * @summary Test ZGC with small heaps
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx8M gc.z.TestSmallHeap
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx16M gc.z.TestSmallHeap
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Fri Nov 29 10:02:07 2019 +0000
@@ -48,6 +48,7 @@
         {"AllowRedefinitionToAddDeleteMethods", "true"},
         {"CompactFields", "true"},
         {"FieldsAllocationStyle", "1"},
+        {"UseParallelOldGC", "false"},
 
         // deprecated alias flags (see also aliased_jvm_flags):
         {"DefaultMaxRAMFraction", "4"},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/NMT/HugeArenaTracking.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @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:NativeMemoryTracking=detail HugeArenaTracking
+ */
+
+import java.util.Random;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.JDKToolFinder;
+import sun.hotspot.WhiteBox;
+
+public class HugeArenaTracking {
+  private static final long GB = 1024 * 1024 * 1024;
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Long.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    long arena1 = wb.NMTNewArena(1024);
+    long arena2 = wb.NMTNewArena(1024);
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=2KB, committed=2KB)");
+
+    Random rand = new Random();
+
+    // Allocate 2GB+ from arena
+    long total = 0;
+    while (total < 2 * GB) {
+      // Cap to 10M
+      long inc = rand.nextInt(10 * 1024 * 1024);
+      wb.NMTArenaMalloc(arena1, inc);
+      total += inc;
+    }
+
+    ProcessBuilder pb2 = new ProcessBuilder();
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb2.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"});
+    output = new OutputAnalyzer(pb2.start());
+    output.shouldContain("Test (reserved=2GB, committed=2GB)");
+
+    wb.NMTFreeArena(arena1);
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=1KB, committed=1KB)");
+    wb.NMTFreeArena(arena2);
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved");
+  }
+}
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Fri Nov 29 10:02:07 2019 +0000
@@ -111,8 +111,20 @@
             if (coreFileLocation == null) {
                 if (Platform.isOSX()) {
                     File coresDir = new File("/cores");
-                    if (!coresDir.isDirectory() || !coresDir.canWrite()) {
-                        throw new Error("cores is not a directory or does not have write permissions");
+                    if (!coresDir.isDirectory()) {
+                        throw new Error("cores is not a directory");
+                    }
+                    // the /cores directory is usually not writable on macOS 10.15
+                    final String osVersion = System.getProperty("os.version");
+                    if (osVersion == null) {
+                        throw new Error("Cannot query the 'os.version' property!");
+                    }
+                    if (!coresDir.canWrite()) {
+                        if (osVersion.startsWith("10.15")) {
+                            throw new SkippedException("/cores is not writable");
+                        } else {
+                            throw new Error("cores does not have write permissions");
+                        }
                     }
                 } else if (Platform.isLinux()) {
                     // Check if a crash report tool is installed.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/net/httpserver/HttpServerTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,101 @@
+/*
+ * 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 8233185
+ * @summary HttpServer.stop() blocks indefinitely when called on dispatch thread
+ * @modules java.base/sun.net.www
+ * @library /test/lib
+ * @run main/othervm HttpServerTest
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.concurrent.CountDownLatch;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import jdk.test.lib.net.URIBuilder;
+
+public class HttpServerTest implements HttpHandler {
+    private static final int HTTP_STATUS_CODE_OK = 200;
+    private static CountDownLatch serverStopped = new CountDownLatch(1);
+    private final HttpServer server;
+
+
+    public HttpServerTest(HttpServer server) {
+        this.server = server;
+    }
+
+    @Override
+    public void handle(HttpExchange ex) throws IOException {
+
+        sendHttpStatusCode(HTTP_STATUS_CODE_OK, ex);
+
+        System.out.println("Stopping server ...");
+        server.stop(1);
+        serverStopped.countDown();
+    }
+
+    private void sendHttpStatusCode(int httpCode, HttpExchange ex) {
+        try {
+            ex.sendResponseHeaders(httpCode, 0);
+            ex.close();
+        } catch (IOException e) {
+            throw new RuntimeException("Server couldn't send response: " + e, e);
+        }
+    }
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        HttpServer server = HttpServer.create(
+                new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
+
+        try {
+            server.createContext("/context", new HttpServerTest(server));
+            server.start();
+
+            URL url = URIBuilder.newBuilder()
+                    .scheme("http")
+                    .loopback()
+                    .port(server.getAddress().getPort())
+                    .path("/context")
+                    .toURLUnchecked();
+
+            HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
+            System.out.println("Client: Response code received: " + urlc.getResponseCode());
+            InputStream is = urlc.getInputStream();
+            is.readAllBytes();
+            is.close();
+        } finally {
+            serverStopped.await();
+            System.out.println("Server stopped as expected");
+        }
+    }
+}
--- a/test/jdk/java/lang/invoke/CallSiteTest.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/java/lang/invoke/CallSiteTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -24,10 +24,11 @@
 /**
  * @test
  * @summary smoke tests for CallSite
+ * @library /test/lib
  *
  * @build indify.Indify
  * @compile CallSiteTest.java
- * @run main/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
+ * @run main/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -Xbatch
  *      indify.Indify
  *      --expand-properties --classpath ${test.classes}
  *      --java test.java.lang.invoke.CallSiteTest
@@ -40,6 +41,7 @@
 import java.lang.invoke.*;
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
+import static jdk.test.lib.Asserts.*;
 
 public class CallSiteTest {
     private static final Class<?> CLASS = CallSiteTest.class;
@@ -51,16 +53,19 @@
 
     static {
         try {
+
             mh_foo = lookup().findStatic(CLASS, "foo", methodType(int.class, int.class, int.class));
             mh_bar = lookup().findStatic(CLASS, "bar", methodType(int.class, int.class, int.class));
             mcs = new MutableCallSite(mh_foo);
             vcs = new VolatileCallSite(mh_foo);
         } catch (Exception e) {
             e.printStackTrace();
+            throw new Error(e);
         }
     }
 
     public static void main(String... av) throws Throwable {
+        testConstantCallSite();
         testMutableCallSite();
         testVolatileCallSite();
     }
@@ -69,9 +74,61 @@
     private static final int RESULT1 = 762786192;
     private static final int RESULT2 = -21474836;
 
-    private static void assertEquals(int expected, int actual) {
-        if (expected != actual)
-            throw new AssertionError("expected: " + expected + ", actual: " + actual);
+    static final CallSite     MCS         = new MutableCallSite(methodType(void.class));
+    static final MethodHandle MCS_INVOKER = MCS.dynamicInvoker();
+
+    static void test(boolean shouldThrow) {
+        try {
+            MCS_INVOKER.invokeExact();
+            if (shouldThrow) {
+                throw new AssertionError("should throw");
+            }
+        } catch (IllegalStateException ise) {
+            if (!shouldThrow) {
+                throw new AssertionError("should not throw", ise);
+            }
+        } catch (Throwable e) {
+            throw new Error(e);
+        }
+    }
+
+    static class MyCCS extends ConstantCallSite {
+        public MyCCS(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
+            super(targetType, createTargetHook);
+        }
+    }
+
+    private static MethodHandle testConstantCallSiteHandler(CallSite cs, CallSite[] holder) throws Throwable {
+        holder[0] = cs; // capture call site instance for subsequent checks
+
+        MethodType csType = cs.type(); // should not throw on partially constructed instance
+
+        // Truly dynamic invoker for constant call site
+        MethodHandle getTarget = lookup().findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class))
+                                         .bindTo(cs);
+        MethodHandle invoker = MethodHandles.exactInvoker(csType);
+        MethodHandle target = MethodHandles.foldArguments(invoker, getTarget);
+
+        MCS.setTarget(target);
+        // warmup
+        for (int i = 0; i < 20_000; i++) {
+            test(true); // should throw IllegalStateException
+        }
+
+        return MethodHandles.empty(csType); // initialize cs with an empty method handle
+    }
+
+    private static void testConstantCallSite() throws Throwable {
+        CallSite[] holder = new CallSite[1];
+        MethodHandle handler = lookup().findStatic(CLASS, "testConstantCallSiteHandler", MethodType.methodType(MethodHandle.class, CallSite.class, CallSite[].class));
+        handler = MethodHandles.insertArguments(handler, 1, new Object[] { holder } );
+
+        CallSite ccs = new MyCCS(MCS.type(), handler); // trigger call to handler
+
+        if (ccs != holder[0]) {
+            throw new AssertionError("different call site instances");
+        }
+        test(false); // should not throw
     }
 
     private static void testMutableCallSite() throws Throwable {
@@ -83,11 +140,11 @@
         for (int n = 0; n < 2; n++) {
             mcs.setTarget(mh_foo);
             for (int i = 0; i < 5; i++) {
-                assertEquals(RESULT1, runMutableCallSite());
+                assertEQ(RESULT1, runMutableCallSite());
             }
             mcs.setTarget(mh_bar);
             for (int i = 0; i < 5; i++) {
-                assertEquals(RESULT2, runMutableCallSite());
+                assertEQ(RESULT2, runMutableCallSite());
             }
         }
     }
@@ -100,11 +157,11 @@
         for (int n = 0; n < 2; n++) {
             vcs.setTarget(mh_foo);
             for (int i = 0; i < 5; i++) {
-                assertEquals(RESULT1, runVolatileCallSite());
+                assertEQ(RESULT1, runVolatileCallSite());
             }
             vcs.setTarget(mh_bar);
             for (int i = 0; i < 5; i++) {
-                assertEquals(RESULT2, runVolatileCallSite());
+                assertEQ(RESULT2, runVolatileCallSite());
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/DatagramSocket/InterruptibleDatagramSocket.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,106 @@
+/*
+ * 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.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.MulticastSocket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.DatagramChannel;
+import java.util.concurrent.CountDownLatch;
+
+import static java.lang.Thread.sleep;
+
+/*
+ * @test
+ * @summary Check interrupt mechanism for DatagramSocket,
+ *      MulticastSocket, and DatagramSocketAdaptor
+ */
+
+public class InterruptibleDatagramSocket {
+    private static void test0(DatagramSocket s) throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        Thread testThread = Thread.currentThread();
+
+        Thread coordinator = new Thread(() -> {
+            try {
+                latch.await();
+                sleep(500);
+                testThread.interrupt();
+            } catch (InterruptedException e) {
+            }
+        });
+        byte[] data = {0, 1, 2};
+        DatagramPacket p = new DatagramPacket(data, data.length,
+                s.getLocalAddress(), s.getLocalPort());
+        s.setSoTimeout(2000);
+        coordinator.start();
+        latch.countDown();
+        try {
+            s.receive(p);
+        } finally {
+            try {
+                coordinator.join();
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    static void test(DatagramSocket s, boolean interruptible) throws Exception {
+        try {
+            test0(s);
+            throw new RuntimeException("Receive shouldn't have succeeded");
+        } catch (SocketTimeoutException e) {
+            if (interruptible)
+                throw e;
+            System.out.println("Got expected SocketTimeoutException: " + e);
+        } catch (SocketException e) {
+            if ((e.getCause() instanceof ClosedByInterruptException) && interruptible) {
+                System.out.println("Got expected ClosedByInterruptException: " + e);
+            } else {
+                throw e;
+            }
+        } catch (ClosedByInterruptException e) {
+            if (!interruptible)
+                throw e;
+            System.out.println("Got expected ClosedByInterruptException: " + e);
+        }
+        if (s.isClosed() && !interruptible)
+            throw new RuntimeException("DatagramSocket should not be closed");
+        else if (!s.isClosed() && interruptible)
+            throw new RuntimeException("DatagramSocket should be closed");
+    }
+
+    public static void main(String[] args) throws Exception {
+        try (DatagramSocket s = new DatagramSocket()) {
+            test(s, false);
+        }
+        try (DatagramSocket s = new MulticastSocket()) {
+            test(s, false);
+        }
+        try (DatagramSocket s = DatagramChannel.open().socket()) {
+            test(s, true);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/NetworkInterface/NoSetNetworkInterface.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,147 @@
+/*
+ * 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 8233307
+ * @library /test/lib
+ * @run main/othervm NoSetNetworkInterface
+ * @run main/othervm -Djava.net.preferIPv4Stack=true NoSetNetworkInterface
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true NoSetNetworkInterface
+ * @summary Check that methods that are used to set and get the NetworkInterface
+ *  for a MulticastSocket work as expected. This test also checks that getOption
+ *  returns null correctly when a NetworkInterface has not been set
+ */
+
+import jdk.test.lib.NetworkConfiguration;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.NetworkInterface;
+import java.net.StandardSocketOptions;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+public class NoSetNetworkInterface {
+    public static void main(String[] args) throws Exception {
+
+        NetworkConfiguration nc = NetworkConfiguration.probe();
+
+        // check set and get methods work as expected
+        nc.multicastInterfaces(true).forEach(ni -> {
+            checkSetInterface(ni);
+            checkSetNetworkInterface(ni);
+            checkSetOption(ni);
+        });
+
+        // Check that dummy NetworkInterface is returned when not set
+        checkDummyNetworkInterface();
+    }
+
+    public static void checkSetInterface(NetworkInterface ni) {
+        try (MulticastSocket ms = new MulticastSocket()) {
+            Optional<InetAddress> iAddr = ni.inetAddresses()
+                    .filter(Predicate.not(InetAddress::isAnyLocalAddress))
+                    .findFirst();
+            if (iAddr.isPresent()) {
+                ms.setInterface(iAddr.get());
+                checkForCorrectNetworkInterface("setInterface", ms, ni);
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    public static void checkSetNetworkInterface(NetworkInterface ni) {
+        try (MulticastSocket ms = new MulticastSocket()) {
+            ms.setNetworkInterface(ni);
+            checkForCorrectNetworkInterface("setNetworkInterface", ms, ni);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    public static void checkSetOption(NetworkInterface ni) {
+        try (MulticastSocket ms = new MulticastSocket()) {
+            ms.setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
+            checkForCorrectNetworkInterface("setOption", ms, ni);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    public static void checkForCorrectNetworkInterface(String setterMethod,
+                                                       MulticastSocket ms,
+                                                       NetworkInterface ni) throws IOException {
+
+        // getInterface
+        InetAddress testAddr = ms.getInterface();
+        if (!ni.inetAddresses().anyMatch(i -> i.equals(testAddr))) {
+            throw new RuntimeException(setterMethod + " != getInterface");
+        }
+
+        // getNetworkInterface
+        if (!ni.equals(ms.getNetworkInterface())) {
+            throw new RuntimeException(setterMethod + " != getNetworkInterface");
+        }
+
+        // getOption
+        if (!ni.equals(ms.getOption(StandardSocketOptions.IP_MULTICAST_IF))) {
+            throw new RuntimeException(setterMethod + " != getOption");
+        }
+    }
+
+    public static void checkDummyNetworkInterface() throws IOException {
+
+        try(MulticastSocket ms = new MulticastSocket()) {
+
+            // getOption with no Network Interface set
+            NetworkInterface n0 = ms.getOption(StandardSocketOptions.IP_MULTICAST_IF);
+            if (n0 != null) {
+                throw new RuntimeException("NetworkInterface should be null");
+            }
+
+            // getNetworkInterface with no Network Interface set
+            NetworkInterface n1 = ms.getNetworkInterface();
+            if (n1 == null) {
+                throw new RuntimeException("getNetworkInterface() should not return null");
+            } else if (!((n1.getName().equals("0.0.0.0") || n1.getName().equals("::"))
+                    && (n1.getIndex() == 0)
+                    && (n1.inetAddresses().count() == 1))) {
+
+                throw new RuntimeException("Dummy NetworkInterface not returned as expected");
+            }
+
+            // getInterface with no Network Interface set
+            InetAddress iaddr = ms.getInterface();
+            if (iaddr == null) {
+                throw new RuntimeException("getInterface() should not return null");
+            } else if (!iaddr.isAnyLocalAddress()) {
+                throw new RuntimeException("getInterface() should return anyLocalAddress");
+            }
+        }
+    }
+}
+
--- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -91,7 +92,7 @@
      */
     public static SocketChannel launchWithSocketChannel(String className, String options[], String args[]) throws IOException {
         ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.socket().bind(new InetSocketAddress(0));
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
         InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(),
                                                       ssc.socket().getLocalPort());
         SocketChannel sc1 = SocketChannel.open(isa);
@@ -120,7 +121,7 @@
         throws IOException
     {
         ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.socket().bind(new InetSocketAddress(0));
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
         int port = ssc.socket().getLocalPort();
         launch(className, options, args, Util.getFD(ssc));
         ssc.close();
@@ -147,18 +148,18 @@
     public static DatagramChannel launchWithDatagramChannel(String className, String options[], String args[])
         throws IOException
     {
+        InetAddress address = InetAddress.getLocalHost();
+        if (address.isLoopbackAddress()) {
+            address = InetAddress.getLoopbackAddress();
+        }
         DatagramChannel dc = DatagramChannel.open();
-        dc.socket().bind(new InetSocketAddress(0));
+        dc.socket().bind(new InetSocketAddress(address, 0));
 
         int port = dc.socket().getLocalPort();
         launch(className, options, args, Util.getFD(dc));
         dc.close();
 
         dc = DatagramChannel.open();
-        InetAddress address = InetAddress.getLocalHost();
-        if (address.isLoopbackAddress()) {
-            address = InetAddress.getLoopbackAddress();
-        }
         InetSocketAddress isa = new InetSocketAddress(address, port);
 
         dc.connect(isa);
--- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -35,6 +35,7 @@
  */
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.net.InetAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.DatagramChannel;
 import java.nio.channels.SelectionKey;
@@ -66,6 +67,7 @@
         /*
          * Wait for service to connect
          */
+        System.err.println("Waiting for the service to connect");
         ssc.configureBlocking(false);
         sk = ssc.register(sel, SelectionKey.OP_ACCEPT);
         long to = Utils.adjustTimeout(15*1000);
@@ -89,6 +91,7 @@
         /*
          * Wait for service to report test result
          */
+        System.err.println("Waiting for the service to report test result");
         sc.configureBlocking(false);
         sk = sc.register(sel, SelectionKey.OP_READ);
         to = Utils.adjustTimeout(5000);
@@ -111,6 +114,7 @@
                 throw new IOException("Timed out waiting for service to report test result");
             }
         }
+        System.err.println("Cleaning up");
         sk.cancel();
         sc.close();
         sel.close();
@@ -118,6 +122,7 @@
         /*
          * Examine the test result
          */
+        System.err.println("Examine test result");
         bb.flip();
         byte b = bb.get();
 
@@ -152,7 +157,8 @@
          * from the service.
          */
         ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.socket().bind(new InetSocketAddress(0));
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        System.err.println("Listener bound to: " + ssc.socket().getLocalSocketAddress());
 
         /*
          * The port is passed to the service as an argument.
@@ -164,7 +170,9 @@
         /*
          * Launch service with a SocketChannel (tcp nowait)
          */
+        System.err.println("launchWithSocketChannel");
         SocketChannel sc = Launcher.launchWithSocketChannel(TEST_SERVICE, options, arg);
+        System.err.println("Waiting for test results");
         waitForTestResult(ssc, expectFail);
         sc.close();
 
@@ -173,6 +181,7 @@
          * launchWithServerSocketChannel establishes a connection to the service
          * and the returned SocketChannel is connected to the service.
          */
+        System.err.println("launchWithServerSocketChannel");
         sc = Launcher.launchWithServerSocketChannel(TEST_SERVICE, options, arg);
         waitForTestResult(ssc, expectFail);
         sc.close();
@@ -180,10 +189,12 @@
         /*
          * Launch service with a DatagramChannel (udp wait)
          */
+        System.err.println("launchWithDatagramChannel");
         DatagramChannel dc = Launcher.launchWithDatagramChannel(TEST_SERVICE, options, arg);
         waitForTestResult(ssc, expectFail);
         dc.close();
 
+        System.err.println("done");
         if (failures > 0) {
             throw new RuntimeException("Test failed - see log for details");
         } else {
--- a/test/jdk/javax/net/ssl/TLS/TLSClientPropertyTest.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/javax/net/ssl/TLS/TLSClientPropertyTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8049432 8069038
+ * @bug 8049432 8069038 8234723
  * @summary New tests for TLS property jdk.tls.client.protocols
  * @summary javax/net/ssl/TLS/TLSClientPropertyTest.java needs to be
  *     updated for JDK-8061210
@@ -40,6 +40,8 @@
  * @run main/othervm TLSClientPropertyTest TLSv1
  * @run main/othervm TLSClientPropertyTest TLSv11
  * @run main/othervm TLSClientPropertyTest TLSv12
+ * @run main/othervm TLSClientPropertyTest TLSv13
+ * @run main/othervm TLSClientPropertyTest TLS
  * @run main/othervm TLSClientPropertyTest WrongProperty
  */
 
@@ -57,7 +59,7 @@
  */
 public class TLSClientPropertyTest {
     private final String[] expectedSupportedProtos = new String[] {
-            "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
+            "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"
     };
 
     public static void main(String[] args) throws Exception {
@@ -77,7 +79,7 @@
             }
             contextProtocol = null;
             expectedDefaultProtos = new String[] {
-                    "TLSv1", "TLSv1.1", "TLSv1.2"
+                    "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"
             };
             break;
         case "SSLv3":
@@ -103,6 +105,13 @@
                     "TLSv1", "TLSv1.1", "TLSv1.2"
             };
             break;
+        case "TLSv13":
+        case "TLS":
+            contextProtocol = "TLSv1.3";
+            expectedDefaultProtos = new String[] {
+                    "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"
+            };
+            break;
         case "WrongProperty":
             expectedDefaultProtos = new String[] {};
             contextProtocol = "TLSV";
--- a/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/javax/net/ssl/TLS/TestJSSEClientDefaultProtocol.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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 8049429
+ * @bug 8049429 8234723
  * @modules java.management
  *          jdk.crypto.ec/sun.security.ec
  * @summary Test that all cipher suites work in all versions and all client
@@ -33,23 +33,35 @@
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1
  *              -DCLIENT_PROTOCOL=DEFAULT
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_CBC_SHA
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
  *              -DCLIENT_PROTOCOL=DEFAULT
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_GCM_SHA256
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
  *              -DCLIENT_PROTOCOL=DEFAULT
  *              -Djdk.tls.client.protocols=TLSv1
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_CBC_SHA
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1
  *              -DCLIENT_PROTOCOL=DEFAULT
  *              -Djdk.tls.client.protocols=TLSv1.2
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_GCM_SHA256
+ *          TestJSSE javax.net.ssl.SSLHandshakeException
+ * @run main/othervm
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=DEFAULT
+ *              -Djdk.tls.client.protocols=TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
+ *          TestJSSE
+ * @run main/othervm
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1
+ *              -DCLIENT_PROTOCOL=DEFAULT
+ *              -Djdk.tls.client.protocols=TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
  *          TestJSSE javax.net.ssl.SSLHandshakeException
  */
--- a/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/javax/net/ssl/TLS/TestJSSEClientProtocol.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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 8049429 8172273
+ * @bug 8049429 8172273 8234723
  * @modules java.management
  *          jdk.crypto.ec/sun.security.ec
  * @summary Test that all cipher suites work in all versions and all client
@@ -31,21 +31,26 @@
  *          and all checking is done on the client side.
  * @compile CipherTestUtils.java JSSEClient.java JSSEServer.java
  * @run main/othervm
- *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
  *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
  *          TestJSSE
  * @run main/othervm
- *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
  *              -DCIPHER=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  *          TestJSSE
  * @run main/othervm
- *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
  *              -DCIPHER=TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  *          TestJSSE
  * @run main/othervm
+ *              -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
+ *          TestJSSE
+ * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv3
  *              -DCLIENT_PROTOCOL=SSLv3
  *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
@@ -53,16 +58,21 @@
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv3,TLSv1
  *              -DCLIENT_PROTOCOL=TLSv1
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_CBC_SHA
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=SSLv3,TLSv1,TLSv1.1
  *              -DCLIENT_PROTOCOL=TLSv1.1
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_256_CBC_SHA
  *          TestJSSE
  * @run main/othervm
- *              -DSERVER_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2
+ *              -DSERVER_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
  *              -DCLIENT_PROTOCOL=TLSv1.2
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_GCM_SHA256
+ *          TestJSSE
+ * @run main/othervm
+ *              -DSERVER_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCLIENT_PROTOCOL=TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
  *          TestJSSE
  */
--- a/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/javax/net/ssl/TLS/TestJSSEServerProtocol.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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 8049429
+ * @bug 8049429 8234723
  * @modules java.management
  *          jdk.crypto.ec/sun.security.ec
  * @summary Test that all cipher suites work in all versions and all client
@@ -38,16 +38,26 @@
  * @run main/othervm
  *              -DSERVER_PROTOCOL=TLSv1
  *              -DCLIENT_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_CBC_SHA
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=TLSv1.1
  *              -DCLIENT_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_256_CBC_SHA
  *          TestJSSE
  * @run main/othervm
  *              -DSERVER_PROTOCOL=TLSv1.2
  *              -DCLIENT_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2
- *              -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
+ *              -DCIPHER=TLS_RSA_WITH_AES_128_GCM_SHA256
+ *          TestJSSE
+ * @run main/othervm
+ *              -DSERVER_PROTOCOL=TLSv1.3
+ *              -DCLIENT_PROTOCOL=SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
  *          TestJSSE
+ * @run main/othervm
+ *              -DSERVER_PROTOCOL=TLSv1.2
+ *              -DCLIENT_PROTOCOL=TLSv1.3
+ *              -DCIPHER=TLS_AES_256_GCM_SHA384
+ *          TestJSSE javax.net.ssl.SSLHandshakeException
  */
--- a/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -124,7 +124,6 @@
     private static final String pathToStores = "../etc";
     private static final String keyStoreFile = "keystore";
     private static final String trustStoreFile = "truststore";
-    private static final String passwd = "passphrase";
     private static final String keyFilename =
             System.getProperty("test.src", ".") + "/" + pathToStores
             + "/" + keyStoreFile;
@@ -146,7 +145,7 @@
         }
 
         String [] protocols = new String [] {
-            "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" };
+            "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" };
 
         for (String protocol : protocols) {
             log("Testing " + protocol);
--- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,11 +25,15 @@
 
 package jdk.jfr.api.consumer.recordingstream;
 
+import java.time.Instant;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
 
 import jdk.jfr.Event;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.EventStream;
 import jdk.jfr.consumer.RecordingStream;
 
 /**
@@ -51,6 +55,7 @@
         testCloseTwice();
         testCloseStreaming();
         testCloseMySelf();
+        testCloseNoEvents();
     }
 
     private static void testCloseMySelf() throws Exception {
@@ -122,6 +127,26 @@
         log("Leaving testCloseTwice()");
     }
 
+    private static void testCloseNoEvents() throws Exception {
+        try (Recording r = new Recording()) {
+            r.start();
+            CountDownLatch finished = new CountDownLatch(2);
+            AtomicReference<Thread> streamingThread = new AtomicReference<>();
+            try (EventStream es = EventStream.openRepository()) {
+                es.setStartTime(Instant.EPOCH);
+                es.onFlush( () -> {
+                    streamingThread.set(Thread.currentThread());
+                    finished.countDown();;
+                });
+                es.startAsync();
+                finished.await();
+            } // <- EventStream::close should terminate thread
+            while (streamingThread.get().isAlive()) {
+                Thread.sleep(10);
+            }
+        }
+    }
+
     private static void log(String msg) {
         System.out.println(msg);
     }
--- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestSetEndTime.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestSetEndTime.java	Fri Nov 29 10:02:07 2019 +0000
@@ -63,6 +63,14 @@
     public static void main(String... args) throws Exception {
         testEventStream();
         testRecordingStream();
+        testEmptyStream();
+    }
+
+    private static void testEmptyStream() {
+        try (RecordingStream rs = new RecordingStream()) {
+            rs.setEndTime(Instant.now().plusMillis(1100));
+            rs.start();
+        }
     }
 
     private static void testRecordingStream() throws Exception {
@@ -89,10 +97,10 @@
                 }
                 closed.await();
                 System.out.println("Found events: " + count.get());
-                if (count.get() < 50) {
+                if (count.get() > 0 && count.get() < 50) {
                     return;
                 }
-                System.out.println("Found 50 events. Retrying");
+                System.out.println("Retrying");
                 System.out.println();
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/jfr/jvm/TestFormatDuration.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.jfr.jvm;
+
+import jdk.jfr.internal.Utils;
+import jdk.test.lib.Asserts;
+
+import java.time.Duration;
+import java.util.Locale;
+
+/**
+ * @test
+ * @key jfr
+ * @requires vm.hasJFR
+ * @library /test/lib
+ * @modules jdk.jfr/jdk.jfr.internal
+ * @run main/othervm jdk.jfr.jvm.TestFormatDuration
+ */
+public class TestFormatDuration {
+    public static void main(String[] args) throws Exception{
+        Locale.setDefault(Locale.US);
+
+        // Nanoseconds
+        assertDuration("0 ns   ", "0 s");
+        assertDuration("1 ns   ", "0.000001 ms");
+        assertDuration("10 ns  ", "0.000010 ms");
+        assertDuration("100 ns ", "0.000100 ms");
+        assertDuration("999 ns ", "0.000999 ms");
+        assertDuration("1000 ns", "0.00100 ms");
+        assertDuration("1004 ns", "0.00100 ms");
+        assertDuration("1005 ns", "0.00101 ms");
+
+        // 10 us
+        assertDuration("9 us 994 ns", "0.00999 ms");
+        assertDuration("9 us 995 ns", "0.0100 ms");
+        assertDuration("10 us      ", "0.0100 ms");
+        assertDuration("10 us 49 ns", "0.0100 ms");
+        assertDuration("10 us 50 ns", "0.0101 ms");
+
+        // 100 us
+        assertDuration("99 us 949 ns ", "0.0999 ms");
+        assertDuration("99 us 950 ns ", "0.100 ms");
+        assertDuration("100 us       ", "0.100 ms");
+        assertDuration("100 us 499 ns", "0.100 ms");
+        assertDuration("100 us 500 ns", "0.101 ms");
+
+        // 1 ms
+        assertDuration("999 us 499 ns       ", "0.999 ms");
+        assertDuration("999 us 500 ns       ", "1.00 ms");
+        assertDuration("1 ms                ", "1.00 ms");
+        assertDuration("1 ms 4 us 999 ns    ", "1.00 ms");
+        assertDuration("1 ms 5 us", "1.01 ms");
+
+        // 10 ms
+        assertDuration("9 ms 994 us 999 ns", "9.99 ms");
+        assertDuration("9 ms 995 us       ", "10.0 ms");
+        assertDuration("10 ms             ", "10.0 ms");
+        assertDuration("10 ms 49 us 999 ns", "10.0 ms");
+        assertDuration("10 ms 50 us 999 ns", "10.1 ms");
+
+        // 100 ms
+        assertDuration("99 ms 949 us 999 ns ", "99.9 ms");
+        assertDuration("99 ms 950 us 000 ns ", "100 ms");
+        assertDuration("100 ms              ", "100 ms");
+        assertDuration("100 ms 499 us 999 ns", "100 ms");
+        assertDuration("100 ms 500 us       ", "101 ms");
+
+        // 1 second
+        assertDuration("999 ms 499 us 999 ns  ", "999 ms");
+        assertDuration("999 ms 500 us         ", "1.00 s");
+        assertDuration("1 s                   ", "1.00 s");
+        assertDuration("1 s 4 ms 999 us 999 ns", "1.00 s");
+        assertDuration("1 s 5 ms              ", "1.01 s");
+
+        // 10 seconds
+        assertDuration("9 s 994 ms 999 us 999 ns ", "9.99 s");
+        assertDuration("9 s 995 ms               ", "10.0 s");
+        assertDuration("10 s                     ", "10.0 s");
+        assertDuration("10 s 049 ms 999 us 999 ns", "10.0 s");
+        assertDuration("10 s 050 ms              ", "10.1 s");
+
+        // 1 minute
+        assertDuration("59 s 949 ms 999 us 999 ns", "59.9 s");
+        assertDuration("59 s 950 ms              ", "1 m 0 s");
+        assertDuration("1 m 0 s                  ", "1 m 0 s");
+        assertDuration("60 s 499 ms 999 us 999 ns", "1 m 0 s");
+        assertDuration("60 s 500 ms              ", "1 m 1 s");
+
+        // 10 minutes
+        assertDuration("10 m 0 s", "10 m 0 s");
+
+        // 1 hour
+        assertDuration("59 m 59 s 499 ms 999 us 999 ns", "59 m 59 s");
+        assertDuration("59 m 59 s 500 ms              ", "1 h 0 m");
+        assertDuration("1 h 0 m                       ", "1 h 0 m");
+        assertDuration("1 h 29 s 999 ms 999 us 999 ns ", "1 h 0 m");
+        assertDuration("1 h 30 s                      ", "1 h 1 m");
+
+        // 1 day
+        assertDuration("23 h 59 m 29 s 999 ms 999 us 999 ns", "23 h 59 m");
+        assertDuration("23 h 59 m 30 s                     ", "1 d 0 h");
+        assertDuration("1 d 0 h                            ", "1 d 0 h");
+        assertDuration("1 d 29 m 59 s 999 ms 999 us 999 ns ", "1 d 0 h");
+        assertDuration("1 d 30 m                           ", "1 d 1 h");
+
+        // 100 days
+        assertDuration("100 d 13 h", "100 d 13 h");
+
+        // 1000 days
+        assertDuration("1000 d 13 h", "1000 d 13 h");
+    }
+
+    private static void assertDuration(String value, String expected) throws Exception {
+        long nanos = parse(value);
+        System.out.println(value + " == " + expected + " ? (" + nanos + " ns) ");
+        Asserts.assertEquals(Utils.formatDuration(Duration.ofNanos(nanos)), expected);
+        if (nanos != 0) {
+            Asserts.assertEquals(Utils.formatDuration(Duration.ofNanos(-nanos)), "-" + expected);
+        }
+    }
+
+
+    private static long parse(String duration) throws Exception {
+        String[] t = duration.trim().split(" ");
+        long nanos = 0;
+        for (int i = 0; i < t.length - 1; i += 2) {
+            nanos += Long.parseLong(t[i]) * parseUnit(t[i + 1]);
+        }
+        return nanos;
+    }
+
+    private static long parseUnit(String unit) throws Exception {
+        switch (unit) {
+            case "ns":
+                return 1L;
+            case "us":
+                return 1_000L;
+            case "ms":
+                return 1_000_000L;
+            case "s":
+                return 1_000_000_000L;
+            case "m":
+                return 60 * 1_000_000_000L;
+            case "h":
+                return 3600 * 1_000_000_000L;
+            case "d":
+                return 24 * 3600 * 1_000_000_000L;
+        }
+        throw new Exception("Test error. Unknown unit " + unit);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,552 @@
+/*
+ * 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 8233223
+ * @summary Interoperability tests with Amazon's CA1, CA2, CA3, and CA4
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath AmazonCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath AmazonCA CRL
+ */
+
+/*
+ * Obtain TLS test artifacts for Amazon CAs from:
+ *
+ * Amazon Root CA 1
+ *     Valid - https://good.sca1a.amazontrust.com/
+ *     Revoked - https://revoked.sca1a.amazontrust.com/
+ * Amazon Root CA 2
+ *     Valid - https://good.sca2a.amazontrust.com/
+ *     Revoked - https://revoked.sca2a.amazontrust.com/
+ * Amazon Root CA 3
+ *     Valid - https://good.sca3a.amazontrust.com/
+ *     Revoked - https://revoked.sca3a.amazontrust.com/
+ * Amazon Root CA 4
+ *     Valid - https://good.sca4a.amazontrust.com/
+ *     Revoked - https://revoked.sca4a.amazontrust.com/
+ */
+public class AmazonCA {
+
+    public static void main(String[] args) throws Exception {
+
+        ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+        boolean ocspEnabled = false;
+
+        if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+            pathValidator.enableCRLCheck();
+        } else {
+            // OCSP check by default
+            pathValidator.enableOCSPCheck();
+            ocspEnabled = true;
+        }
+
+        new AmazonCA_1().runTest(pathValidator, ocspEnabled);
+        new AmazonCA_2().runTest(pathValidator, ocspEnabled);
+        new AmazonCA_3().runTest(pathValidator, ocspEnabled);
+        new AmazonCA_4().runTest(pathValidator, ocspEnabled);
+    }
+}
+
+class AmazonCA_1 {
+
+    // Owner: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US
+    // Issuer: CN=Amazon Root CA 1, O=Amazon, C=US
+    // Serial number: 67f9457508c648c09ca652e71791830e72592
+    // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIERzCCAy+gAwIBAgITBn+UV1CMZIwJymUucXkYMOclkjANBgkqhkiG9w0BAQsF\n" +
+            "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" +
+            "b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\n" +
+            "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\n" +
+            "IDFBMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" +
+            "AoIBAQCeQM3XCsIZunv8bSJxOqkc/ed87uL76FDB7teBNThDRB+1J7aITuadbNfH\n" +
+            "5ZfZykrdZ1qQLKxP6DwHOmJr9u2b4IxjUX9qUMuq4B02ghD2g6yU3YivEosZ7fpo\n" +
+            "srD2TBN29JpgPGrOrpOE+ArZuIpBjdKFinemu6fTDD0NCeQlfyHXd1NOYyfYRLTa\n" +
+            "xlpDqr/2M41BgSkWQfSPHHyRWNQgWBiGsIQaS8TK0g8OWi1ov78+2K9DWT+AHgXW\n" +
+            "AanjZK91GfygPXJYSlAGxSiBAwH/KhAMifhaoFYAbH0Yuohmd85B45G2xVsop4TM\n" +
+            "Dsl007U7qnS7sdJ4jYGzEvva/a95AgMBAAGjggE5MIIBNTASBgNVHRMBAf8ECDAG\n" +
+            "AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUYtRCXoZwdWqQvMa40k1g\n" +
+            "wjS6UTowHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH\n" +
+            "AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy\n" +
+            "dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy\n" +
+            "dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js\n" +
+            "LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBEGA1UdIAQKMAgw\n" +
+            "BgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEAMHbSWHRFMzGNIE0qhN6gnRahTrTU\n" +
+            "CDPwe7l9/q0IA+QBlrpUHnlAreetYeH1jB8uF3qXXzy22gpBU7NqulTkqSPByT1J\n" +
+            "xOhpT2FpO5R3VAdMPdWfSEgtrED0jkmyUQrR1T+/A+nBLdJZeQcl+OqLgeY790JM\n" +
+            "JJTsJnnI6FBWeTGhcDI4Y+n3KS3QCVePeWI7jx1dhrHcXH+QDX8Ywe31hV7YENdr\n" +
+            "HDpUXrjK6eHN8gazy8G6pndXHFwHp4auiZbJbYAk/q1peOTRagD2JojcLkm+i3cD\n" +
+            "843t4By6YT/PVlePU2PCWejkrJQnKQAPOov7IA8kuO2RDWuzE/zF6Hotdg==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=good.sca1a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US
+    // Serial number: 703e4e4bbd78e2b6db5634f36c4ee944cb1a4
+    // Valid from: Mon Jul 29 16:53:36 PDT 2019 until: Sat Aug 29 16:53:36 PDT 2020
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIFEzCCA/ugAwIBAgITBwPk5LvXjitttWNPNsTulEyxpDANBgkqhkiG9w0BAQsF\n" +
+            "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" +
+            "ZXIgQ0EgMUExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzUzMzZaFw0yMDA4\n" +
+            "MjkyMzUzMzZaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" +
+            "AQITCERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4G\n" +
+            "A1UEBRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n" +
+            "EDAOBgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNl\n" +
+            "czEjMCEGA1UEAxMaZ29vZC5zY2ExYS5hbWF6b250cnVzdC5jb20wggEiMA0GCSqG\n" +
+            "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQyuJ83c2Zf9k29f6iLqd8nJSuHSk1v+SS\n" +
+            "0sYyG8tjscfCC1HcOdNj37vtiNN65sXh/e/kBKH9wvzhCLOJbBqVKRHOZuHdJEpH\n" +
+            "35R6C/PbcV/tp49g6mNmBe+lcmm/cwwCtYvkL0rgL/OKB0liFhhRIqy2TPg08op/\n" +
+            "RlY2DdbgBA2B3g7wdMo0hK3SO56/QUccUtLRm43km9Yd4E3U+CEUyDd0Bmc/YbPa\n" +
+            "htuXVsXJwiwlwooomujIIENhFw3htdcsu2apRj8EYUrKL8Mvvn+h16gDyobj0f01\n" +
+            "jWXlUgmH2lzUzca5eGuphfvmWN/ME/yqC2mMvWGnWySycqtT8VdJAgMBAAGjggFj\n" +
+            "MIIBXzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYEFFENOZBwFkjVdQX0iK32c77z\n" +
+            "SUl6MB8GA1UdIwQYMBaAFGLUQl6GcHVqkLzGuNJNYMI0ulE6MB0GA1UdJQQWMBQG\n" +
+            "CCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcBAQRpMGcwLQYIKwYBBQUHMAGG\n" +
+            "IWh0dHA6Ly9vY3NwLnNjYTFhLmFtYXpvbnRydXN0LmNvbTA2BggrBgEFBQcwAoYq\n" +
+            "aHR0cDovL2NydC5zY2ExYS5hbWF6b250cnVzdC5jb20vc2NhMWEuY2VyMCUGA1Ud\n" +
+            "EQQeMByCGmdvb2Quc2NhMWEuYW1hem9udHJ1c3QuY29tMFAGA1UdIARJMEcwDQYL\n" +
+            "YIZIAYb9bgEHGAMwNgYFZ4EMAQEwLTArBggrBgEFBQcCARYfaHR0cHM6Ly93d3cu\n" +
+            "YW1hem9udHJ1c3QuY29tL2NwczANBgkqhkiG9w0BAQsFAAOCAQEAmn7z6Ub1sL77\n" +
+            "wyUEaCq/Odqm+2RtYYMJ1MeW6nTXTfAgZ/iLx/6hStafd9AK9gHiTCggBpj6KgnF\n" +
+            "UsGMDeX879jP675fH6SEk710QPDhIrfAzwE0pF/eUNsd7pLwne32zHX0ouCoAt4d\n" +
+            "KwBCZkKNUkdj4U+bpOJzvtcTP9JlzziLp9IFRjjQh3xKgfblx57CmRJbqH3fT5JJ\n" +
+            "IAIDVTz3ZUcqhPTFAnNsO1oNBEyrO5X9rwCiSy7aRijY/11R75mIIvyA9zyd9ss1\n" +
+            "kvrrER0GWMTDvC84FZD2vhkXgPTFrB1Dn9f3QgO5APT9GCFY5hdpqqPEXOSdRzQo\n" +
+            "h9j4OQAqtA==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=revoked.sca1a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US
+    // Serial number: 6f1d774ad5e7b6d251d217661782bbdb6f37d
+    // Valid from: Mon Jan 28 15:34:38 PST 2019 until: Thu Apr 28 16:34:38 PDT 2022
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIE2zCCA8OgAwIBAgITBvHXdK1ee20lHSF2YXgrvbbzfTANBgkqhkiG9w0BAQsF\n" +
+            "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" +
+            "ZXIgQ0EgMUExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzM0MzhaFw0yMjA0\n" +
+            "MjgyMzM0MzhaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" +
+            "AQITCERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYD\n" +
+            "VQQFEwc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ\n" +
+            "MA4GA1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2Vz\n" +
+            "MSYwJAYDVQQDEx1yZXZva2VkLnNjYTFhLmFtYXpvbnRydXN0LmNvbTCCASIwDQYJ\n" +
+            "KoZIhvcNAQEBBQADggEPADCCAQoCggEBANUoHop9sW+QlgVsdtacioraTAWHcSTd\n" +
+            "MNkOkOEMgJIFPyfdcDvW/H2NvpdYeIQqzaCgT2kcsONWTZTPJMirCPnzl1ohHOZU\n" +
+            "uTnOVkamGxvNmQCURLBXmlCMRTCI5RY3CuYntFFbSPAnbumsF+K/gKqcE6ME53Bw\n" +
+            "PAwn4qwavB0i5Ib7Jk8XYzxSYXC9l8QLxt6fshPJRlecpXzfmVFvMAm3IbaLcpuv\n" +
+            "AtD+8I2KwjNtBPRPNYeFsWxwsgUGAyHEGa61oTGUqqAXu5YmPfyK+YTOJdoofsh4\n" +
+            "Tf3K7AKxnPWuvY3RNTs1pzEVwJYZqSsNwbgyKJJ4+0Xe4iP7qB8SYf8CAwEAAaOC\n" +
+            "ASkwggElMA4GA1UdDwEB/wQEAwIFoDAdBgNVHQ4EFgQUGHreoz+LP/Wr+RKzuexO\n" +
+            "V8ICtmEwHwYDVR0jBBgwFoAUYtRCXoZwdWqQvMa40k1gwjS6UTowHQYDVR0lBBYw\n" +
+            "FAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw\n" +
+            "AYYhaHR0cDovL29jc3Auc2NhMWEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC\n" +
+            "hipodHRwOi8vY3J0LnNjYTFhLmFtYXpvbnRydXN0LmNvbS9zY2ExYS5jZXIwKAYD\n" +
+            "VR0RBCEwH4IdcmV2b2tlZC5zY2ExYS5hbWF6b250cnVzdC5jb20wEwYDVR0gBAww\n" +
+            "CjAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBABSbe1UCLL7Qay6XK5wD8B5a\n" +
+            "wvR1XG3UrggpVIz/w5cutEm/yE71hzE0gag/3YPbNYEnaLbJH+9jz4YW9wd/cEPj\n" +
+            "xSK5PErAQjCd+aA4LKN1xqkSysgYknl0y47hJBXGnWf+hxvBBHeSoUzM0KIC21pC\n" +
+            "ZyXrmfaPCQAz13ruYIYdQaETqXGVORmKbf/a+Zn18/tfQt0LeeCYVoSopbXWQvcJ\n" +
+            "gUMtdIqYQmb8aVj0pdZXwKl4yZ2DtlS3Z9MpWNgQNlhRPmiYlu28y2yTtZ9SwD6m\n" +
+            "2f+cwc19aJrDT4Y280px+jRU7dIE6oZVJU+yBRVIZYpUFAB7extCMVxnTkCf8Dk=\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception {
+        // EE certificates don't have CRLDP extension
+        if (!ocspEnabled){
+            pathValidator.validate(new String[]{INT},
+                    ValidatePathWithParams.Status.GOOD, null, System.out);
+
+            return;
+        }
+
+        // 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,
+                "Mon Jan 28 15:35:56 PST 2019", System.out);
+    }
+}
+
+class AmazonCA_2 {
+
+    // Owner: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US
+    // Issuer: CN=Amazon Root CA 2, O=Amazon, C=US
+    // Serial number: 67f945755f187a91f8163f3e624620177ff38
+    // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGRzCCBC+gAwIBAgITBn+UV1Xxh6kfgWPz5iRiAXf/ODANBgkqhkiG9w0BAQwF\n" +
+            "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" +
+            "b24gUm9vdCBDQSAyMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\n" +
+            "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\n" +
+            "IDJBMQ8wDQYDVQQDEwZBbWF6b24wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" +
+            "AoICAQC0P8hSLewmrZ41CCPBQytZs5NBFMq5ztbnMf+kZUp9S25LPfjNW3zgC/6E\n" +
+            "qCTWNVMMHhq7ez9IQJk48qbfBTLlZkuKnUWbA9vowrDfcxUN0mRE4B/TJbveXyTf\n" +
+            "vE91iDlqDrERecE9D8sdjzURrtHTp27lZdRkXFvfEVCq4hl3sHkzjodisaQthLp1\n" +
+            "gLsiA7vKt+8zcL4Aeq52UyYb8r4/jdZ3KaQp8O/T4VwDCRKm8ey3kttpJWaflci7\n" +
+            "eRzNjY7gE3NMANVXCeQwOBfH2GjINFCObmPsqiBuoAnsv2k5aQLNoU1OZk08ClXm\n" +
+            "mEZ2rI5qZUTX1HuefBJnpMkPugFCw8afaHnB13SkLE7wxX8SZRdDIe5WiwyDL1tR\n" +
+            "2+8lpz4JsMoFopHmD3GaHyjbN+hkOqHgLltwewOsiyM0u3CZphypN2KeD+1FLjnY\n" +
+            "TgdIAd1FRgK2ZXDDrEdjnsSEfShKf0l4mFPSBs9E3U6sLmubDRXKLLLpa/dF4eKu\n" +
+            "LEKS1bXYT28iM6D5gSCnzho5G4d18jQD/slmc5XmRo5Pig0RyBwDaLuxeIZuiJ0A\n" +
+            "J6YFhffbrLYF5dEQl0cU+t3VBK5u/o1WkWXsZawU038lWn/AXerodT/pAcrtWA4E\n" +
+            "NQEN09WEKMhZVPhqdwhF/Gusr04mQtKt7T2v6UMQvtVglv5E7wIDAQABo4IBOTCC\n" +
+            "ATUwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYE\n" +
+            "FNpDStD8AcBLv1gnjHbNCoHzlC70MB8GA1UdIwQYMBaAFLAM8Eww9AVYAkj9M+VS\n" +
+            "r0uE42ZSMHsGCCsGAQUFBwEBBG8wbTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3Au\n" +
+            "cm9vdGNhMi5hbWF6b250cnVzdC5jb20wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcnQu\n" +
+            "cm9vdGNhMi5hbWF6b250cnVzdC5jb20vcm9vdGNhMi5jZXIwPwYDVR0fBDgwNjA0\n" +
+            "oDKgMIYuaHR0cDovL2NybC5yb290Y2EyLmFtYXpvbnRydXN0LmNvbS9yb290Y2Ey\n" +
+            "LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggIBAEO5W+iF\n" +
+            "yChjDyyrmiwFupVWQ0Xy2ReFNQiZq7XKVHvsLQe01moSLnxcBxioOPBKt1KkZO7w\n" +
+            "Gcbmke0+7AxLaG/F5NPnzRtK1/pRhXQ0XdU8pVh/1/h4GoqRlZ/eN0JDarUhZPkV\n" +
+            "kSr96LUYDTxcsAidF7zkzWfmtcJg/Aw8mi14xKVEa6aVyKu54c8kKkdlt0WaigOv\n" +
+            "Z/xYhxp24AfoFKaIraDNdsD8q2N7eDYeN4WGLzNSlil+iFjzflI9mq1hTuI/ZNjV\n" +
+            "rbvob6FUQ8Cc524gMjbpZCNuZ1gfXzwwhGp0AnQF6CJsWF9uwPpZEVFnnnfiWH3M\n" +
+            "oup41EvBhqaAqOlny0sm5pI82nRUCAE3DLkJ1+eAtdQaYblZQkQrRyTuPmJEm+5y\n" +
+            "QwdDVw6uHc5OsSj/tyhh8zJ2Xq3zgh3dMONGjJEysxGaCoIb+61PWwMy2dIarVwI\n" +
+            "r+c+AY+3PrhgBspNdWZ87JzNHii7ksdjUSVGTTy1vGXgPYrv0lp0IMnKaZP58xiw\n" +
+            "rDx7uTlQuPVWNOZvCaT3ZcoxTsNKNscIUe+WJjWx5hdzpv/oksDPY5ltZ0j3hlDS\n" +
+            "D+Itk95/cNJVRM/0HpxI1SX9MTZtOSJoEDdUtOpVaOuBAvEK4gvTzdt0r5L+fuI6\n" +
+            "o5LAuRo/LO1xVRH49KFRoaznzU3Ch9+kbPb3\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=good.sca2a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US
+    // Serial number: 703e4e70616c90d611fd04a5ecc635665184e
+    // Valid from: Mon Jul 29 16:54:06 PDT 2019 until: Sat Aug 29 16:54:06 PDT 2020
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIHEzCCBPugAwIBAgITBwPk5wYWyQ1hH9BKXsxjVmUYTjANBgkqhkiG9w0BAQwF\n" +
+            "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" +
+            "ZXIgQ0EgMkExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU0MDZaFw0yMDA4\n" +
+            "MjkyMzU0MDZaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" +
+            "AQITCERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4G\n" +
+            "A1UEBRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n" +
+            "EDAOBgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNl\n" +
+            "czEjMCEGA1UEAxMaZ29vZC5zY2EyYS5hbWF6b250cnVzdC5jb20wggIiMA0GCSqG\n" +
+            "SIb3DQEBAQUAA4ICDwAwggIKAoICAQC+XjOB3ZCFX+b9y9reP+e6EAQz4ytiMSqU\n" +
+            "O4s5MyYLkY6n4BIZHmgWeQ2IgW1VrH8ho+Iu3UsTiuhd3/L/q/w+T0OJfcrWngTs\n" +
+            "uVcIuvUr32ObPeeWbg/m/lkN7hqH1jY62iybYVrFXiLo1+0G92PUazcyNvyA20+G\n" +
+            "HsvGG5jlArWNgRLdc8KUXxvnDUxx5vu4jeHEZnqSwuulV1h9ve0UutkmoK0Sk7Rz\n" +
+            "HMxYK0LmUT5OvcNQSkUi5nLi+M1FxnYYgsELwSiKSSEDfEdgxooMAiVTgw51Q/DB\n" +
+            "lTOjAIDL3K3J0yGfIG3bwLvE1qz2Z5yWn8f3JibIah7LrC4PiZDDLHFM6V9l+YqU\n" +
+            "RqimJ5BltSyAx7bxQNZ1AW3Lxvvm894i4k6/Vdf1CDovRuTMPCDAQmKA/A/AQ7TN\n" +
+            "q3bBimX6UyuJu0I8RyvAYKzFhOOqe4vXrbndTbje/jnzTNQPeIIcuRa9cgXTOrbw\n" +
+            "86FTUKj6AZXihRWjKWsQpDwdgE0tQETZ3ynCXfbBKfFmn0MSjeX0CEEAZdYHR8EV\n" +
+            "F271Yt7UJjS/FP702aHTOWk7zFbIRfFQODvBhn0I8p/Stk2sDq4/YsbXVZOe3+ad\n" +
+            "YavoiODGSAH6ZcZzULumgK9eii0koAOPB/xqXnkcTS63gEHOKjLQl3hqdVZRCugv\n" +
+            "1CwUXLvoSwIDAQABo4IBYzCCAV8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdDgQWBBTa\n" +
+            "j6dHgPdOxTGLcwaNDeaMnlSxNjAfBgNVHSMEGDAWgBTaQ0rQ/AHAS79YJ4x2zQqB\n" +
+            "85Qu9DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYIKwYBBQUHAQEE\n" +
+            "aTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5zY2EyYS5hbWF6b250cnVzdC5j\n" +
+            "b20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2NhMmEuYW1hem9udHJ1c3QuY29t\n" +
+            "L3NjYTJhLmNlcjAlBgNVHREEHjAcghpnb29kLnNjYTJhLmFtYXpvbnRydXN0LmNv\n" +
+            "bTBQBgNVHSAESTBHMA0GC2CGSAGG/W4BBxgDMDYGBWeBDAEBMC0wKwYIKwYBBQUH\n" +
+            "AgEWH2h0dHBzOi8vd3d3LmFtYXpvbnRydXN0LmNvbS9jcHMwDQYJKoZIhvcNAQEM\n" +
+            "BQADggIBAE6RwZAZvN0i9ygwzqoX9DhSPtvZ3xIO0G0Bhgjkb986+p8XJstU3gEM\n" +
+            "8P2i1J/YthXCnRGedm+Odxx+31G6xIYfP5S5g7HyRGkj/aXNXy4s3KjH8HJgOY9N\n" +
+            "ra3XfC05OKq5FpyZQDZ+hxCdLrH3Gs+UxREbu+LuIKUpI7nMVEjn9XynKyOdKN21\n" +
+            "Kq5VsuI0fDWCYvUN1M+lI/LgE5HbNJVQJs+dB7g1/kaOeaLia7Wk1ys+uRzB58rp\n" +
+            "FKAoLk++HWTfNDkbN8vKRfHhJ/xhI9ju3TWcci6EyFVAym1C62UkJNI0KHgQ+zc7\n" +
+            "nl1tv/ytj8N/eJoysyp23lJ5qrVetlQORfgXryGkWBMYBvYF8zbBb/f+UXHDKVWt\n" +
+            "9l1lL6HQGY/tTo253pj6/FgDD35bZdjLQeUVmbnz679S5oUmoH5ZtSdnpUTghU3p\n" +
+            "bae9adBFY9S1pm50Q3ckRVBAwNqNmI0KKUh14Ms8KSAUHg19NvGsBonqwOT2rdbv\n" +
+            "xZ47N6c2eCl/cjMvzre0v0NoUO+3og2GHeAoOwVos6480YDbMqp739tOFPxBcsII\n" +
+            "6SjpDVh+14dkSW6kEKeaCFLR+eChqutri1VQbQ49nmADQWw9Al8vBytSnPv0YN6W\n" +
+            "XfIE1Qj7YmHu/UuoeKVsqDqoP/no29+96dtfd4afJqlIoyZUqXpt\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=revoked.sca2a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    //Issuer: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US
+    //Serial number: 6f1d782c0aa2f4866b7b522c279b939b92369
+    //Valid from: Mon Jan 28 15:37:45 PST 2019 until: Thu Apr 28 16:37:45 PDT 2022
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIG2zCCBMOgAwIBAgITBvHXgsCqL0hmt7Uiwnm5ObkjaTANBgkqhkiG9w0BAQwF\n" +
+            "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" +
+            "ZXIgQ0EgMkExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzM3NDVaFw0yMjA0\n" +
+            "MjgyMzM3NDVaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" +
+            "AQITCERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYD\n" +
+            "VQQFEwc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ\n" +
+            "MA4GA1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2Vz\n" +
+            "MSYwJAYDVQQDEx1yZXZva2VkLnNjYTJhLmFtYXpvbnRydXN0LmNvbTCCAiIwDQYJ\n" +
+            "KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKFm418X8hN1YTgD2XpMb4sp78mw8k3j\n" +
+            "Dq/vnpX48evVUzNpHpy4qRz/ZHBR4HUJO4lhfnX+CO0uRqqqx4F0JZRQB3KevaU8\n" +
+            "QGWHdJGhEddnurDhrgOUa+ZroqUnMCsTJfbyGtC6aiEXeu/eMhEUFkuBxJH1JtwD\n" +
+            "dQXMXuMjG07SVjOkhTkbMDzA/YbUqkDeOIybifDuvA5LEsl+kReY0b6RYFo2Tt/M\n" +
+            "dPhJD8q3Wsu+XCiCnbpcwlEVGxiD2RVRXJJ9o3ALGOxqU69V+lYS0kkwNHT7oV9J\n" +
+            "rhgt7iOCq0aoTAxu2j4FCp0JHNhGoW9pXoMXnmS6kK80hzLNYDxvKEaVaKkiYHw5\n" +
+            "CV0Vwii05ICa14nrStH/jcRNLyU+gp+6OeerPV3jpKWshGKWewF+2UiWU2WHTSrd\n" +
+            "Wis0/qEfFK/kSraAxpd+KavEEavKeudoMAHIxMACOk9E/fF5zhd2y4G1q1BdoRlR\n" +
+            "KP4GIV2v6qH6Ru2mNSuge9il6kDXxFNucrYKLDbAqkqalohkvDavcPoG9gZT3etv\n" +
+            "4IcgJriIWRxbJwKPpwJM+6wa6RpwoeJMuEp3ZBP7KDaQ8YX4rlf4zXLAsOKCNA9K\n" +
+            "OS/qYQ/I4g0E1WhfgEKClaLPS2u7jeVR6s1t4txGo4vq5Dkt17KTCew/WsX3rckf\n" +
+            "a2p5zvFcfpCNAgMBAAGjggEpMIIBJTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYE\n" +
+            "FAF8N1wV8EoYFkMXH6tEnmR/7vI+MB8GA1UdIwQYMBaAFNpDStD8AcBLv1gnjHbN\n" +
+            "CoHzlC70MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcB\n" +
+            "AQRpMGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnNjYTJhLmFtYXpvbnRydXN0\n" +
+            "LmNvbTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5zY2EyYS5hbWF6b250cnVzdC5j\n" +
+            "b20vc2NhMmEuY2VyMCgGA1UdEQQhMB+CHXJldm9rZWQuc2NhMmEuYW1hem9udHJ1\n" +
+            "c3QuY29tMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBDAUAA4ICAQBC\n" +
+            "VwR1NFk1IYIF4cjU7ML1aj8OIn+8mtakGQnuSJLK6ypSysINJBS48ZDdP6XZXvyD\n" +
+            "iTS0xEAPjAZHTqrABdNYmvJeL2RnN99DIwVzBpZp4NLTXbiSW7jb0Y5cEPDGJMOo\n" +
+            "SUAAM6fsiPRfz5vX4XVPznbcF2AwE/NVV+L3n9LVRt7qv2VqIEvLioR56Dq+5ofR\n" +
+            "4bw0BVlEYWF4Gsy7WDDTL1iLNBUwZTqBHwTv0fgDRiPqb/odmLQuRANwcJy8B8Zr\n" +
+            "s/yX4SeESaRdA82lAlQilksQitXS2qvQN06GEDOgUxYE6EabFdgklV5JypKqdOly\n" +
+            "vzpaDpF3z5W8Bj3D4fns1Kjrh1pPh5JRvg+616diKnQRt4X5q+EtmnXhDvIGMISI\n" +
+            "FuGwj57CNQ2x2MY2HHKWPrOccpQfEEvoSNR+ntYWrtSSttZq948O+zZBk1TXWuXV\n" +
+            "TVXllqTg8lp6d5cfKgvtHKgt98WkpPOcLVrNuVnMAIfDw6ar54dVKqrvkeEcF6mJ\n" +
+            "7oMKjJX/Vu9lYoGViBIfdeqcCPWSI8BpnCKaG7dTQO3Q1ObGmLdGBRlsRh+d+S5l\n" +
+            "Fq326ckbjx537e5/ai31lOR7OwVh9TDweKLqIACjs987C0EJSEfoOue25WRww2va\n" +
+            "iX9SrTPm4GxQ2OJgYwx0+HbezJXFN+dhaOFUavTSFw==\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception {
+        // EE certificates don't have CRLDP extension
+        if (!ocspEnabled){
+            pathValidator.validate(new String[]{INT},
+                    ValidatePathWithParams.Status.GOOD, null, System.out);
+
+            return;
+        }
+
+        // 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,
+                "Mon Jan 28 15:38:57 PST 2019", System.out);
+    }
+}
+
+class AmazonCA_3 {
+
+    // Owner: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US
+    // Issuer: CN=Amazon Root CA 3, O=Amazon, C=US
+    // Serial number: 67f945758fe55b9ee3f75831d47f07d226c8a
+    // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIICuzCCAmGgAwIBAgITBn+UV1j+VbnuP3WDHUfwfSJsijAKBggqhkjOPQQDAjA5\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" +
+            "Um9vdCBDQSAzMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjELMAkG\n" +
+            "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENBIDNB\n" +
+            "MQ8wDQYDVQQDEwZBbWF6b24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATYcYsK\n" +
+            "mYdR0Gj8Xz45E/lfcTTnXhg2EtAIYBIHyXv/ZQyyyCas1aptX/I5T1coT6XK181g\n" +
+            "nB8hADuKfWlNoIYRo4IBOTCCATUwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8B\n" +
+            "Af8EBAMCAYYwHQYDVR0OBBYEFATc4JXl6LlrlKHvjFsxHhN+VZfaMB8GA1UdIwQY\n" +
+            "MBaAFKu229cGnjesMIYHkXDHnMQZsXjAMHsGCCsGAQUFBwEBBG8wbTAvBggrBgEF\n" +
+            "BQcwAYYjaHR0cDovL29jc3Aucm9vdGNhMy5hbWF6b250cnVzdC5jb20wOgYIKwYB\n" +
+            "BQUHMAKGLmh0dHA6Ly9jcnQucm9vdGNhMy5hbWF6b250cnVzdC5jb20vcm9vdGNh\n" +
+            "My5jZXIwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC5yb290Y2EzLmFtYXpv\n" +
+            "bnRydXN0LmNvbS9yb290Y2EzLmNybDARBgNVHSAECjAIMAYGBFUdIAAwCgYIKoZI\n" +
+            "zj0EAwIDSAAwRQIgOl/vux0qfxNm05W3eofa9lKwz6oKvdu6g6Sc0UlwgRcCIQCS\n" +
+            "WSQ6F6JHLoeOWLyFFF658eNKEKbkEGMHz34gLX/N3g==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=good.sca3a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US
+    // Serial number: 703e4e9bbc2605f37967a0e95f31f4789a677
+    // Valid from: Mon Jul 29 16:54:43 PDT 2019 until: Sat Aug 29 16:54:43 PDT 2020
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDhzCCAy2gAwIBAgITBwPk6bvCYF83lnoOlfMfR4mmdzAKBggqhkjOPQQDAjBG\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" +
+            "Q0EgM0ExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU0NDNaFw0yMDA4Mjky\n" +
+            "MzU0NDNaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" +
+            "CERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UE\n" +
+            "BRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO\n" +
+            "BgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNlczEj\n" +
+            "MCEGA1UEAxMaZ29vZC5zY2EzYS5hbWF6b250cnVzdC5jb20wWTATBgcqhkjOPQIB\n" +
+            "BggqhkjOPQMBBwNCAARl4yxf8XcvWR0LZ+YuBC0CpkwtU2NiMdlIM7eX0lxhQp53\n" +
+            "NpLlCrPRNzOWrjCJDdn21D0u7PrtN94UHLHOg9X0o4IBYzCCAV8wDgYDVR0PAQH/\n" +
+            "BAQDAgeAMB0GA1UdDgQWBBT2cHmOJFLWfg1Op7xAdAnqYcwaPzAfBgNVHSMEGDAW\n" +
+            "gBQE3OCV5ei5a5Sh74xbMR4TflWX2jAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" +
+            "BQUHAwIwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5z\n" +
+            "Y2EzYS5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2Nh\n" +
+            "M2EuYW1hem9udHJ1c3QuY29tL3NjYTNhLmNlcjAlBgNVHREEHjAcghpnb29kLnNj\n" +
+            "YTNhLmFtYXpvbnRydXN0LmNvbTBQBgNVHSAESTBHMA0GC2CGSAGG/W4BBxgDMDYG\n" +
+            "BWeBDAEBMC0wKwYIKwYBBQUHAgEWH2h0dHBzOi8vd3d3LmFtYXpvbnRydXN0LmNv\n" +
+            "bS9jcHMwCgYIKoZIzj0EAwIDSAAwRQIgURdcqJVr4PWNIkmWcSKmzgZ1i94hQpGe\n" +
+            "mWbE9osk4m0CIQDhxIguihwvDa5RsBwdM0aRDgGKLNHigGqJoKqgH0d2qg==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=revoked.sca3a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US
+    // Serial number: 6f1d78cf0ca64ce7f551a6f2a0715cc0e8b50
+    // Valid from: Mon Jan 28 15:40:01 PST 2019 until: Thu Apr 28 16:40:01 PDT 2022
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDTzCCAvWgAwIBAgITBvHXjPDKZM5/VRpvKgcVzA6LUDAKBggqhkjOPQQDAjBG\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" +
+            "Q0EgM0ExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzQwMDFaFw0yMjA0Mjgy\n" +
+            "MzQwMDFaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" +
+            "CERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYDVQQF\n" +
+            "Ewc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G\n" +
+            "A1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2VzMSYw\n" +
+            "JAYDVQQDEx1yZXZva2VkLnNjYTNhLmFtYXpvbnRydXN0LmNvbTBZMBMGByqGSM49\n" +
+            "AgEGCCqGSM49AwEHA0IABJNl90Jq0wddpFj+JbLtmvGR/1geL5t1tvV406jGpYn2\n" +
+            "C5lAFjwASFy7pAnazZbfSkIDUU2i2XU0+7Cs+j1S/EOjggEpMIIBJTAOBgNVHQ8B\n" +
+            "Af8EBAMCB4AwHQYDVR0OBBYEFPhX3dYays5Sps0xTgouLkZzYLg4MB8GA1UdIwQY\n" +
+            "MBaAFATc4JXl6LlrlKHvjFsxHhN+VZfaMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr\n" +
+            "BgEFBQcDAjB1BggrBgEFBQcBAQRpMGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3Nw\n" +
+            "LnNjYTNhLmFtYXpvbnRydXN0LmNvbTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5z\n" +
+            "Y2EzYS5hbWF6b250cnVzdC5jb20vc2NhM2EuY2VyMCgGA1UdEQQhMB+CHXJldm9r\n" +
+            "ZWQuc2NhM2EuYW1hem9udHJ1c3QuY29tMBMGA1UdIAQMMAowCAYGZ4EMAQIBMAoG\n" +
+            "CCqGSM49BAMCA0gAMEUCICLb16/50S4fOAFafi5lagdx7q6EDPPm596g19eQDMXk\n" +
+            "AiEAksCMLypRB4t30FABlsEjhVCBIxay0iIer2OcCIrhfEI=\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception {
+        // EE certificates don't have CRLDP extension
+        if (!ocspEnabled){
+            pathValidator.validate(new String[]{INT},
+                    ValidatePathWithParams.Status.GOOD, null, System.out);
+
+            return;
+        }
+
+        // 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,
+                "Mon Jan 28 15:40:35 PST 2019", System.out);
+    }
+}
+
+class AmazonCA_4 {
+
+    // Owner: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US
+    // Issuer: CN=Amazon Root CA 4, O=Amazon, C=US
+    // Serial number: 67f94575a8862a9072e3239c37ceba1274e18
+    // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIC+TCCAn6gAwIBAgITBn+UV1qIYqkHLjI5w3zroSdOGDAKBggqhkjOPQQDAzA5\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" +
+            "Um9vdCBDQSA0MB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjELMAkG\n" +
+            "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENBIDRB\n" +
+            "MQ8wDQYDVQQDEwZBbWF6b24wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASRP0kIW0Ha\n" +
+            "7+ORvEVhIS5gIgkH66X5W9vBRTX14oG/1elIyI6LbFZ+E5KAufL0XoWJGI1WbPRm\n" +
+            "HW246FKSzF0wOEZZyxEROz6tuaVsnXRHRE76roS/Wr064uJpKH+Lv+SjggE5MIIB\n" +
+            "NTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU\n" +
+            "pSHN2+tTIZmqytlnQpQlsnv0wuMwHwYDVR0jBBgwFoAU0+zHOmVuzOHadppW+5zz\n" +
+            "hm1X5YEwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5y\n" +
+            "b290Y2E0LmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5y\n" +
+            "b290Y2E0LmFtYXpvbnRydXN0LmNvbS9yb290Y2E0LmNlcjA/BgNVHR8EODA2MDSg\n" +
+            "MqAwhi5odHRwOi8vY3JsLnJvb3RjYTQuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTQu\n" +
+            "Y3JsMBEGA1UdIAQKMAgwBgYEVR0gADAKBggqhkjOPQQDAwNpADBmAjEA59RAOBaj\n" +
+            "uh0rT/OOTWPEv6TBnb9XEadburBaXb8SSrR8il+NdkfS9WXRAzbwrG7LAjEA3ukD\n" +
+            "1HrQq+WXHBM5sIuViJI/Zh7MOjsc159Q+dn36PBqLRq03AXqE/lRjnv8C5nj\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=good.sca4a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US
+    // Serial number: 703e4ec57c72d5669efbc98875c3f6bc3f934
+    // Valid from: Mon Jul 29 16:55:17 PDT 2019 until: Sat Aug 29 16:55:17 PDT 2020
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDxTCCA0qgAwIBAgITBwPk7FfHLVZp77yYh1w/a8P5NDAKBggqhkjOPQQDAzBG\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" +
+            "Q0EgNEExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU1MTdaFw0yMDA4Mjky\n" +
+            "MzU1MTdaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" +
+            "CERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UE\n" +
+            "BRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO\n" +
+            "BgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNlczEj\n" +
+            "MCEGA1UEAxMaZ29vZC5zY2E0YS5hbWF6b250cnVzdC5jb20wdjAQBgcqhkjOPQIB\n" +
+            "BgUrgQQAIgNiAAS9fqMYfOBsdXMSsPjqOlTgIGOlOQWA7Wg6XwVvHTr0+UN+XTeC\n" +
+            "yZN+XjLbEDQ0CF5eryRZ535sDpwh3qNe0lYFO1n1+2iDtDI1jhhLNYNxBpVnR2BU\n" +
+            "2l9EuRmgRbQpDCajggFjMIIBXzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFMd0\n" +
+            "itH5IcE6DpM1uTSBV/6DLmK7MB8GA1UdIwQYMBaAFKUhzdvrUyGZqsrZZ0KUJbJ7\n" +
+            "9MLjMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcBAQRp\n" +
+            "MGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnNjYTRhLmFtYXpvbnRydXN0LmNv\n" +
+            "bTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5zY2E0YS5hbWF6b250cnVzdC5jb20v\n" +
+            "c2NhNGEuY2VyMCUGA1UdEQQeMByCGmdvb2Quc2NhNGEuYW1hem9udHJ1c3QuY29t\n" +
+            "MFAGA1UdIARJMEcwDQYLYIZIAYb9bgEHGAMwNgYFZ4EMAQEwLTArBggrBgEFBQcC\n" +
+            "ARYfaHR0cHM6Ly93d3cuYW1hem9udHJ1c3QuY29tL2NwczAKBggqhkjOPQQDAwNp\n" +
+            "ADBmAjEA2RBD1F+rnm394VkqA3ncysM3deoyfWqaoAO5923MNisswPnHfVqnfeXf\n" +
+            "ZwTAvVTBAjEAiiaPx9GRjEk8IBKvCSbTp9rPogVTN7zDDQGrwA83O0pRP7A0dxtT\n" +
+            "pn/0K5Sj8otp\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=revoked.sca4a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \
+    // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \
+    // OID.1.3.6.1.4.1.311.60.2.1.3=US
+    // Issuer: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US
+    // Serial number: 6f1d79295c384a699d51c2d756bd46213b5b3
+    // Valid from: Mon Jan 28 15:41:16 PST 2019 until: Thu Apr 28 16:41:16 PDT 2022
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDjTCCAxKgAwIBAgITBvHXkpXDhKaZ1RwtdWvUYhO1szAKBggqhkjOPQQDAzBG\n" +
+            "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" +
+            "Q0EgNEExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzQxMTZaFw0yMjA0Mjgy\n" +
+            "MzQxMTZaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" +
+            "CERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYDVQQF\n" +
+            "Ewc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G\n" +
+            "A1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2VzMSYw\n" +
+            "JAYDVQQDEx1yZXZva2VkLnNjYTRhLmFtYXpvbnRydXN0LmNvbTB2MBAGByqGSM49\n" +
+            "AgEGBSuBBAAiA2IABLuNpZTcNU3FElNP3Y/OeXIZcIMXkFTBi/n92fNwHfqUbEhH\n" +
+            "H+PovJ26eAGvb5a8bGc275MBFcVnWL0rCVgM+j9KAtBDCRJX3f7mo0D2VKcmtZKu\n" +
+            "jPxwGPy2kuqM505dGqOCASkwggElMA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQU\n" +
+            "zUFIhn+hphzCKA2qgAdLztSBzJgwHwYDVR0jBBgwFoAUpSHN2+tTIZmqytlnQpQl\n" +
+            "snv0wuMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGCCsGAQUFBwEB\n" +
+            "BGkwZzAtBggrBgEFBQcwAYYhaHR0cDovL29jc3Auc2NhNGEuYW1hem9udHJ1c3Qu\n" +
+            "Y29tMDYGCCsGAQUFBzAChipodHRwOi8vY3J0LnNjYTRhLmFtYXpvbnRydXN0LmNv\n" +
+            "bS9zY2E0YS5jZXIwKAYDVR0RBCEwH4IdcmV2b2tlZC5zY2E0YS5hbWF6b250cnVz\n" +
+            "dC5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaQAwZgIxALDA\n" +
+            "klY3iKwyzwpwVtLfLxzQEl45xvE2VjBJvfJJ60KhJt7Ud0gt0zxkogh29+mpEQIx\n" +
+            "ANTG1mk8OJB41DU7ru1Pwc6ju8STw1FdwDp/Eliqhvnm2i0k4/F1bBHLta2mlC2V\n" +
+            "hg==\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception {
+        // EE certificates don't have CRLDP extension
+        if (!ocspEnabled){
+            pathValidator.validate(new String[]{INT},
+                    ValidatePathWithParams.Status.GOOD, null, System.out);
+
+            return;
+        }
+
+        // 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,
+                "Mon Jan 28 15:41:53 PST 2019", System.out);
+    }
+}
--- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	Fri Nov 29 10:02:07 2019 +0000
@@ -26,7 +26,7 @@
  * @test
  * @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
  *      8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137 8222136
- *      8223499 8225392 8232019 8234245
+ *      8223499 8225392 8232019 8234245 8233223
  * @summary Check root CA entries in cacerts file
  */
 import java.io.ByteArrayInputStream;
@@ -52,12 +52,12 @@
             + File.separator + "security" + File.separator + "cacerts";
 
     // The numbers of certs now.
-    private static final int COUNT = 89;
+    private static final int COUNT = 93;
 
     // SHA-256 of cacerts, can be generated with
     // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95
     private static final String CHECKSUM
-            = "DE:71:94:6D:6C:5B:2A:AE:5C:AC:D1:3E:07:23:B6:43:CB:F7:32:69:32:04:36:9C:B4:11:78:6A:49:9D:C5:AB";
+            = "22:AA:EB:89:4E:A4:EA:25:CA:3E:DA:0F:F1:2B:FA:05:4B:68:C5:E1:3A:F9:03:40:BF:EF:F5:13:7C:CE:BC:60";
 
     // map of cert alias to SHA-256 fingerprint
     @SuppressWarnings("serial")
@@ -241,6 +241,14 @@
                     "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");
             put("luxtrustglobalroot2ca [jdk]",
                     "54:45:5F:71:29:C2:0B:14:47:C4:18:F9:97:16:8F:24:C5:8F:C5:02:3B:F5:DA:5B:E2:EB:6E:1D:D8:90:2E:D5");
+            put("amazonrootca1 [jdk]",
+                    "8E:CD:E6:88:4F:3D:87:B1:12:5B:A3:1A:C3:FC:B1:3D:70:16:DE:7F:57:CC:90:4F:E1:CB:97:C6:AE:98:19:6E");
+            put("amazonrootca2 [jdk]",
+                    "1B:A5:B2:AA:8C:65:40:1A:82:96:01:18:F8:0B:EC:4F:62:30:4D:83:CE:C4:71:3A:19:C3:9C:01:1E:A4:6D:B4");
+            put("amazonrootca3 [jdk]",
+                    "18:CE:6C:FE:7B:F1:4E:60:B2:E3:47:B8:DF:E8:68:CB:31:D0:2E:BB:3A:DA:27:15:69:F5:03:43:B4:6D:B3:A4");
+            put("amazonrootca4 [jdk]",
+                    "E3:5D:28:41:9E:D0:20:25:CF:A6:90:38:CD:62:39:62:45:8D:A5:C6:95:FB:DE:A3:C2:2B:0B:FB:25:89:70:92");
         }
     };
 
--- a/test/jdk/sun/security/ssl/SSLContextImpl/IllegalProtocolProperty.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/sun/security/ssl/SSLContextImpl/IllegalProtocolProperty.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -26,7 +26,7 @@
 
 /*
  * @test
- * @bug 7093640
+ * @bug 7093640 8234725
  * @summary Enable TLS 1.1 and TLS 1.2 by default in client side of SunJSSE
  * @run main/othervm -Djdk.tls.client.protocols="XSLv3,TLSv1"
  *      IllegalProtocolProperty
@@ -43,7 +43,8 @@
         TLS_CV_04("TLSv1", "TLSv1", "TLSv1.2", false),
         TLS_CV_05("TLSv1.1", "TLSv1.1", "TLSv1.2", false),
         TLS_CV_06("TLSv1.2", "TLSv1.2", "TLSv1.2", false),
-        TLS_CV_07("Default", "TLSv1", "TLSv1.2", true);
+        TLS_CV_07("Default", "TLSv1", "TLSv1.2", true),
+        TLS_CV_08("TLSv1.3", "TLSv1.3", "TLSv1.3", false);
 
         final String contextVersion;
         final String defaultProtocolVersion;
--- a/test/jdk/sun/security/ssl/SSLContextImpl/SSLContextVersion.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/jdk/sun/security/ssl/SSLContextImpl/SSLContextVersion.java	Fri Nov 29 10:02:07 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, 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
@@ -26,7 +26,7 @@
 
 /*
  * @test
- * @bug 6976117
+ * @bug 6976117 8234725
  * @summary SSLContext.getInstance("TLSv1.1") returns SSLEngines/SSLSockets
  *          without TLSv1.1 enabled
  * @run main/othervm SSLContextVersion
@@ -42,7 +42,10 @@
         TLS_CV_04("TLSv1", "TLSv1", "TLSv1.2"),
         TLS_CV_05("TLSv1.1", "TLSv1.1", "TLSv1.2"),
         TLS_CV_06("TLSv1.2", "TLSv1.2", "TLSv1.2"),
-        TLS_CV_07("Default", "TLSv1.2", "TLSv1.2");
+        TLS_CV_07("Default", "TLSv1.2", "TLSv1.2"),
+        TLS_CV_08("Default", "TLSv1.3", "TLSv1.3"),
+        TLS_CV_09("TLS", "TLSv1.3", "TLSv1.3"),
+        TLS_CV_10("TLSv1.3", "TLSv1.3", "TLSv1.3");
 
         final String contextVersion;
         final String defaultProtocolVersion;
--- a/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlLandmarkRegions/TestHtmlLandmarkRegions.java	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8210047 8199892 8215599
+ * @bug 8210047 8199892 8215599 8223378
  * @summary some pages contains content outside of landmark region
  * @library /tools/lib ../../lib
  * @modules
@@ -74,7 +74,7 @@
         checkExit(Exit.OK);
 
         checkOrder("index.html",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">\n"
@@ -98,7 +98,7 @@
         checkExit(Exit.OK);
 
         checkOrder("index.html",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">\n"
@@ -130,9 +130,10 @@
         checkExit(Exit.OK);
 
         checkOrder("pkg1/doc-files/s.html",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n",
-                "<main role=\"main\">A sample doc file",
+                "<main role=\"main\">\n"
+                + "<div class=\"contentContainer\">A sample doc file",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">"
                 );
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Fri Nov 29 10:02:07 2019 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 8072945 8081854 8141492 8148985 8150188 4649116 8173707 8151743 8169819 8183037 8182765 8196202
- *      8202624 8210047 8184205 8221871 8223733
+ *      8202624 8210047 8184205 8221871 8223733 8223378
  * @summary Test the version of HTML generated by the javadoc tool.
  * @author bpatel
  * @library ../../lib
@@ -78,9 +78,8 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table>\n"
                 + "<caption>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -94,9 +93,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<div class=\"typeSummary\">\n<table>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -124,9 +122,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<li class=\"circle\">",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -150,9 +147,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<div class=\"useSummary\">\n<table>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -168,9 +164,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<div class=\"constantsSummary\">\n<table>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -190,9 +185,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<div class=\"deprecatedSummary\">\n<table>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -207,9 +201,8 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -227,9 +220,8 @@
                 + "<!--   -->\n"
                 + "</a>",
                 "<li class=\"circle\">",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -252,11 +244,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "</header>\n"
+                + "<div class=\"flexContent\">\n"
                 + "<main role=\"main\">",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
@@ -275,9 +267,8 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -298,11 +289,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"nestedClassSummary\"><a id=\"nested.class.summary\">\n"
                 + "<!--   -->\n"
@@ -349,11 +340,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"constantsSummary\"><a id=\"enum.constant.summary\">\n"
                 + "<!--   -->\n"
@@ -388,11 +379,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"methodSummary\"><a id=\"method.summary\">\n"
                 + "<!--   -->\n"
@@ -416,11 +407,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"constructorSummary\"><a id=\"constructor.summary\">\n"
                 + "<!--   -->\n"
@@ -442,11 +433,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"constructorSummary\"><a id=\"constructor.summary\">\n"
                 + "<!--   -->\n"
@@ -468,11 +459,11 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->\n"
                 + "<div class=\"header\">",
                 "<section class=\"memberSummary\"><a id=\"annotation.type.required.element.summary\">\n"
                 + "<!--   -->\n"
@@ -500,9 +491,8 @@
                 "<a id=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<header role=\"banner\">\n"
+                "<header role=\"banner\" class=\"flexHeader\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
                 "<main role=\"main\">\n"
                 + "<div class=\"header\">",
@@ -528,7 +518,6 @@
                 "<table summary=\"Package Summary table, listing packages, and an explanation\">\n"
                 + "<caption>",
                 "</noscript>\n"
-                + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->");
 
         // Negated test for package-summary page
@@ -574,11 +563,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">",
                 "<div class=\"constantsSummary\">\n"
                 + "<table summary=\"Constant Field Values table, listing constant fields, and values\">");
@@ -592,11 +576,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">\n"
                 + "<h1 title=\"Deprecated API\" class=\"title\">Deprecated API</h1>\n"
                 + "<h2 title=\"Contents\">Contents</h2>",
@@ -620,11 +599,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">",
                 "<li class=\"blockList\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>");
@@ -638,11 +612,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">",
                 "<div class=\"contentContainer\">\n"
                 + "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>",
@@ -660,11 +629,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"contentContainer\">");
 
         // Negated test for src-html page
@@ -682,11 +646,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">",
                 "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
@@ -703,8 +662,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- ======== NESTED CLASS SUMMARY ======== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"nested.class.summary\">\n"
@@ -763,8 +720,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- =========== ENUM CONSTANT SUMMARY =========== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"enum.constant.summary\">\n"
@@ -801,8 +756,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- ========== METHOD SUMMARY =========== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"method.summary\">\n"
@@ -825,8 +778,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- ======== CONSTRUCTOR SUMMARY ======== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"constructor.summary\">\n"
@@ -847,8 +798,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- ======== CONSTRUCTOR SUMMARY ======== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"constructor.summary\">\n"
@@ -869,8 +818,6 @@
                 "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>",
-                "<!-- ======== START OF CLASS DATA ======== -->\n"
-                + "<div class=\"header\">",
                 "<!-- =========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY =========== -->\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\"><a name=\"annotation.type.required.element.summary\">\n"
@@ -903,11 +850,6 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
                 + "<div class=\"header\">",
                 "<div class=\"useSummary\">\n"
                 + "<table summary=\"Use table, listing packages, and an explanation\">",
--- a/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985 8151921 8151743 8196202
+ * @bug      4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985 8151921 8151743 8196202 8223378
  * @summary  Verify that the output has the right javascript.
  * @author   jamieh
  * @library  ../../lib
@@ -48,18 +48,18 @@
                 "pkg", testSrc("TestJavascript.java"));
         checkExit(Exit.OK);
 
-        checkOutput("pkg/C.html", true,
+        checkOutput("pkg/C.html", false,
                 "<script type=\"text/javascript\"><!--\n"
                 + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
                 + "//-->\n"
                 + "</script>");
 
-        checkOutput("index.html", true,
+        checkOutput("index.html", false,
                 "<script type=\"text/javascript\"><!--\n"
                 + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
                 + "//-->\n");
 
-        checkOutput("script.js", true,
+        checkOutput("script.js", false,
                 "$(window).resize(function() {\n"
                 + "        $('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
                 + "    });");
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Fri Nov 29 10:02:07 2019 +0000
@@ -27,7 +27,7 @@
  *      8168766 8168688 8162674 8160196 8175799 8174974 8176778 8177562 8175218
  *      8175823 8166306 8178043 8181622 8183511 8169819 8074407 8183037 8191464
         8164407 8192007 8182765 8196200 8196201 8196202 8196202 8205593 8202462
-        8184205 8219060
+        8184205 8219060 8223378
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../../lib
@@ -533,6 +533,7 @@
         checkOutput("index.html", found,
                 "</nav>\n"
                 + "</header>\n"
+                + "<div class=\"flexContent\">\n"
                 + "<main role=\"main\">\n"
                 + "<div class=\"contentContainer\">\n"
                 + "<div class=\"block\">The overview summary page header.</div>\n"
@@ -744,9 +745,9 @@
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
                 + "</thead>",
-                "</script>\n"
-                + "</nav>\n"
+                "</nav>\n"
                 + "</header>\n"
+                + "<div class=\"flexContent\">\n"
                 + "<main role=\"main\">\n"
                 + "<div class=\"contentContainer\">\n"
                 + "<div class=\"block\">The overview summary page header.</div>\n"
--- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java	Fri Nov 29 10:02:07 2019 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854 8150188 8151743 8196027 8182765
- *           8196200 8196202
+ *           8196200 8196202 8223378
  * @summary  Make sure the Next/Prev Class links iterate through all types.
  *           Make sure the navagation is 2 columns, not 3.
  * @author   jamieh
@@ -85,26 +85,23 @@
         // Remaining tests check for additional padding to offset the fixed navigation bar.
         checkOutput("pkg/A.html", true,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
-                + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>\n"
                 + "</header>\n"
+                + "<div class=\"flexContent\">\n"
+                + "<main role=\"main\">\n"
                 + "<!-- ======== START OF CLASS DATA ======== -->");
 
         checkOutput("pkg/package-summary.html", true,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
-                + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>\n"
                 + "</header>\n"
+                + "<div class=\"flexContent\">\n"
                 + "<main role=\"main\">\n"
                 + "<div class=\"header\">");
     }
@@ -121,24 +118,20 @@
 
         checkOutput("pkg/A.html", true,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
-                + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>\n"
                 + "</header>\n"
+                + "<div class=\"flexContent\">\n"
+                + "<main role=\"main\">\n"
                 + "<!-- ======== START OF CLASS DATA ======== -->");
 
         checkOutput("pkg/package-summary.html", true,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
-                + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>");
     }
 
@@ -155,11 +148,9 @@
         checkOutput("pkg/A.html", false,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>\n"
                 + "</header>\n"
                 + "<!-- ======== START OF CLASS DATA ======== -->");
@@ -167,11 +158,9 @@
         checkOutput("pkg/package-summary.html", false,
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
-                + "<div class=\"navPadding\">&nbsp;</div>\n"
-                + "<script type=\"text/javascript\"><!--\n"
-                + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                + "//-->\n"
-                + "</script>\n"
+                + "<div class=\"skipNav\"><a id=\"skip.navbar.top\">\n"
+                + "<!--   -->\n"
+                + "</a></div>\n"
                 + "</nav>");
     }
 
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Fri Nov 29 10:02:07 2019 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 8141492 8071982 8141636 8147890 8166175 8168965 8176794 8175218 8147881
  *      8181622 8182263 8074407 8187521 8198522 8182765 8199278 8196201 8196202
- *      8184205 8214468 8222548
+ *      8184205 8214468 8222548 8223378
  * @summary Test the search feature of javadoc.
  * @author bpatel
  * @library ../../lib
@@ -385,7 +385,7 @@
                 + "<input type=\"text\" id=\"search\" value=\"search\" disabled=\"disabled\">\n"
                 + "<input type=\"reset\" id=\"reset\" value=\"reset\" disabled=\"disabled\">\n");
         checkOutput(fileName, true,
-                "<div class=\"fixedNav\">");
+                "<div class=\"flexBox\">");
     }
 
     void checkSingleIndex(boolean expectedOutput, boolean html5) {
--- a/test/langtools/jdk/javadoc/doclet/testSearchScript/javadoc-search.js	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testSearchScript/javadoc-search.js	Fri Nov 29 10:02:07 2019 +0000
@@ -52,29 +52,29 @@
         f();
     } else {
         return {
-            val: function() { 
-                return this; 
+            val: function() {
+                return this;
             },
-            prop: function() { 
-                return this; 
+            prop: function() {
+                return this;
             },
-            addClass: function() { 
-                return this; 
-            },    
-            removeClass: function() { 
-                return this; 
+            addClass: function() {
+                return this;
+            },
+            removeClass: function() {
+                return this;
             },
-            on: function() { 
-                return this; 
+            on: function() {
+                return this;
             },
-            focus: function() { 
-                return this; 
+            focus: function() {
+                return this;
             },
-            blur: function() { 
-                return this; 
+            blur: function() {
+                return this;
             },
-            click: function() { 
-                return this; 
+            click: function() {
+                return this;
             },
             catcomplete: function(o) {
                 o.close = function() {};
@@ -90,11 +90,11 @@
                     return resultList;
                 };
                 for (var i = 0; i < clargs.length; i++) {
-                    search(clargs[i]);  
+                    search(clargs[i]);
                 }
             },
             "0": {
-                setSelectionRange: function() { 
+                setSelectionRange: function() {
                     return this;
                 }
             }
--- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Fri Nov 29 10:02:07 2019 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417
- *           8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369 8182765 8196201 8184205
+ *           8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369 8182765 8196201 8184205 8223378
  * @summary  Run tests on doclet stylesheet.
  * @author   jamieh
  * @library  ../../lib
@@ -143,18 +143,8 @@
                 + "    padding:0px 0px 12px 10px;\n"
                 + "}",
                 "@import url('resources/fonts/dejavu.css');",
-                ".navPadding {\n"
-                + "    padding-top: 107px;\n"
-                + "}",
-                "a[name]:before, a[name]:target, a[id]:before, a[id]:target {\n"
-                + "    content:\"\";\n"
-                + "    display:inline-block;\n"
-                + "    position:relative;\n"
-                + "    padding-top:129px;\n"
-                + "    margin-top:-129px;\n"
-                + "}",
-                ".searchTagResult:before, .searchTagResult:target {\n"
-                + "    color:red;\n"
+                ".searchTagResult:target {\n"
+                + "    background-color:yellow;\n"
                 + "}",
                 "a[href]:hover, a[href]:focus {\n"
                 + "    text-decoration:none;\n"
@@ -190,7 +180,7 @@
                 + "    background-size:12px;\n"
                 + "    border:0 none;\n"
                 + "    width:16px;\n"
-                + "    height:17px;\n"
+                + "    height:16px;\n"
                 + "    position:relative;\n"
                 + "    left:-4px;\n"
                 + "    top:-4px;\n"
--- a/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testTopOption/TestTopOption.java	Fri Nov 29 10:02:07 2019 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      6227616 8043186 8196202
+ * @bug      6227616 8043186 8196202 8223378
  * @summary  Test the new -top option.
  * @author   jamieh
  * @library  ../../lib
@@ -87,6 +87,30 @@
                 "help-doc.html");
     }
 
+    @Test
+    public void testNoNavbar() {
+        javadoc("-overview", testSrc("overview.html"),
+                "-use",
+                "-top", "TOP TEXT",
+                "-nonavbar",
+                "-d", "out-3",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkTopText(
+                "pkg/AnnotationType.html",
+                "pkg/class-use/AnnotationType.html",
+                "pkg/Cl.html",
+                "pkg/class-use/Cl.html",
+                "pkg/package-summary.html",
+                "pkg/package-use.html",
+                "index.html",
+                "overview-tree.html",
+                "constant-values.html",
+                "help-doc.html");
+    }
+
     void checkTopText(String... files) {
         for (String file : files) {
             checkOutput(file, true, "TOP TEXT");
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -27,12 +27,14 @@
 import java.util.List;
 
 import com.sun.tools.classfile.*;
+import java.util.ArrayList;
 
 public class ClassfileTestHelper {
     int expected_tinvisibles = 0;
     int expected_tvisibles = 0;
     int expected_invisibles = 0;
     int expected_visibles = 0;
+    List<String> extraOptions = List.of();
 
     //Makes debugging much easier. Set to 'false' for less output.
     public Boolean verbose = true;
@@ -48,8 +50,9 @@
     }
 
     File compile(File f) {
-        int rc = com.sun.tools.javac.Main.compile(new String[] {
-                "-g", f.getPath() });
+        List<String> options = new ArrayList<>(List.of("-g", f.getPath()));
+        options.addAll(extraOptions);
+        int rc = com.sun.tools.javac.Main.compile(options.toArray(new String[0]));
         if (rc != 0)
             throw new Error("compilation failed. rc=" + rc);
         String path = f.getPath();
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -30,9 +30,13 @@
 
 import com.sun.tools.classfile.*;
 import java.io.File;
+import java.util.List;
 
 public class CombinationsTargetTest2 extends ClassfileTestHelper {
 
+    private static final String JDK_VERSION =
+            Integer.toString(Runtime.getRuntime().version().feature());
+
     // Test count helps identify test case in event of failure.
     int testcount = 0;
 
@@ -45,7 +49,9 @@
         src5("(repeating) type annotations on field in anonymous class", false),
         src6("(repeating) type annotations on void method declaration", false),
         src7("(repeating) type annotations in use of instanceof", true),
-        src8("(repeating) type annotations in use of instanceof in method", true);
+        src7p("(repeating) type annotations in use of instanceof with type test pattern", true),
+        src8("(repeating) type annotations in use of instanceof in method", true),
+        src8p("(repeating) type annotations in use of instanceof with type test pattern in method", true);
 
         String description;
         Boolean local;
@@ -92,8 +98,12 @@
                        test( 0, 0, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src6);
                        test( 2, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src7);
                        test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src7);
+                       test( 2, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src7p);
+                       test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src7p);
                        test( 4, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src8);
                        test( 0, 4, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src8);
+                       test( 4, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src8p);
+                       test( 0, 4, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src8p);
                        break;
                    case "FIELD":
                        test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src1);
@@ -122,6 +132,7 @@
         expected_tinvisibles = tinv;
         expected_visibles = vis;
         expected_invisibles = inv;
+        extraOptions = List.of();
         File testFile = null;
         String tname="Test" + N.toString();
         hasInnerClass=false;
@@ -385,6 +396,24 @@
                     "\n\n";
                     hasInnerClass=false;
                 break;
+            case src7p: // (repeating) type annotations in use of instanceof with type test pattern
+                    /*
+                     *   class Test10{
+                     *       String data = "test";
+                     *       boolean dataIsString = ( data instanceof @A @B @A @B String str);
+                     *   }
+                     */
+                source = new String( source +
+                    "// " + src.description + "\n" +
+                    "class "+ testname + "{\n" +
+                    "    String data = \"test\";\n" +
+                    "    boolean dataIsString = ( data instanceof _As_ _Bs_ String str && str.isEmpty());\n" +
+                    "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
+                    "\n\n";
+                extraOptions = List.of("--enable-preview",
+                                       "-source", JDK_VERSION);
+                hasInnerClass=false;
+                break;
             case src8: // (repeating) type annotations in use of instanceof
                     /*
                      *   class Test20{
@@ -411,6 +440,34 @@
                     "\n\n";
                     hasInnerClass=false;
                 break;
+            case src8p: // (repeating) type annotations in use of instanceof with type test pattern
+                   /*
+                     *   class Test20{
+                     *       String data = "test";
+                     *       Boolean isString() {
+                     *           if( data instanceof @A @B @A @B String )
+                     *               return true;
+                     *           else
+                     *               return( data instanceof @A @B @A @B String );
+                     *       }
+                     *   }
+                     */
+                source = new String( source +
+                    "// " + src.description + "\n" +
+                    "class "+ testname + "{\n" +
+                    "    String data = \"test\";\n" +
+                    "    Boolean isString() { \n" +
+                    "        if( data instanceof _As_ _Bs_ String str)\n" +
+                    "            return true;\n" +
+                    "        else\n" +
+                    "            return( data instanceof _As_ _Bs_ String str && str.isEmpty());\n" +
+                    "    }\n" +
+                    "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
+                    "\n\n";
+                extraOptions = List.of("--enable-preview",
+                                       "-source", JDK_VERSION);
+                hasInnerClass=false;
+                break;
 
         }
         return imports + source;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,222 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify type annotation on binding patterns
+ * @library /tools/lib
+ * @modules java.compiler
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.JavapTask
+ * @compile --enable-preview -source ${jdk.version} Patterns.java
+ * @run main/othervm --enable-preview Patterns
+ */
+
+import java.lang.annotation.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class Patterns {
+
+    private ToolBox tb = new ToolBox();
+
+    public static void main(String[] args) throws Exception {
+        new Patterns().run();
+    }
+
+    public void run() throws Exception {
+        String out = new JavapTask(tb)
+                .options("-private",
+                         "-verbose")
+                .classpath(System.getProperty("test.classes"))
+                .classes("Patterns$SimpleBindingPattern")
+                .run()
+                .getOutputLines(Task.OutputKind.DIRECT)
+                .stream()
+                .collect(Collectors.joining("\n"));
+
+        String constantPool = out.substring(0, out.indexOf('{'));
+
+        out = out.replaceAll("(?ms) *Code:.*?\n( *RuntimeInvisibleTypeAnnotations:)", "$1");
+        out = out.substring(out.indexOf('{'));
+        out = out.substring(0, out.lastIndexOf('}') + 1);
+
+        String A = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$A;");
+        String CA = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$CA;");
+        String value = snipCPNumber(constantPool, "value");
+
+        String expected = """
+                          {
+                            private static final java.lang.Object o;
+                              descriptor: Ljava/lang/Object;
+                              flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
+
+                            private static final boolean B1s;
+                              descriptor: Z
+                              flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
+
+                            private static final boolean B1m;
+                              descriptor: Z
+                              flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
+
+                            private final boolean B2s;
+                              descriptor: Z
+                              flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+
+                            private final boolean B2m;
+                              descriptor: Z
+                              flags: (0x0012) ACC_PRIVATE, ACC_FINAL
+
+                            public Patterns$SimpleBindingPattern();
+                              descriptor: ()V
+                              flags: (0x0001) ACC_PUBLIC
+                                RuntimeInvisibleTypeAnnotations:
+                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=257, length=18, index=2}
+                                    Patterns$SimpleBindingPattern$A
+                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=297, length=19, index=3}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=22, length=18, index=1}
+                                    Patterns$SimpleBindingPattern$A
+                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=18, index=1}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+                                  4: #_A_(): LOCAL_VARIABLE, {start_pc=101, length=18, index=2}
+                                    Patterns$SimpleBindingPattern$A
+                                  5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=141, length=19, index=3}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+                                  6: #_A_(): LOCAL_VARIABLE, {start_pc=179, length=18, index=2}
+                                    Patterns$SimpleBindingPattern$A
+                                  7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=219, length=19, index=3}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+
+                            void testPatterns();
+                              descriptor: ()V
+                              flags: (0x0000)
+                                RuntimeInvisibleTypeAnnotations:
+                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=17, length=18, index=2}
+                                    Patterns$SimpleBindingPattern$A
+                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=57, length=19, index=3}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+
+                            void testPatternsDesugared();
+                              descriptor: ()V
+                              flags: (0x0000)
+                                RuntimeInvisibleTypeAnnotations:
+                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=17, length=15, index=1; start_pc=51, length=15, index=1}
+                                    Patterns$SimpleBindingPattern$A
+
+                            static {};
+                              descriptor: ()V
+                              flags: (0x0008) ACC_STATIC
+                                RuntimeInvisibleTypeAnnotations:
+                                  0: #_A_(): LOCAL_VARIABLE, {start_pc=22, length=18, index=0}
+                                    Patterns$SimpleBindingPattern$A
+                                  1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=61, length=18, index=0}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+                                  2: #_A_(): LOCAL_VARIABLE, {start_pc=100, length=18, index=1}
+                                    Patterns$SimpleBindingPattern$A
+                                  3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=137, length=18, index=2}
+                                    Patterns$SimpleBindingPattern$CA(
+                                      value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
+                                    )
+                          }""".replace("_A_", A).replace("_CA_", CA).replace("_value_", value);
+
+        if (!expected.equals(out)) {
+            throw new AssertionError("Unexpected output:\n" + out + "\nexpected:\n" + expected);
+        }
+    }
+
+    private String snipCPNumber(String constantPool, String expectedConstant) {
+        Matcher m = Pattern.compile("#([0-9]+).*" + Pattern.quote(expectedConstant))
+                           .matcher(constantPool);
+        if (!m.find()) {
+            throw new AssertionError("Cannot find constant pool item");
+        }
+
+        return m.group(1);
+    }
+
+    /*********************** Test class *************************/
+    static class SimpleBindingPattern {
+        @Target(ElementType.TYPE_USE)
+        @Repeatable(CA.class)
+        @interface A {}
+        @Target(ElementType.TYPE_USE)
+        @interface CA {
+            public A[] value();
+        }
+
+        private static final Object o = "";
+        private static final boolean B1s = o instanceof @A String s && s.isEmpty();
+        private static final boolean B1m = o instanceof @A @A String s && s.isEmpty();
+        private final boolean B2s = o instanceof @A String s && s.isEmpty();
+        private final boolean B2m = o instanceof @A @A String s && s.isEmpty();
+
+        static {
+            boolean B3s = o instanceof @A String s && s.isEmpty();
+            boolean B3m = o instanceof @A @A String s && s.isEmpty();
+        }
+
+        {
+            boolean B4s = o instanceof @A String s && s.isEmpty();
+            boolean B4m = o instanceof @A @A String s && s.isEmpty();
+        }
+
+        {
+            boolean B5s = o instanceof @A String s && s.isEmpty();
+            boolean B5m = o instanceof @A @A String s && s.isEmpty();
+        }
+
+        public SimpleBindingPattern() {
+            boolean B6s = o instanceof @A String s && s.isEmpty();
+            boolean B6m = o instanceof @A @A String s && s.isEmpty();
+        }
+
+        void testPatterns() {
+            boolean B7s = o instanceof @A String s && s.isEmpty();
+            boolean B7m = o instanceof @A @A String s && s.isEmpty();
+        }
+
+        void testPatternsDesugared() {
+            @A String s;
+            boolean B8s = o instanceof String && (s = (String) o) == s && s.isEmpty();
+            boolean B8sx = o instanceof String && (s = (String) o) == s && s.isEmpty();
+        }
+    }
+}
--- a/test/langtools/tools/javac/api/TestGetElementReference.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/api/TestGetElementReference.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -51,6 +51,9 @@
 
 public class TestGetElementReference {
 
+    private static final String JDK_VERSION =
+            Integer.toString(Runtime.getRuntime().version().feature());
+
     public static void main(String... args) throws IOException {
         analyze("TestGetElementReferenceData.java");
         analyze("mod/module-info.java", "mod/api/pkg/Api.java");
@@ -66,7 +69,10 @@
                 }
             }
             DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
-            JavacTask ct = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, diagnostics, Arrays.asList("-Xjcov"), null, files);
+            List<String> options = List.of("-Xjcov",
+                                           "--enable-preview",
+                                           "-source", JDK_VERSION);
+            JavacTask ct = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, diagnostics, options, null, files);
             Trees trees = Trees.instance(ct);
             CompilationUnitTree cut = ct.parse().iterator().next();
 
--- a/test/langtools/tools/javac/api/TestGetElementReferenceData.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/api/TestGetElementReferenceData.java	Fri Nov 29 10:02:07 2019 +0000
@@ -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
@@ -35,6 +35,8 @@
         java.util.List< /*getElement:INTERFACE:java.util.List*/ String> l;
         utility/*getElement:METHOD:test.TestGetElementReferenceData.Base.utility()*/();
         target(TestGetElementReferenceData :: test/*getElement:METHOD:test.TestGetElementReferenceData.test()*/);
+        Object/*getElement:CLASS:java.lang.Object*/ o = null;
+        if (o/*getElement:LOCAL_VARIABLE:o*/ instanceof String/*getElement:CLASS:java.lang.String*/ str/*getElement:LOCAL_VARIABLE:str*/) ;
     }
     private static void target(Runnable r) { r.run(); }
     public static class Base {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/InstanceofReifiableNotSafe.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.instanceof.reifiable.not.safe
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+import java.util.List;
+
+class InstanceofReifiableNotSafe {
+    boolean test(Object o) {
+        return o instanceof List<String> l;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/MatchBindingExists.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// key: compiler.err.match.binding.exists
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class MatchBindingExists {
+    public void test(Object o1, Object o2) {
+        if (o1 instanceof String k && o2 instanceof Integer k) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/PatternBindingMayNotBeAssigned.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+// key: compiler.err.pattern.binding.may.not.be.assigned
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class ResourceMayNotBeAssigned {
+    void m(Object o) {
+        if (o instanceof String s) {
+            s = "";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/PatternMatchingInstanceof.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.feature.pattern.matching.instanceof
+// key: compiler.warn.preview.feature.use
+// options: --enable-preview -source ${jdk.version} -Xlint:preview
+
+class PatternMatchingInstanceof {
+    boolean m(Object o) {
+        return o instanceof String s && s.isEmpty();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/ReifiableTypesInstanceof.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.feature.reifiable.types.instanceof
+// key: compiler.warn.preview.feature.use.plural
+// options: --enable-preview -source ${jdk.version} -Xlint:preview
+
+class PatternMatchingInstanceof {
+    boolean m(I<String> i) {
+        return i instanceof C<String>;
+    }
+    interface I<T> {}
+    class C<T> implements I<T> {}
+}
--- a/test/langtools/tools/javac/lambda/deduplication/Deduplication.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/lambda/deduplication/Deduplication.java	Fri Nov 29 10:02:07 2019 +0000
@@ -163,6 +163,9 @@
 
         group((Function<Integer, Integer>) x -> switch (x) { default: yield x; },
               (Function<Integer, Integer>) x -> switch (x) { default: yield x; });
+
+        group((Function<Object, Integer>) x -> x instanceof Integer i ? i : -1,
+              (Function<Object, Integer>) x -> x instanceof Integer i ? i : -1);
     }
 
     void f() {}
--- a/test/langtools/tools/javac/lib/DPrinter.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/langtools/tools/javac/lib/DPrinter.java	Fri Nov 29 10:02:07 2019 +0000
@@ -880,7 +880,7 @@
         @Override
         public void visitTypeTest(JCInstanceOf tree) {
             printTree("expr", tree.expr);
-            printTree("clazz", tree.clazz);
+            printTree("pattern", tree.pattern);
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsExistTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,30 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Clashing bindings are reported correctly
+ * @compile/fail/ref=BindingsExistTest.out -XDrawDiagnostics --enable-preview -source ${jdk.version} BindingsExistTest.java
+ */
+public class BindingsExistTest {
+    public void t(Object o1, Object o2) {
+        if (o1 instanceof String k && o2 instanceof Integer k) {}
+
+        if (o1 instanceof String k || o2 instanceof Integer k) {}
+
+        if (!(o1 instanceof String k)) {
+            return ;
+        }
+        if (o1 instanceof Integer k) {}
+
+        String s2 = "";
+        if (o1 instanceof String s2) {}
+
+        if (o1 instanceof String s3) {
+            String s3 = "";
+        }
+
+        if (!(o1 instanceof String s4)) {
+            return ;
+        }
+        String s4 = "";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsExistTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,9 @@
+BindingsExistTest.java:9:36: compiler.err.match.binding.exists
+BindingsExistTest.java:11:36: compiler.err.match.binding.exists
+BindingsExistTest.java:16:35: compiler.err.already.defined: kindname.variable, k, kindname.method, t(java.lang.Object,java.lang.Object)
+BindingsExistTest.java:19:34: compiler.err.already.defined: kindname.variable, s2, kindname.method, t(java.lang.Object,java.lang.Object)
+BindingsExistTest.java:22:20: compiler.err.already.defined: kindname.variable, s3, kindname.method, t(java.lang.Object,java.lang.Object)
+BindingsExistTest.java:28:16: compiler.err.already.defined: kindname.variable, s4, kindname.method, t(java.lang.Object,java.lang.Object)
+- compiler.note.preview.filename: BindingsExistTest.java
+- compiler.note.preview.recompile
+6 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsTest1.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Basic tests for bindings from instanceof
+ * @compile --enable-preview -source ${jdk.version} BindingsTest1.java
+ * @run main/othervm --enable-preview BindingsTest1
+ */
+
+public class BindingsTest1 {
+    public static boolean Ktrue() { return true; }
+    public static void main(String[] args) {
+        Object o1 = "hello";
+        Integer i = 42;
+        Object o2 = i;
+        Object o3 = "there";
+
+
+        // Test for (e matches P).T = { binding variables in P }
+        if (o1 instanceof String s) {
+            s.length();
+        }
+
+        // Test for e1 && e2.T = union(e1.T, e2.T)
+        if (o1 instanceof String s && o2 instanceof Integer in) {
+            s.length();
+            in.intValue();
+        }
+
+        // test for e1&&e2 - include e1.T in e2
+        if (o1 instanceof String s && s.length()>0) {
+            System.out.print("done");
+        }
+
+        // Test for (e1 || e2).F = union(e1.F, e2.F)
+        if (!(o1 instanceof String s) || !(o3 instanceof Integer in)){
+        } else {
+            s.length();
+            i.intValue();
+        }
+
+        // Test for e1||e2 - include e1.F in e2
+
+        if (!(o1 instanceof String s) || s.length()>0) {
+            System.out.println("done");
+        }
+
+        // Test for e1 ? e2: e3 - include e1.T in e2
+        if (o1 instanceof String s ? s.length()>0 : false) {
+            System.out.println("done");
+        }
+
+        // Test for e1 ? e2 : e3 - include e1.F in e3
+        if (!(o1 instanceof String s) ? false : s.length()>0){
+            System.out.println("done");
+        }
+
+        // Test for (!e).T = e.F
+
+        if (!(!(o1 instanceof String s) || !(o3 instanceof Integer in))){
+            s.length();
+            i.intValue();
+        }
+
+        // Test for (!e).F = e.T
+        if (!(o1 instanceof String s)) {
+
+        } else {
+            s.length();
+        }
+
+        L1: {
+            if (o1 instanceof String s) {
+                s.length();
+            } else {
+                break L1;
+            }
+            s.length();
+        }
+
+        L2: {
+            if (!(o1 instanceof String s)) {
+                break L2;
+            } else {
+                s.length();
+            }
+            s.length();
+        }
+
+        L4: {
+            if (!(o1 instanceof String s)) {
+                break L4;
+            }
+            s.length();
+        }
+
+        {
+            while (!(o1 instanceof String s)) {
+            }
+
+            s.length();
+        }
+
+        L5: {
+            while (!(o1 instanceof String s)) {
+            }
+
+            s.length();
+        }
+
+        {
+            L6: for ( ;!(o1 instanceof String s); ) {
+
+            }
+
+            s.length();
+        }
+
+        {
+            L7: do {
+
+            } while (!(o1 instanceof String s));
+
+            s.length();
+        }
+
+        if (o1 instanceof String s) {
+            Runnable r1 = new Runnable() {
+                @Override
+                public void run() {
+                    s.length();
+                }
+            };
+            r1.run();
+            Runnable r2 = () -> {
+                s.length();
+            };
+            r2.run();
+            String s2 = s;
+        }
+
+        System.out.println("BindingsTest1 complete");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsTest1Merging.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,72 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Basic tests for bindings from instanceof - tests for merging pattern variables
+ * @compile/fail/ref=BindingsTest1Merging.out -XDrawDiagnostics --enable-preview -source ${jdk.version} BindingsTest1Merging.java
+ */
+
+public class BindingsTest1Merging {
+    public static boolean Ktrue() { return true; }
+    public static void main(String[] args) {
+        Object o1 = "hello";
+        Integer i = 42;
+        Object o2 = i;
+        Object o3 = "there";
+
+        // Test for e1 && e2.F = intersect(e1.F, e2.F)
+        if (!(o1 instanceof String s) && !(o1 instanceof String s)) {
+
+        } else {
+            s.length();
+        }
+
+        // Test for (e1 || e2).T = intersect(e1.T, e2.T)
+        if (o1 instanceof String s || o3 instanceof String s){
+            System.out.println(s); // ?
+        }
+
+        // Test for (e1 ? e2 : e3).T contains intersect(e2.T, e3.T)
+        if (Ktrue() ? o2 instanceof Integer x : o2 instanceof Integer x) {
+            x.intValue();
+        }
+
+        // Test for (e1 ? e2 : e3).T contains intersect(e1.T, e3.T)
+        if (o1 instanceof String s ? true : o1 instanceof String s) {
+            s.length();
+        }
+
+        // Test for (e1 ? e2 : e3).T contains intersect(e1.F, e2.T)
+        if (!(o1 instanceof String s) ? (o1 instanceof String s) : true) {
+            s.length();
+        }
+
+        // Test for (e1 ? e2 : e3).F contains intersect(e2.F, e3.F)
+        if (Ktrue() ? !(o2 instanceof Integer x) : !(o2 instanceof Integer x)){
+        } else {
+            x.intValue();
+        }
+
+        // Test for (e1 ? e2 : e3).F contains intersect(e1.T, e3.F)
+        if (o1 instanceof String s ? true : !(o1 instanceof String s)){
+        } else {
+            s.length();
+        }
+
+        // Test for (e1 ? e2 : e3).F contains intersect(e1.F, e2.F)
+        if (!(o1 instanceof String s) ? !(o1 instanceof String s) : true){
+        } else {
+            s.length();
+        }
+
+        L3: {
+            if ((o1 instanceof String s) || (o3 instanceof String s)) {
+                s.length();
+            } else {
+                break L3;
+            }
+            s.length();
+        }
+
+        System.out.println("BindingsTest1Merging complete");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsTest1Merging.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,12 @@
+BindingsTest1Merging.java:17:39: compiler.err.match.binding.exists
+BindingsTest1Merging.java:24:36: compiler.err.match.binding.exists
+BindingsTest1Merging.java:29:21: compiler.err.match.binding.exists
+BindingsTest1Merging.java:34:36: compiler.err.match.binding.exists
+BindingsTest1Merging.java:39:39: compiler.err.match.binding.exists
+BindingsTest1Merging.java:44:21: compiler.err.match.binding.exists
+BindingsTest1Merging.java:50:36: compiler.err.match.binding.exists
+BindingsTest1Merging.java:56:39: compiler.err.match.binding.exists
+BindingsTest1Merging.java:62:42: compiler.err.match.binding.exists
+- compiler.note.preview.filename: BindingsTest1Merging.java
+- compiler.note.preview.recompile
+9 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsTest2.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,191 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Ensure that scopes arising from conditionalExpressions are handled corrected.
+ * @compile/fail/ref=BindingsTest2.out -XDrawDiagnostics -XDshould-stop.at=FLOW --enable-preview -source ${jdk.version} BindingsTest2.java
+ */
+public class BindingsTest2 {
+    public static boolean Ktrue() { return true; }
+    public static void main(String[] args) {
+        Object o1 = "hello";
+        Integer in = 42;
+        Object o2 = in;
+        Object o3 = "there";
+
+
+        if (Ktrue() ? o2 instanceof Integer x : o2 instanceof String x) {
+            x.intValue();
+        }
+        if (Ktrue() ? o2 instanceof Integer x : true) {
+            x.intValue();
+        }
+
+        if (o1 instanceof String s ? true : true) {
+            s.length();
+        }
+        if (o1 instanceof String s ? true : o2 instanceof Integer s) {
+            s.length();
+        }
+        if (o1 instanceof String s ? true : o2 instanceof Integer i) {
+            s.length();
+        }
+
+        // Test for (e1 ? e2 : e3).T contains intersect(e1.F, e2.T)
+        if (!(o1 instanceof String s) ? true : true) {
+            s.length();
+        }
+        if (!(o1 instanceof String s) ? (o2 instanceof Integer s) : true) {
+            s.length();
+        }
+        if (!(o1 instanceof String s) ? (o2 instanceof Integer i) : true) {
+            s.length();
+            i.intValue();
+        }
+        if (!(o1 instanceof String s) ? (o1 instanceof String s2) : true) {
+            s.length();
+            s2.length();
+        }
+
+
+        // Test for (e1 ? e2 : e3).F contains intersect(e2.F, e3.F)
+        if (Ktrue() ? !(o2 instanceof Integer x) : !(o1 instanceof String x)){
+        } else {
+            x.intValue();
+        }
+        if (Ktrue() ? !(o2 instanceof Integer x) : !(o1 instanceof String s)){
+        } else {
+            x.intValue();
+        }
+        if (Ktrue() ? !(o2 instanceof Integer x) : !(o2 instanceof Integer x1)){
+        } else {
+            x.intValue();
+            x1.intValue();
+        }
+        if (Ktrue() ? !(o2 instanceof Integer x) : false){
+        } else {
+            x.intValue();
+        }
+
+        // Test for (e1 ? e2 : e3).F contains intersect(e1.T, e3.F)
+        if (o1 instanceof String s ? true : !(o2 instanceof Integer s)){
+        } else {
+            s.length();
+        }
+        if (o1 instanceof String s ? true : !(o2 instanceof Integer i)){
+        } else {
+            s.length();
+            i.intValue();
+        }
+        if (o1 instanceof String s ? true : !(o2 instanceof String s1)){
+        } else {
+            s.length();
+            s1.length();
+        }
+        // Test for (e1 ? e2 : e3).F contains intersect(e1.F, e2.F)
+        if (!(o1 instanceof String s) ? !(o1 instanceof String s1) : true){
+        } else {
+            s.length();
+            s1.length();
+        }
+        if (!(o1 instanceof String s) ? !(o2 instanceof Integer s) : true){
+        } else {
+            s.length();
+        }
+        if (!(o1 instanceof String s) ? !(o2 instanceof Integer i) : true){
+        } else {
+            s.length();
+            i.intValue();
+        }
+
+        // Test for e1 ? e2: e3 - include e1.T in e2
+        if (o1 instanceof String s ? false : s.length()>0) {
+            System.out.println("done");
+        }
+        if (o1 instanceof String s ? false : s.intValue!=0) {
+            System.out.println("done");
+        }
+
+        // Test for e1 ? e2 : e3 - include e1.F in e3
+        if (!(o1 instanceof String s) ? s.length()>0 : false){
+            System.out.println("done");
+        }
+        if (!(o1 instanceof String s) ? s.intValue>0 : false){
+            System.out.println("done");
+        }
+
+        {
+            while (!(o1 instanceof String s)) {
+                break;
+            }
+
+            s.length();
+        }
+
+        {
+            while (!(o1 instanceof String s)) {
+                if (false) break;
+            }
+
+            s.length();
+        }
+
+        {
+            while (!(o1 instanceof String s)) {
+                while (true);
+                break;
+            }
+
+            s.length();
+        }
+
+        {
+            for (; !(o1 instanceof String s); ) {
+                break;
+            }
+
+            s.length();
+        }
+
+        {
+            for (; !(o1 instanceof String s); ) {
+                if (false) break;
+            }
+
+            s.length();
+        }
+
+        {
+            for (; !(o1 instanceof String s); ) {
+                while (true);
+                break;
+            }
+
+            s.length();
+        }
+
+        {
+            do {
+                break;
+            } while (!(o1 instanceof String s));
+
+            s.length();
+        }
+
+        {
+            do {
+                if (false) break;
+            } while (!(o1 instanceof String s));
+
+            s.length();
+        }
+
+        {
+            do {
+                while (true);
+                break;
+            } while (!(o1 instanceof String s));
+
+            s.length();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/BindingsTest2.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,48 @@
+BindingsTest2.java:16:21: compiler.err.match.binding.exists
+BindingsTest2.java:17:14: compiler.err.cant.resolve.location.args: kindname.method, intValue, , , (compiler.misc.location.1: kindname.variable, x, java.lang.String)
+BindingsTest2.java:20:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:24:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:26:36: compiler.err.match.binding.exists
+BindingsTest2.java:27:14: compiler.err.cant.resolve.location.args: kindname.method, length, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
+BindingsTest2.java:30:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:35:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:37:39: compiler.err.match.binding.exists
+BindingsTest2.java:38:14: compiler.err.cant.resolve.location.args: kindname.method, length, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
+BindingsTest2.java:41:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:42:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:45:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:46:13: compiler.err.cant.resolve.location: kindname.variable, s2, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:51:21: compiler.err.match.binding.exists
+BindingsTest2.java:53:14: compiler.err.cant.resolve.location.args: kindname.method, intValue, , , (compiler.misc.location.1: kindname.variable, x, java.lang.String)
+BindingsTest2.java:57:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:61:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:62:13: compiler.err.cant.resolve.location: kindname.variable, x1, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:66:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:70:36: compiler.err.match.binding.exists
+BindingsTest2.java:72:14: compiler.err.cant.resolve.location.args: kindname.method, length, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
+BindingsTest2.java:76:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:77:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:81:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:82:13: compiler.err.cant.resolve.location: kindname.variable, s1, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:87:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:88:13: compiler.err.cant.resolve.location: kindname.variable, s1, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:90:39: compiler.err.match.binding.exists
+BindingsTest2.java:92:14: compiler.err.cant.resolve.location.args: kindname.method, length, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
+BindingsTest2.java:96:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:97:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:101:46: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:104:46: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:109:41: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:112:41: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:121:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:129:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:146:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:154:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:171:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:179:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
+BindingsTest2.java:135:17: compiler.err.unreachable.stmt
+BindingsTest2.java:160:17: compiler.err.unreachable.stmt
+BindingsTest2.java:185:17: compiler.err.unreachable.stmt
+- compiler.note.preview.filename: BindingsTest2.java
+- compiler.note.preview.recompile
+45 errors
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/CastConversionMatch.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamicopyright/
+ * @bug 8231827
+ * @summary Match which involves a cast conversion
+ * @compile/fail/ref=CastConversionMatch.out -XDrawDiagnostics --enable-preview -source ${jdk.version} CastConversionMatch.java
+ */
+
+public class CastConversionMatch {
+    public static void main(String [] args) {
+        Object o = 42;
+        if (o instanceof int s) {
+            System.out.println("Okay");
+        } else {
+            throw new AssertionError("broken");
+        }
+        System.out.println(">Test complete");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/CastConversionMatch.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,4 @@
+CastConversionMatch.java:11:26: compiler.err.type.found.req: int, (compiler.misc.type.req.class.array)
+- compiler.note.preview.filename: CastConversionMatch.java
+- compiler.note.preview.recompile
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/DuplicateBindingTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Basic pattern bindings scope test
+ * @compile/fail/ref=DuplicateBindingTest.out -XDrawDiagnostics --enable-preview -source ${jdk.version} DuplicateBindingTest.java
+ */
+
+public class DuplicateBindingTest {
+
+    int f;
+
+    public static void main(String[] args) {
+
+        if (args != null) {
+            int s;
+            if (args[0] instanceof String s) { // NOT OK. Redef same scope.
+            }
+            if (args[0] instanceof String f) { // OK to redef field.
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/DuplicateBindingTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,4 @@
+DuplicateBindingTest.java:16:43: compiler.err.already.defined: kindname.variable, s, kindname.method, main(java.lang.String[])
+- compiler.note.preview.filename: DuplicateBindingTest.java
+- compiler.note.preview.recompile
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/EnsureTypesOrderTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8187420 8231827
+ * @summary Error message mentions relevant types transposed
+ * @compile/fail/ref=EnsureTypesOrderTest.out -XDrawDiagnostics --enable-preview -source ${jdk.version} EnsureTypesOrderTest.java
+ */
+public class EnsureTypesOrderTest {
+    public static void main(String [] args) {
+        if (args instanceof String s) {
+            System.out.println("Broken");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/EnsureTypesOrderTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,4 @@
+EnsureTypesOrderTest.java:9:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String[], java.lang.String)
+- compiler.note.preview.filename: EnsureTypesOrderTest.java
+- compiler.note.preview.recompile
+1 error
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ExamplesFromProposal.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary All example code from "Pattern Matching for Java" document, released April 2017, adjusted to current state (no switches, etc)
+ * @compile --enable-preview -source ${jdk.version} ExamplesFromProposal.java
+ * @run main/othervm --enable-preview ExamplesFromProposal
+ */
+
+interface Node {
+}
+
+class IntNode implements Node {
+    int value;
+
+    IntNode(int value) {
+        this.value = value;
+    }
+}
+
+class NegNode implements Node {
+    Node node;
+
+    NegNode(Node node) {
+        this.node = node;
+    }
+}
+
+class MulNode implements Node {
+    Node left, right;
+
+    MulNode(Node left, Node right) {
+        this.left = left;
+        this.right = right;
+    }
+}
+
+class AddNode implements Node {
+    Node left, right;
+
+    AddNode(Node left, Node right) {
+        this.left = left;
+        this.right = right;
+    }
+}
+
+public class ExamplesFromProposal {
+
+    public static Object getSomething() {
+        return new Long(42);
+    }
+
+    public static int eval(Node n) {
+        if (n instanceof IntNode in) return in.value;
+        else if (n instanceof NegNode nn) return -eval(nn.node);
+        else if (n instanceof AddNode an) return eval(an.left) + eval(an.right);
+        else if (n instanceof MulNode mn) return eval(mn.left) * eval(mn.right);
+        else {
+            // should never happen
+            throw new AssertionError("broken");
+        }
+    }
+
+    public static String toString(Node n) {
+        if (n instanceof IntNode in) return String.valueOf(in.value);
+        else if (n instanceof NegNode nn) return "-"+eval(nn.node);
+        else if (n instanceof AddNode an) return eval(an.left) + " + " + eval(an.right);
+        else if (n instanceof MulNode mn) return eval(mn.left) + " * " + eval(mn.right);
+        else {
+            // should never happen
+            throw new AssertionError("broken");
+        }
+    }
+
+    public static Node simplify(Node n) {
+        if (n instanceof IntNode in) {
+            return n;
+        } else if (n instanceof NegNode nn) {
+            return new NegNode(simplify(nn.node));
+        } else if (n instanceof AddNode ad) {
+            n = simplify(ad.left);
+            if (n instanceof IntNode intn) {
+                if (intn.value == 0)
+                    return simplify(ad.right);
+                else
+                    return new AddNode(intn, simplify(ad.right));
+            } else {
+                return new AddNode(simplify(ad.left), simplify(ad.right));
+            }
+        } else if (n instanceof MulNode mn) {
+            return new MulNode(simplify(mn.left), simplify(mn.right));
+        } else {
+            //should never happen
+            throw new AssertionError("broken");
+        }
+    }
+
+    public static void testNode(Node n, int expected) {
+        if (eval(n) != expected)
+            throw new AssertionError("broken");
+    }
+
+    public static void main(String[] args) {
+        Object x = new Integer(42);
+
+        if (x instanceof Integer i) {
+            // can use i here
+            System.out.println(i.intValue());
+        }
+
+        Object obj = getSomething();
+
+        String formatted = "unknown";
+        if (obj instanceof Integer i) {
+            formatted = String.format("int %d", i);
+        }
+        else if (obj instanceof Byte b) {
+            formatted = String.format("byte %d", b);
+        }
+        else if (obj instanceof Long l) {
+            formatted = String.format("long %d", l);
+        }
+        else if (obj instanceof Double d) {
+            formatted = String.format("double %f", d);
+        }
+        else if (obj instanceof String s) {
+            formatted = String.format("String %s", s);
+        }
+        System.out.println(formatted);
+
+        if (obj instanceof Integer i) formatted = String.format("int %d", i);
+        else if (obj instanceof Byte b) formatted = String.format("byte %d", b);
+        else if (obj instanceof Long l) formatted = String.format("long %d", l);
+        else if (obj instanceof Double d) formatted = String.format("double %f", d);
+        else if (obj instanceof String s) formatted = String.format("String %s", s);
+        else formatted = String.format("Something else "+ obj.toString());
+        System.out.println(formatted);
+
+        Node zero = new IntNode(0);
+        Node one = new IntNode(1);
+        Node ft = new IntNode(42);
+
+        Node temp = new AddNode(zero,ft);
+
+        testNode(temp,42);
+
+
+
+        if (toString(simplify(temp)).equals(toString(ft)))
+            System.out.println("Simplify worked!");
+        else
+            throw new AssertionError("broken");
+
+
+        if (toString(simplify(new AddNode(zero,temp))).equals(toString(ft)))
+            System.out.println("Simplify worked!");
+        else
+            throw new AssertionError("broken");
+
+
+        temp = new AddNode(zero,ft);
+        temp = new AddNode(one,temp);
+        temp = new AddNode(zero,temp);
+
+        Node fortythree = new AddNode(one,ft);
+
+        if (toString(simplify(temp)).equals(toString(fortythree)))
+            System.out.println("Simplify worked!");
+        else
+            throw new AssertionError("broken");
+
+
+        x = "Hello";
+
+        if (x instanceof String s1) {
+            System.out.println(s1);
+        }
+        if (x instanceof String s1 && s1.length() > 0) {
+            System.out.println(s1);
+        }
+        if (x instanceof String s1) {
+            System.out.println(s1 + " is a string");
+        } else {
+            System.out.println("not a string");
+        }
+
+        if (!(x instanceof String s1)) {
+            System.out.println("not a string");
+        } else {
+            System.out.println(s1 + " is a string");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ImpossibleTypeTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Ensure that in type test patterns, the predicate is not trivially provable false.
+ * @compile/fail/ref=ImpossibleTypeTest.out -XDrawDiagnostics --enable-preview -source ${jdk.version} ImpossibleTypeTest.java
+ */
+public class ImpossibleTypeTest {
+
+    public static void main(String[] args) {
+
+        int in = 42;
+        Integer i = 42;
+
+        if (i instanceof String s ) {
+            System.out.println("Broken");
+        }
+        if (i instanceof Undefined u ) {
+            System.out.println("Broken");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ImpossibleTypeTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,5 @@
+ImpossibleTypeTest.java:14:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String)
+ImpossibleTypeTest.java:17:26: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, ImpossibleTypeTest, null)
+- compiler.note.preview.filename: ImpossibleTypeTest.java
+- compiler.note.preview.recompile
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/LocalVariableTable.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Ensure the LV table entries are generated for bindings
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * @compile -g --enable-preview -source ${jdk.version} LocalVariableTable.java
+ * @run main/othervm --enable-preview LocalVariableTable
+ */
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+import com.sun.tools.classfile.*;
+
+/*
+ * The test checks that a LocalVariableTable attribute is generated for the
+ * method bodies containing patterns, and checks that the expected
+ * set of entries is found in the attribute.
+ *
+ * The test looks for test cases represented by nested classes whose
+ * name begins with "Pattern".  Each such class contains a method
+ * with patterns, and because the test is compiled
+ * with -g, these methods should have a LocalVariableTable.  The set of
+ * expected names in the LVT is provided in an annotation on the class for
+ * the test case.
+ */
+//Copied from: test/langtools/tools/javac/lambda/LocalVariableTable.java
+public class LocalVariableTable {
+    public static void main(String... args) throws Exception {
+        new LocalVariableTable().run();
+    }
+
+    void run() throws Exception {
+        // the declared classes are returned in an unspecified order,
+        // so for neatness, sort them by name before processing them
+        Class<?>[] classes = getClass().getDeclaredClasses();
+        Arrays.sort(classes, (c1, c2) -> c1.getName().compareTo(c2.getName()));
+
+        for (Class<?> c : classes) {
+            if (c.getSimpleName().startsWith("Pattern"))
+                check(c);
+        }
+        if (errors > 0)
+            throw new Exception(errors + " errors found");
+    }
+
+    /** Check an individual test case. */
+    void check(Class<?> c) throws Exception {
+        System.err.println("Checking " + c.getSimpleName());
+
+        Expect expect = c.getAnnotation(Expect.class);
+        if (expect == null) {
+            error("@Expect not found for class " + c.getSimpleName());
+            return;
+        }
+
+        ClassFile cf = ClassFile.read(getClass().getResource(c.getName() + ".class").openStream());
+        Method m = getMethodByName(cf, c.getSimpleName().contains("Lambda") ? "lambda$" : "test");
+        if (m == null) {
+            error("test method not found");
+            return;
+        }
+
+        Code_attribute code = (Code_attribute) m.attributes.get(Attribute.Code);
+        if (code == null) {
+            error("Code attribute not found");
+            return;
+        }
+
+        LocalVariableTable_attribute lvt =
+                (LocalVariableTable_attribute) code.attributes.get(Attribute.LocalVariableTable);
+        if (lvt == null) {
+            error("LocalVariableTable attribute not found");
+            return;
+        }
+
+        Set<String> foundNames = new LinkedHashSet<>();
+        for (LocalVariableTable_attribute.Entry e: lvt.local_variable_table) {
+            foundNames.add(cf.constant_pool.getUTF8Value(e.name_index));
+        }
+
+        Set<String> expectNames = new LinkedHashSet<>(Arrays.asList(expect.value()));
+        if (!foundNames.equals(expectNames)) {
+            Set<String> foundOnly = new LinkedHashSet<>(foundNames);
+            foundOnly.removeAll(expectNames);
+            for (String s: foundOnly)
+                error("Unexpected name found: " + s);
+            Set<String> expectOnly = new LinkedHashSet<>(expectNames);
+            expectOnly.removeAll(foundNames);
+            for (String s: expectOnly)
+                error("Expected name not found: " + s);
+        }
+    }
+
+    Method getMethodByName(ClassFile cf, String name) throws ConstantPoolException {
+        for (Method m: cf.methods) {
+            if (m.getName(cf.constant_pool).startsWith(name))
+                return m;
+        }
+        return null;
+    }
+
+    /** Report an error. */
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+
+    /**
+     * Annotation used to provide the set of names expected in the LVT attribute.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Expect {
+        String[] value();
+    }
+
+    /*
+     * ---------- Test cases ---------------------------------------------------
+     */
+
+    @Expect({ "o", "s" })
+    static class Pattern_Simple {
+        public static void test(Object o) {
+            if (o instanceof String s) {}
+        }
+    }
+
+    @Expect({ "s" })
+    static class Pattern_Lambda {
+        public static void test(Object o) {
+            if (o instanceof String s) {
+                Runnable r = () -> {
+                    s.length();
+                };
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/MatchBindingScopeTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,68 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Basic pattern bindings scope test
+ * @compile/fail/ref=MatchBindingScopeTest.out -XDrawDiagnostics --enable-preview -source ${jdk.version} MatchBindingScopeTest.java
+ */
+public class MatchBindingScopeTest {
+
+    static Integer i = 42;
+    static String s = "Hello";
+    static Object o1 = s;
+    static Object o2 = i;
+
+    public static void main(String[] args) {
+
+        if (o1 instanceof String j && j.length() == 5) { // OK
+            System.out.println(j); // OK
+        } else {
+            System.out.println(j); // NOT OK
+        }
+
+        // NOT OK, name reused.
+        if (o1 instanceof String j && o2 instanceof Integer j) {
+        }
+
+        if (o1 instanceof String j && j.length() == 5 && o2 instanceof Integer k && k == 42) { // OK
+            System.out.println(j); // OK
+            System.out.println(k); // OK
+        } else {
+            System.out.println(j); // NOT OK
+            System.out.println(k); // NOT OK
+        }
+
+        if (o1 instanceof String j || j.length() == 5) { // NOT OK
+            System.out.println(j); // NOT OK
+        }
+
+        if (o1 instanceof String j || o2 instanceof Integer j) { // NOT OK, types differ
+            System.out.println(j);
+        } else {
+            System.out.println(j); // NOT OK.
+        }
+
+        while (o1 instanceof String j && j.length() == 5) { // OK
+            System.out.println(j); // OK
+        }
+
+        while (o1 instanceof String j || true) {
+            System.out.println(j); // Not OK
+        }
+
+        for (; o1 instanceof String j; j.length()) { // OK
+            System.out.println(j); // OK
+        }
+
+        for (; o1 instanceof String j || true; j.length()) { // NOT OK
+            System.out.println(j); // Not OK
+        }
+
+        int x = o1 instanceof String j ?
+                      j.length() : // OK.
+                      j.length();  // NOT OK.
+
+        x = !(o1 instanceof String j) ?
+                      j.length() : // NOT OK.
+                      j.length();  // OK.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/MatchBindingScopeTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,16 @@
+MatchBindingScopeTest.java:19:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:23:36: compiler.err.match.binding.exists
+MatchBindingScopeTest.java:30:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:31:32: compiler.err.cant.resolve.location: kindname.variable, k, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:34:39: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:35:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:38:36: compiler.err.match.binding.exists
+MatchBindingScopeTest.java:41:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:49:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:56:48: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:57:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:62:23: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+MatchBindingScopeTest.java:65:23: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
+- compiler.note.preview.filename: MatchBindingScopeTest.java
+- compiler.note.preview.recompile
+13 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/NullsInPatterns.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Testing pattern matching against the null constant
+ * @compile --enable-preview -source ${jdk.version} NullsInPatterns.java
+ * @run main/othervm --enable-preview NullsInPatterns
+ */
+import java.util.List;
+
+public class NullsInPatterns {
+
+    public static void main(String[] args) {
+        if (null instanceof List t) {
+            throw new AssertionError("broken");
+        } else {
+            System.out.println("null does not match List type pattern");
+        }
+        //reifiable types not allowed in type test patterns in instanceof:
+//        if (null instanceof List<Integer> l) {
+//            throw new AssertionError("broken");
+//        } else {
+//            System.out.println("null does not match List<Integer> type pattern");
+//        }
+        if (null instanceof List<?> l) {
+            throw new AssertionError("broken");
+        } else {
+            System.out.println("null does not match List<?> type pattern");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternMatchPosTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Check proper positions.
+ * @build PatternMatchPosTest
+ * @compile/ref=PatternMatchPosTest.out -processor PatternMatchPosTest -Xlint:unchecked -XDrawDiagnostics --enable-preview -source ${jdk.version} PatternMatchPosTestData.java
+ */
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+import com.sun.source.tree.IfTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+import javax.tools.Diagnostic;
+
+@SupportedAnnotationTypes("*")
+public class PatternMatchPosTest extends AbstractProcessor {
+
+    int round;
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (round++ != 0)
+            return false;
+
+        try {
+            TypeElement data = processingEnv.getElementUtils().getTypeElement("PatternMatchPosTestData");
+            Trees trees = Trees.instance(processingEnv);
+            SourcePositions sp = trees.getSourcePositions();
+            TreePath dataPath = trees.getPath(data);
+            String text = dataPath.getCompilationUnit().getSourceFile().getCharContent(true).toString();
+
+            new TreeScanner<Void, Void>() {
+                boolean print;
+                @Override
+                public Void visitIf(IfTree node, Void p) {
+                    boolean prevPrint = print;
+                    try {
+                        print = true;
+                        scan(node.getCondition(), p);
+                    } finally {
+                        print = prevPrint;
+                    }
+                    scan(node.getThenStatement(), p);
+                    scan(node.getElseStatement(), p);
+                    return null;
+                }
+                @Override
+                public Void scan(Tree tree, Void p) {
+                    if (tree == null)
+                        return null;
+                    if (print) {
+                        int start = (int) sp.getStartPosition(dataPath.getCompilationUnit(), tree);
+                        int end = (int) sp.getEndPosition(dataPath.getCompilationUnit(), tree);
+                        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
+                                                                 text.substring(start, end));
+                    }
+                    return super.scan(tree, p);
+                }
+            }.scan(dataPath.getLeaf(), null);
+            return false;
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latestSupported();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternMatchPosTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,14 @@
+- compiler.note.proc.messager: (o instanceof String s)
+- compiler.note.proc.messager: o instanceof String s
+- compiler.note.proc.messager: o
+- compiler.note.proc.messager: String s
+- compiler.note.proc.messager: String
+- compiler.note.proc.messager: (o instanceof java.lang.String s)
+- compiler.note.proc.messager: o instanceof java.lang.String s
+- compiler.note.proc.messager: o
+- compiler.note.proc.messager: java.lang.String s
+- compiler.note.proc.messager: java.lang.String
+- compiler.note.proc.messager: java.lang
+- compiler.note.proc.messager: java
+- compiler.note.preview.filename: PatternMatchPosTestData.java
+- compiler.note.preview.recompile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternMatchPosTestData.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+class PatternMatchPosTestData {
+    void data(Object o) {
+        if (o instanceof String s) { }
+        if (o instanceof java.lang.String s) { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternTypeTest2.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Basic pattern test
+ * @compile --enable-preview -source ${jdk.version} PatternTypeTest2.java
+ * @run main/othervm --enable-preview PatternTypeTest2
+ */
+public class PatternTypeTest2 {
+
+    public static void main(String[] args) {
+
+        Integer i = 42;
+        String s = "Hello";
+        Object o = i;
+
+        if (o instanceof Integer j) {
+            System.out.println("It's an Integer");
+        } else {
+            throw new AssertionError("Broken");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternVariablesAreFinal.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Ensure that in type test patterns, the predicate is not trivially provable false.
+ * @compile/fail/ref=PatternVariablesAreFinal.out -XDrawDiagnostics --enable-preview -source ${jdk.version} PatternVariablesAreFinal.java
+ */
+public class PatternVariablesAreFinal {
+    public static void main(String[] args) {
+        Object o = 32;
+        if (o instanceof String s) {
+            s = "hello again";
+            System.out.println(s);
+        }
+        System.out.println("test complete");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternVariablesAreFinal.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,4 @@
+PatternVariablesAreFinal.java:11:13: compiler.err.pattern.binding.may.not.be.assigned: s
+- compiler.note.preview.filename: PatternVariablesAreFinal.java
+- compiler.note.preview.recompile
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternVariablesAreFinal2.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Pattern variables are final so should be allowed to be referenced in an inner class
+ * @compile --enable-preview -source ${jdk.version} PatternVariablesAreFinal2.java
+ * @run main/othervm --enable-preview PatternVariablesAreFinal2
+ */
+public class PatternVariablesAreFinal2 {
+    public static void main(String[] args) {
+        Object o = "42";
+        if (o instanceof String s) {
+            new Object() {
+                void run() { System.err.println(s); }
+            }.run();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/PatternsSimpleVisitorTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231827
+ * @summary Ensure SimpleTreeVisitor.visitBindingPattern and visitInstanceOf behaves as it should
+ * @modules jdk.compiler
+ */
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.*;
+
+import com.sun.source.tree.BindingPatternTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.InstanceOfTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.SimpleTreeVisitor;
+import com.sun.source.util.TreePathScanner;
+
+public class PatternsSimpleVisitorTest {
+
+    public static void main(String[] args) throws Exception {
+        new PatternsSimpleVisitorTest().run();
+    }
+
+    void run() throws Exception {
+        String code = "class Test {\n" +
+                      "    boolean t(Object o) {\n" +
+                      "         return o instanceof String s ? s.isEmpty() : false;\n" +
+                      "    }\n" +
+                      "}\n";
+        int[] callCount = new int[1];
+        int[] instanceOfNodeCount = new int[1];
+        int[] bindingPatternNodeCount = new int[1];
+        new TreePathScanner<Void, Void>() {
+            @Override
+            public Void visitInstanceOf(InstanceOfTree node, Void p) {
+                node.accept(new SimpleTreeVisitor<Void, Void>() {
+                    @Override
+                    protected Void defaultAction(Tree defaultActionNode, Void p) {
+                        callCount[0]++;
+                        if (node == defaultActionNode) {
+                            instanceOfNodeCount[0]++;
+                        }
+                        return null;
+                    }
+                }, null);
+                return super.visitInstanceOf(node, p);
+            }
+            @Override
+            public Void visitBindingPattern(BindingPatternTree node, Void p) {
+                node.accept(new SimpleTreeVisitor<Void, Void>() {
+                    @Override
+                    protected Void defaultAction(Tree defaultActionNode, Void p) {
+                        callCount[0]++;
+                        if (node == defaultActionNode) {
+                            bindingPatternNodeCount[0]++;
+                        }
+                        return null;
+                    }
+                }, null);
+                return super.visitBindingPattern(node, p);
+            }
+        }.scan(parse(code), null);
+
+        if (callCount[0] != 2 || instanceOfNodeCount[0] != 1 ||
+            bindingPatternNodeCount[0] != 1) {
+            throw new AssertionError("Unexpected counts; callCount=" + callCount[0] +
+                                     ", switchExprNodeCount=" + instanceOfNodeCount[0] +
+                                     ", yieldNodeCount=" + bindingPatternNodeCount[0]);
+        }
+    }
+
+    private CompilationUnitTree parse(String code) throws IOException {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        assert tool != null;
+        DiagnosticListener<JavaFileObject> noErrors = d -> {};
+
+        StringWriter out = new StringWriter();
+        JavacTask ct = (JavacTask) tool.getTask(out, null, noErrors,
+            List.of("--enable-preview", "-source", Integer.toString(Runtime.version().feature())), null,
+            Arrays.asList(new MyFileObject(code)));
+        return ct.parse().iterator().next();
+    }
+
+    static class MyFileObject extends SimpleJavaFileObject {
+        private String text;
+
+        public MyFileObject(String text) {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            this.text = text;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return text;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/Reifiable.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Verify behavior w.r.t. non-reifiable types and type test patterns in instanceof
+ * @compile/fail/ref=Reifiable.out --enable-preview -source ${jdk.version} -XDrawDiagnostics Reifiable.java
+ */
+
+public class Reifiable implements ReifiableI {
+    private static boolean test(Object o, List<Reifiable> l1, List<String> l2) {
+        return o instanceof ListImpl<Reifiable> li1 &&
+               l1 instanceof ListImpl<Reifiable> li2 &&
+               l2 instanceof ListImpl<Reifiable> li3 &&
+               l2 instanceof ListImpl<String> li4 &&
+               l1 instanceof Unrelated<Reifiable> li5;
+    }
+
+    public class List<T> {}
+    public class ListImpl<T extends ReifiableI> extends List<T> {}
+    public class Unrelated<T> {}
+}
+
+interface ReifiableI {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/Reifiable.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,7 @@
+Reifiable.java:10:16: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, Reifiable.ListImpl<Reifiable>
+Reifiable.java:12:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Reifiable.List<java.lang.String>, Reifiable.ListImpl<Reifiable>)
+Reifiable.java:13:39: compiler.err.not.within.bounds: java.lang.String, T
+Reifiable.java:14:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Reifiable.List<Reifiable>, Reifiable.Unrelated<Reifiable>)
+- compiler.note.preview.filename: Reifiable.java
+- compiler.note.preview.recompile
+4 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ReifiableOld-old.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,7 @@
+ReifiableOld.java:12:37: compiler.err.illegal.generic.type.for.instof
+ReifiableOld.java:13:38: compiler.err.illegal.generic.type.for.instof
+ReifiableOld.java:14:38: compiler.err.illegal.generic.type.for.instof
+ReifiableOld.java:15:38: compiler.err.illegal.generic.type.for.instof
+ReifiableOld.java:15:39: compiler.err.not.within.bounds: java.lang.String, T
+ReifiableOld.java:16:39: compiler.err.illegal.generic.type.for.instof
+6 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ReifiableOld.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,24 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8231827
+ * @summary Verify behavior w.r.t. non-reifiable types in instanceof
+ * @compile/fail/ref=ReifiableOld-old.out -source 13 -Xlint:-options -XDrawDiagnostics ReifiableOld.java
+ * @compile/fail/ref=ReifiableOld-old.out -source ${jdk.version} -XDrawDiagnostics ReifiableOld.java
+ * @compile/fail/ref=ReifiableOld.out --enable-preview -source ${jdk.version} -XDrawDiagnostics ReifiableOld.java
+ */
+
+public class ReifiableOld implements ReifiableOldI {
+    private static boolean test(Object o, List<ReifiableOld> l1, List<String> l2) {
+        return o instanceof ListImpl<ReifiableOld> &&
+               l1 instanceof ListImpl<ReifiableOld> &&
+               l2 instanceof ListImpl<ReifiableOld> &&
+               l2 instanceof ListImpl<String> &&
+               l1 instanceof Unrelated<ReifiableOld>;
+    }
+
+    public class List<T> {}
+    public class ListImpl<T extends ReifiableOldI> extends List<T> {}
+    public class Unrelated<T> {}
+}
+
+interface ReifiableOldI {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/ReifiableOld.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,7 @@
+ReifiableOld.java:12:16: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, ReifiableOld.ListImpl<ReifiableOld>
+ReifiableOld.java:14:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: ReifiableOld.List<java.lang.String>, ReifiableOld.ListImpl<ReifiableOld>)
+ReifiableOld.java:15:39: compiler.err.not.within.bounds: java.lang.String, T
+ReifiableOld.java:16:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: ReifiableOld.List<ReifiableOld>, ReifiableOld.Unrelated<ReifiableOld>)
+- compiler.note.preview.filename: ReifiableOld.java
+- compiler.note.preview.recompile
+4 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/UncheckedWarningOnMatchesTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8187429 8231827
+ * @summary Missing unchecked conversion warning
+ * @compile/fail/ref=UncheckedWarningOnMatchesTest.out -Xlint:unchecked -Werror -XDrawDiagnostics --enable-preview -source ${jdk.version} UncheckedWarningOnMatchesTest.java
+ */
+import java.util.ArrayList;
+
+public class UncheckedWarningOnMatchesTest {
+
+    public static void main(String [] args) {
+
+        Object o = new ArrayList<UncheckedWarningOnMatchesTest>();
+        if (o instanceof ArrayList<Integer> ai) {  // unchecked conversion
+            System.out.println("Blah");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/UncheckedWarningOnMatchesTest.out	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,4 @@
+UncheckedWarningOnMatchesTest.java:14:13: compiler.err.instanceof.reifiable.not.safe: java.lang.Object, java.util.ArrayList<java.lang.Integer>
+- compiler.note.preview.filename: UncheckedWarningOnMatchesTest.java
+- compiler.note.preview.recompile
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/scope/ScopeTest.java	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+import tools.javac.combo.JavacTemplateTestBase;
+
+import static java.util.stream.Collectors.toList;
+
+@Test
+public class ScopeTest extends JavacTemplateTestBase {
+
+    private static String st_block(String... statements) {
+        return Arrays.stream(statements).collect(Collectors.joining("", "{", "}"));
+    }
+
+    private static String st_if(String condition, String then, String els) {
+        return "if (" + condition + ") " + then + " else " + els;
+    }
+
+    private static String st_while(String condition, String body) {
+        return "while (" + condition + ") " + body;
+    }
+
+    private static String st_do_while(String body, String condition) {
+        return "do " + body + " while (" + condition + ");";
+    }
+
+    private static String st_for(String init, String condition, String update, String body) {
+        return "for (" + init + "; " + condition + "; " + update + ") " + body;
+    }
+
+    private static String st_s_use() {
+        return "s.length();";
+    }
+
+    private static String st_break() {
+        return "break;";
+    }
+
+    private static String st_return() {
+        return "return;";
+    }
+
+    private static String st_noop() {
+        return ";";
+    }
+
+    private static String expr_empty() {
+        return "";
+    }
+
+    private static String expr_o_match_str() {
+        return "o instanceof String s";
+    }
+
+    private static String expr_not(String expr) {
+        return "!(" + expr + ")";
+    }
+
+    @AfterMethod
+    public void dumpTemplateIfError(ITestResult result) {
+        // Make sure offending template ends up in log file on failure
+        if (!result.isSuccess()) {
+            System.err.printf("Diagnostics: %s%nTemplate: %s%n", diags.errorKeys(), sourceFiles.stream().map(p -> p.snd).collect(toList()));
+        }
+    }
+
+    private void program(String block) {
+        String s = "class C { void m(Object o) " + block + "}";
+        addSourceFile("C.java", new StringTemplate(s));
+    }
+
+    private void assertOK(String block) {
+        String sourceVersion = Integer.toString(Runtime.version().feature());
+
+        reset();
+        addCompileOptions("--enable-preview", "-source", sourceVersion);
+        program(block);
+        try {
+            compile();
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        assertCompileSucceeded();
+    }
+
+    private void assertFail(String expectedDiag, String block) {
+        String sourceVersion = Integer.toString(Runtime.version().feature());
+
+        reset();
+        addCompileOptions("--enable-preview", "-source", sourceVersion);
+        program(block);
+        try {
+            compile();
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        assertCompileFailed(expectedDiag);
+    }
+
+    public void testIf() {
+        assertOK(st_block(st_if(expr_o_match_str(), st_s_use(), st_return()), st_s_use()));
+        assertOK(st_block(st_if(expr_not(expr_o_match_str()), st_return(), st_s_use()), st_s_use()));
+        assertFail("compiler.err.cant.resolve.location", st_block(st_if(expr_o_match_str(), st_s_use(), st_noop()), st_s_use()));
+        assertFail("compiler.err.cant.resolve.location", st_block(st_if(expr_not(expr_o_match_str()), st_noop(), st_s_use()), st_s_use()));
+    }
+
+    public void testWhile() {
+        assertOK(st_block(st_while(expr_not(expr_o_match_str()), st_noop()), st_s_use()));
+        assertFail("compiler.err.cant.resolve.location", st_block(st_while(expr_not(expr_o_match_str()), st_break()), st_s_use()));
+    }
+
+    public void testDoWhile() {
+        assertOK(st_block(st_do_while(st_noop(), expr_not(expr_o_match_str())), st_s_use()));
+        assertFail("compiler.err.cant.resolve.location", st_block(st_do_while(st_break(), expr_not(expr_o_match_str())), st_s_use()));
+    }
+
+    public void testFor() {
+        assertOK(st_block(st_for(expr_empty(), expr_not(expr_o_match_str()), expr_empty(), st_noop()), st_s_use()));
+        assertFail("compiler.err.cant.resolve.location", st_block(st_for(expr_empty(), expr_not(expr_o_match_str()), expr_empty(), st_break()), st_s_use()));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/patterns/scope/TEST.properties	Fri Nov 29 10:02:07 2019 +0000
@@ -0,0 +1,6 @@
+TestNG.dirs = .
+
+lib.dirs = /lib/combo
+
+modules = \
+        jdk.compiler/com.sun.tools.javac.util
--- a/test/lib/sun/hotspot/WhiteBox.java	Tue Nov 26 10:22:13 2019 +0000
+++ b/test/lib/sun/hotspot/WhiteBox.java	Fri Nov 29 10:02:07 2019 +0000
@@ -222,6 +222,9 @@
   public native long NMTMallocWithPseudoStackAndType(long size, int index, int type);
   public native boolean NMTChangeTrackingLevel();
   public native int NMTGetHashSize();
+  public native long NMTNewArena(long initSize);
+  public native void NMTFreeArena(long arena);
+  public native void NMTArenaMalloc(long arena, long size);
 
   // Compiler
   public native int     matchesMethod(Executable method, String pattern);