Merge JDK-8200758-branch
authorherrick
Fri, 19 Apr 2019 08:00:42 -0400
branchJDK-8200758-branch
changeset 57332 4649818834e0
parent 57331 221a589c52ee (current diff)
parent 54580 79e95d8dd85d (diff)
child 57333 77109ab87402
Merge
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
test/hotspot/jtreg/runtime/ErrorHandling/ExplicitArithmeticCheck.java
test/hotspot/jtreg/runtime/Thread/MonitorCacheMaybeExpand_DeadLock.java
test/hotspot/jtreg/runtime/interpreter/WideStrictInline.java
--- a/.hgtags	Fri Apr 19 07:55:28 2019 -0400
+++ b/.hgtags	Fri Apr 19 08:00:42 2019 -0400
@@ -554,3 +554,4 @@
 46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14
 f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15
 9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16
+93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17
--- a/doc/testing.html	Fri Apr 19 07:55:28 2019 -0400
+++ b/doc/testing.html	Fri Apr 19 08:00:42 2019 -0400
@@ -41,6 +41,7 @@
 </ul></li>
 <li><a href="#notes-for-specific-tests">Notes for Specific Tests</a><ul>
 <li><a href="#docker-tests">Docker Tests</a></li>
+<li><a href="#non-us-locale">Non-US locale</a></li>
 </ul></li>
 </ul>
 </nav>
@@ -194,5 +195,9 @@
 <pre><code>$ make test TEST=&quot;jtreg:test/hotspot/jtreg/containers/docker&quot;</code></pre>
 <p>To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using <code>JAVA_OPTIONS</code>.</p>
 <pre><code>$ make test TEST=&quot;jtreg:test/hotspot/jtreg/containers/docker&quot; JTREG=&quot;JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest&quot;</code></pre>
+<h3 id="non-us-locale">Non-US locale</h3>
+<p>If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting <code>LANG=&quot;en_US&quot;</code> in the environment before running tests should work. On Windows, setting <code>JTREG=&quot;VM_OPTIONS=-Duser.language=en -Duser.country=US&quot;</code> helps for most, but not all test cases. For example:</p>
+<pre><code>$ export LANG=&quot;en_US&quot; &amp;&amp; make test TEST=...
+$ make test JTREG=&quot;VM_OPTIONS=-Duser.language=en -Duser.country=US&quot; TEST=...</code></pre>
 </body>
 </html>
--- a/doc/testing.md	Fri Apr 19 07:55:28 2019 -0400
+++ b/doc/testing.md	Fri Apr 19 08:00:42 2019 -0400
@@ -388,6 +388,17 @@
 
     $ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
 
+### Non-US locale
+
+If your locale is non-US, some tests are likely to fail. To work around this you can
+set the locale to US. On Unix platforms simply setting `LANG="en_US"` in the
+environment before running tests should work. On Windows, setting
+`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but not all test cases.
+For example:
+
+    $ export LANG="en_US" && make test TEST=...
+    $ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...
+
 ---
 # Override some definitions in the global css file that are not optimal for
 # this document.
--- a/make/autoconf/jdk-version.m4	Fri Apr 19 07:55:28 2019 -0400
+++ b/make/autoconf/jdk-version.m4	Fri Apr 19 08:00:42 2019 -0400
@@ -66,7 +66,33 @@
   AC_SUBST(PRODUCT_SUFFIX)
   AC_SUBST(JDK_RC_PLATFORM_NAME)
   AC_SUBST(HOTSPOT_VM_DISTRO)
+
+  # Set the MACOSX Bundle Name base
+  AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base],
+      [Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.
+      @<:@not specified@:>@])])
+  if test "x$with_macosx_bundle_name_base" = xyes; then
+    AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value])
+  elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then
+    AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base])
+  elif test "x$with_macosx_bundle_name_base" != x; then
+    # Set MACOSX_BUNDLE_NAME_BASE to the configured value.
+    MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base"
+  fi
   AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
+
+  # Set the MACOSX Bundle ID base
+  AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base],
+      [Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.
+      @<:@not specified@:>@])])
+  if test "x$with_macosx_bundle_id_base" = xyes; then
+    AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value])
+  elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then
+    AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base])
+  elif test "x$with_macosx_bundle_id_base" != x; then
+    # Set MACOSX_BUNDLE_ID_BASE to the configured value.
+    MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base"
+  fi
   AC_SUBST(MACOSX_BUNDLE_ID_BASE)
 
   # Set the JDK RC name
--- a/make/autoconf/libraries.m4	Fri Apr 19 07:55:28 2019 -0400
+++ b/make/autoconf/libraries.m4	Fri Apr 19 08:00:42 2019 -0400
@@ -130,6 +130,11 @@
     BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread"
   fi
 
+  # perfstat lib
+  if test "x$OPENJDK_TARGET_OS" = xaix; then
+    BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat"
+  fi
+
   if test "x$OPENJDK_TARGET_OS" = xsolaris; then
     BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -ldemangle -lnsl \
         -lrt -lkstat"
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,13 +67,24 @@
               .forEach(System.out::println);
 
         // Common concatenation patterns
-        String const_I = "string" + args.length;
-        String const_S = "string" + String.valueOf(args.length);
-        String S_const = String.valueOf(args.length) + "string";
-        String S_S     = String.valueOf(args.length) + String.valueOf(args.length);
-        String const_J = "string" + System.currentTimeMillis();
-        String I_const = args.length + "string";
-        String J_const = System.currentTimeMillis() + "string";
+        String SS     = String.valueOf(args.length) + String.valueOf(args.length);
+        String CS     = "string" + String.valueOf(args.length);
+        String SC     = String.valueOf(args.length) + "string";
+        String SCS    = String.valueOf(args.length) + "string" + String.valueOf(args.length);
+        String CSS    = "string" + String.valueOf(args.length) + String.valueOf(args.length);
+        String CSCS   = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
+        String SCSC   = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
+        String CSCSC  = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
+        String SCSCS  = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
+        String CI     = "string" + args.length;
+        String IC     = args.length + "string";
+        String CIC    = "string" + args.length + "string";
+        String CICI   = "string" + args.length + "string" + args.length;
+        String CJ     = "string" + System.currentTimeMillis();
+        String JC     = System.currentTimeMillis() + "string";
+        String CJC    = "string" + System.currentTimeMillis() + "string";
+        String CJCJ   = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis();
+        String CJCJC  = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis() + "string";
 
         String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
                 LocalDateTime.now(ZoneId.of("GMT")));
--- a/make/launcher/Launcher-java.base.gmk	Fri Apr 19 07:55:28 2019 -0400
+++ b/make/launcher/Launcher-java.base.gmk	Fri Apr 19 08:00:42 2019 -0400
@@ -39,7 +39,6 @@
 # overwritten.
 $(eval $(call SetupBuildLauncher, java, \
     CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \
-    LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \
     EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \
     VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \
     OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \
--- a/make/launcher/LauncherCommon.gmk	Fri Apr 19 07:55:28 2019 -0400
+++ b/make/launcher/LauncherCommon.gmk	Fri Apr 19 08:00:42 2019 -0400
@@ -73,8 +73,7 @@
 #     compile time defines exceeding Visual Studio 2013 limitations.
 # CFLAGS   Additional CFLAGS
 # CFLAGS_windows   Additional CFLAGS_windows
-# LDFLAGS_solaris Additional LDFLAGS_solaris
-# RC_FLAGS   Additional RC_FLAGS
+# EXTRA_RC_FLAGS   Additional EXTRA_RC_FLAGS
 # MACOSX_SIGNED   On macosx, sign this binary
 # OPTIMIZATION   Override default optimization level (LOW)
 # OUTPUT_DIR   Override default output directory
@@ -139,7 +138,7 @@
       NAME := $1, \
       EXTRA_FILES := $(LAUNCHER_SRC)/main.c, \
       OPTIMIZATION := $$($1_OPTIMIZATION), \
-      CFLAGS := $$(CFLAGS_JDKEXE) $$($1_CFLAGS) \
+      CFLAGS := $$(CFLAGS_JDKEXE) \
           $(LAUNCHER_CFLAGS) \
           $(VERSION_CFLAGS) \
           -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -38,6 +38,9 @@
 #include "vm_version_ppc.hpp"
 
 #include <sys/sysinfo.h>
+#if defined(_AIX)
+#include <libperfstat.h>
+#endif
 
 #if defined(LINUX) && defined(VM_LITTLE_ENDIAN)
 #include <sys/auxv.h>
@@ -382,6 +385,58 @@
 }
 
 void VM_Version::print_platform_virtualization_info(outputStream* st) {
+#if defined(_AIX)
+  // more info about perfstat API see
+  // https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.prftools/idprftools_perfstat_glob_partition.htm
+  int rc = 0;
+  perfstat_partition_total_t pinfo;
+  memset(&pinfo, 0, sizeof(perfstat_partition_total_t));
+  rc = perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1);
+  if (rc != 1) {
+    return;
+  } else {
+    st->print_cr("Virtualization type   : PowerVM");
+  }
+  // CPU information
+  perfstat_cpu_total_t cpuinfo;
+  memset(&cpuinfo, 0, sizeof(perfstat_cpu_total_t));
+  rc = perfstat_cpu_total(NULL, &cpuinfo, sizeof(perfstat_cpu_total_t), 1);
+  if (rc != 1) {
+    return;
+  }
+
+  st->print_cr("Processor description : %s", cpuinfo.description);
+  st->print_cr("Processor speed       : %llu Hz", cpuinfo.processorHZ);
+
+  st->print_cr("LPAR partition name           : %s", pinfo.name);
+  st->print_cr("LPAR partition number         : %u", pinfo.lpar_id);
+  st->print_cr("LPAR partition type           : %s", pinfo.type.b.shared_enabled ? "shared" : "dedicated");
+  st->print_cr("LPAR mode                     : %s", pinfo.type.b.donate_enabled ? "donating" : pinfo.type.b.capped ? "capped" : "uncapped");
+  st->print_cr("LPAR partition group ID       : %u", pinfo.group_id);
+  st->print_cr("LPAR shared pool ID           : %u", pinfo.pool_id);
+
+  st->print_cr("AMS (active memory sharing)   : %s", pinfo.type.b.ams_capable ? "capable" : "not capable");
+  st->print_cr("AMS (active memory sharing)   : %s", pinfo.type.b.ams_enabled ? "on" : "off");
+  st->print_cr("AME (active memory expansion) : %s", pinfo.type.b.ame_enabled ? "on" : "off");
+
+  if (pinfo.type.b.ame_enabled) {
+    st->print_cr("AME true memory in bytes      : %llu", pinfo.true_memory);
+    st->print_cr("AME expanded memory in bytes  : %llu", pinfo.expanded_memory);
+  }
+
+  st->print_cr("SMT : %s", pinfo.type.b.smt_capable ? "capable" : "not capable");
+  st->print_cr("SMT : %s", pinfo.type.b.smt_enabled ? "on" : "off");
+  int ocpus = pinfo.online_cpus > 0 ?  pinfo.online_cpus : 1;
+  st->print_cr("LPAR threads              : %d", cpuinfo.ncpus/ocpus);
+  st->print_cr("LPAR online virtual cpus  : %d", pinfo.online_cpus);
+  st->print_cr("LPAR logical cpus         : %d", cpuinfo.ncpus);
+  st->print_cr("LPAR maximum virtual cpus : %u", pinfo.max_cpus);
+  st->print_cr("LPAR minimum virtual cpus : %u", pinfo.min_cpus);
+  st->print_cr("LPAR entitled capacity    : %4.2f", (double) (pinfo.entitled_proc_capacity/100.0));
+  st->print_cr("LPAR online memory        : %llu MB", pinfo.online_memory);
+  st->print_cr("LPAR maximum memory       : %llu MB", pinfo.max_memory);
+  st->print_cr("LPAR minimum memory       : %llu MB", pinfo.min_memory);
+#else
   const char* info_file = "/proc/ppc64/lparcfg";
   const char* kw[] = { "system_type=", // qemu indicates PowerKVM
                        "partition_entitled_capacity=", // entitled processor capacity percentage
@@ -400,6 +455,7 @@
   if (!print_matching_lines_from_file(info_file, st, kw)) {
     st->print_cr("  <%s Not Available>", info_file);
   }
+#endif
 }
 
 bool VM_Version::use_biased_locking() {
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -4355,12 +4355,9 @@
 // Emitter does not KILL cnt and base arguments, since they need to be copied to
 // work registers anyway.
 // Actually, only r0, r1, and r5 are killed.
-unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len) {
-  // Src_addr is evenReg.
-  // Src_len is odd_Reg.
+unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg) {
 
   int      block_start = offset();
-  Register tmp_reg  = src_len; // Holds target instr addr for EX.
   Register dst_len  = Z_R1;    // Holds dst len  for MVCLE.
   Register dst_addr = Z_R0;    // Holds dst addr for MVCLE.
 
@@ -4369,7 +4366,7 @@
   BLOCK_COMMENT("Clear_Array {");
 
   // Check for zero len and convert to long.
-  z_ltgfr(src_len, cnt_arg);      // Remember casted value for doSTG case.
+  z_ltgfr(odd_tmp_reg, cnt_arg);
   z_bre(done);                    // Nothing to do if len == 0.
 
   // Prefetch data to be cleared.
@@ -4378,16 +4375,17 @@
     z_pfd(0x02, 256, Z_R0, base_pointer_arg);
   }
 
-  z_sllg(dst_len, src_len, 3);    // #bytes to clear.
-  z_cghi(src_len, 32);            // Check for len <= 256 bytes (<=32 DW).
-  z_brnh(doXC);                   // If so, use executed XC to clear.
+  z_sllg(dst_len, odd_tmp_reg, 3); // #bytes to clear.
+  z_cghi(odd_tmp_reg, 32);         // Check for len <= 256 bytes (<=32 DW).
+  z_brnh(doXC);                    // If so, use executed XC to clear.
 
   // MVCLE: initialize long arrays (general case).
   bind(doMVCLE);
   z_lgr(dst_addr, base_pointer_arg);
-  clear_reg(src_len, true, false); // Src len of MVCLE is zero.
-
-  MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
+  // Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
+  // The even register of the register pair is not killed.
+  clear_reg(odd_tmp_reg, true, false);
+  MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding()-1), 0);
   z_bru(done);
 
   // XC: initialize short arrays.
@@ -4396,12 +4394,12 @@
     z_xc(0,0,base_pointer_arg,0,base_pointer_arg);
 
   bind(doXC);
-    add2reg(dst_len, -1);             // Get #bytes-1 for EXECUTE.
+    add2reg(dst_len, -1);               // Get #bytes-1 for EXECUTE.
     if (VM_Version::has_ExecuteExtensions()) {
-      z_exrl(dst_len, XC_template);   // Execute XC with var. len.
+      z_exrl(dst_len, XC_template);     // Execute XC with var. len.
     } else {
-      z_larl(tmp_reg, XC_template);
-      z_ex(dst_len,0,Z_R0,tmp_reg);   // Execute XC with var. len.
+      z_larl(odd_tmp_reg, XC_template);
+      z_ex(dst_len,0,Z_R0,odd_tmp_reg); // Execute XC with var. len.
     }
     // z_bru(done);      // fallthru
 
@@ -4463,7 +4461,7 @@
 // Compiler ensures base is doubleword aligned and cnt is #doublewords.
 // Emitter does not KILL cnt and base arguments, since they need to be copied to
 // work registers anyway.
-// Actually, only r0, r1, r4, and r5 (which are work registers) are killed.
+// Actually, only r0, r1, (which are work registers) and odd_tmp_reg are killed.
 //
 // For very large arrays, exploit MVCLE H/W support.
 // MVCLE instruction automatically exploits H/W-optimized page mover.
@@ -4471,9 +4469,7 @@
 // - All full pages are cleared with the page mover H/W assist.
 // - Remaining bytes are again cleared by a series of XC to self.
 //
-unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len) {
-  // Src_addr is evenReg.
-  // Src_len is odd_Reg.
+unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg) {
 
   int      block_start = offset();
   Register dst_len  = Z_R1;      // Holds dst len  for MVCLE.
@@ -4486,11 +4482,10 @@
 
   // Prepare other args to MVCLE.
   z_lgr(dst_addr, base_pointer_arg);
-  // Indicate unused result.
-  (void) clear_reg(src_len, true, false);  // Src len of MVCLE is zero.
-
-  // Clear.
-  MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
+  // Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
+  // The even register of the register pair is not killed.
+  (void) clear_reg(odd_tmp_reg, true, false);  // Src len of MVCLE is zero.
+  MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding() - 1), 0);
   BLOCK_COMMENT("} Clear_Array_Const_Big");
 
   int block_end = offset();
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -828,9 +828,9 @@
   //--------------------------
   //---  Operations on arrays.
   //--------------------------
-  unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len);
+  unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg);
   unsigned int Clear_Array_Const(long cnt, Register base);
-  unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len);
+  unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg);
   unsigned int CopyRawMemory_AlignedDisjoint(Register src_reg, Register dst_reg,
                                              Register cnt_reg,
                                              Register tmp1_reg, Register tmp2_reg);
--- a/src/hotspot/cpu/s390/s390.ad	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/s390.ad	Fri Apr 19 08:00:42 2019 -0400
@@ -474,6 +474,19 @@
 /*Z_R15_H,Z_R15*/   // SP
 );
 
+// z_long_reg without even registers
+reg_class z_long_odd_reg(
+/*Z_R0_H,Z_R0*/     // R0
+/*Z_R1_H,Z_R1*/
+  Z_R3_H,Z_R3,
+  Z_R5_H,Z_R5,
+  Z_R7_H,Z_R7,
+  Z_R9_H,Z_R9,
+  Z_R11_H,Z_R11,
+  Z_R13_H,Z_R13
+/*Z_R14_H,Z_R14,*/  // return_pc
+/*Z_R15_H,Z_R15*/   // SP
+);
 
 // Special Class for Condition Code Flags Register
 
@@ -3378,6 +3391,7 @@
   match(RegL);
   match(revenRegL);
   match(roddRegL);
+  match(allRoddRegL);
   match(rarg1RegL);
   match(rarg5RegL);
   format %{ %}
@@ -3400,6 +3414,14 @@
   interface(REG_INTER);
 %}
 
+// available odd registers for iRegL
+operand allRoddRegL() %{
+  constraint(ALLOC_IN_RC(z_long_odd_reg));
+  match(iRegL);
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 operand rarg1RegL() %{
   constraint(ALLOC_IN_RC(z_rarg1_long_reg));
   match(iRegL);
@@ -9899,23 +9921,23 @@
   ins_pipe(pipe_class_dummy);
 %}
 
-instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
+instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
   match(Set dummy (ClearArray cnt base));
-  effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
+  effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
   ins_cost(200);
   // TODO: s390 port size(VARIABLE_SIZE);       // Variable in size due to optimized constant loader.
   format %{ "ClearArrayConstBig $cnt,$base" %}
-  ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $srcA$$Register, $srcL$$Register); %}
-  ins_pipe(pipe_class_dummy);
-%}
-
-instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
+  ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $tmpL$$Register); %}
+  ins_pipe(pipe_class_dummy);
+%}
+
+instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
   match(Set dummy (ClearArray cnt base));
-  effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
+  effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
   ins_cost(300);
   // TODO: s390 port size(FIXED_SIZE);  // z/Architecture: emitted code depends on PreferLAoverADD being on/off.
   format %{ "ClearArrayVar $cnt,$base" %}
-  ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $srcA$$Register, $srcL$$Register); %}
+  ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $tmpL$$Register); %}
   ins_pipe(pipe_class_dummy);
 %}
 
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -2968,9 +2968,8 @@
 
     __ enter();
     __ subptr(rsp, 8 * wordSize);
-    if (multi_block) {
-      __ push(limit);
-    }
+    handleSOERegisters(true /*saving*/);
+
     __ movptr(buf, buf_param);
     __ movptr(state, state_param);
     if (multi_block) {
@@ -2981,9 +2980,7 @@
     __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask,
       buf, state, ofs, limit, rsp, multi_block);
 
-    if (multi_block) {
-      __ pop(limit);
-    }
+    handleSOERegisters(false /*restoring*/);
     __ addptr(rsp, 8 * wordSize);
     __ leave();
     __ ret(0);
--- a/src/hotspot/os/aix/os_aix.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/aix/os_aix.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -1405,13 +1405,7 @@
     st->print_cr("type: %s", (wi.app_wpar ? "application" : "system"));
   }
 
-  // print partition info
-  libperfstat::partitioninfo_t pi;
-  if (libperfstat::get_partitioninfo(&pi)) {
-    st->print_cr("partition info");
-    st->print_cr(" name: %s", pi.name);
-  }
-
+  VM_Version::print_platform_virtualization_info(st);
 }
 
 void os::print_memory_info(outputStream* st) {
--- a/src/hotspot/os/linux/osContainer_linux.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/linux/osContainer_linux.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -122,7 +122,25 @@
     char *subsystem_path() { return _path; }
 };
 
-CgroupSubsystem* memory = NULL;
+class CgroupMemorySubsystem: CgroupSubsystem {
+ friend class OSContainer;
+
+ private:
+    /* Some container runtimes set limits via cgroup
+     * hierarchy. If set to true consider also memory.stat
+     * file if everything else seems unlimited */
+    bool _uses_mem_hierarchy;
+
+ public:
+    CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
+      _uses_mem_hierarchy = false;
+    }
+
+    bool is_hierarchical() { return _uses_mem_hierarchy; }
+    void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
+};
+
+CgroupMemorySubsystem* memory = NULL;
 CgroupSubsystem* cpuset = NULL;
 CgroupSubsystem* cpu = NULL;
 CgroupSubsystem* cpuacct = NULL;
@@ -131,21 +149,24 @@
 
 PRAGMA_DIAG_PUSH
 PRAGMA_FORMAT_NONLITERAL_IGNORED
-template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
+template <typename T> int subsystem_file_line_contents(CgroupSubsystem* c,
                                               const char *filename,
+                                              const char *matchline,
                                               const char *scan_fmt,
                                               T returnval) {
   FILE *fp = NULL;
   char *p;
   char file[MAXPATHLEN+1];
   char buf[MAXPATHLEN+1];
+  char discard[MAXPATHLEN+1];
+  bool found_match = false;
 
   if (c == NULL) {
-    log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL");
+    log_debug(os, container)("subsystem_file_line_contents: CgroupSubsytem* is NULL");
     return OSCONTAINER_ERROR;
   }
   if (c->subsystem_path() == NULL) {
-    log_debug(os, container)("subsystem_file_contents: subsystem path is NULL");
+    log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL");
     return OSCONTAINER_ERROR;
   }
 
@@ -160,16 +181,32 @@
   log_trace(os, container)("Path to %s is %s", filename, file);
   fp = fopen(file, "r");
   if (fp != NULL) {
-    p = fgets(buf, MAXPATHLEN, fp);
-    if (p != NULL) {
-      int matched = sscanf(p, scan_fmt, returnval);
-      if (matched == 1) {
+    int err = 0;
+    while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) {
+      found_match = false;
+      if (matchline == NULL) {
+        // single-line file case
+        int matched = sscanf(p, scan_fmt, returnval);
+        found_match = (matched == 1);
+      } else {
+        // multi-line file case
+        if (strstr(p, matchline) != NULL) {
+          // discard matchline string prefix
+          int matched = sscanf(p, scan_fmt, discard, returnval);
+          found_match = (matched == 2);
+        } else {
+          continue; // substring not found
+        }
+      }
+      if (found_match) {
         fclose(fp);
         return 0;
       } else {
+        err = 1;
         log_debug(os, container)("Type %s not found in file %s", scan_fmt, file);
       }
-    } else {
+    }
+    if (err == 0) {
       log_debug(os, container)("Empty file %s", file);
     }
   } else {
@@ -186,10 +223,11 @@
   return_type variable;                                                   \
 {                                                                         \
   int err;                                                                \
-  err = subsystem_file_contents(subsystem,                                \
-                                filename,                                 \
-                                scan_fmt,                                 \
-                                &variable);                               \
+  err = subsystem_file_line_contents(subsystem,                           \
+                                     filename,                            \
+                                     NULL,                                \
+                                     scan_fmt,                            \
+                                     &variable);                          \
   if (err != 0)                                                           \
     return (return_type) OSCONTAINER_ERROR;                               \
                                                                           \
@@ -201,16 +239,33 @@
   char variable[bufsize];                                                 \
 {                                                                         \
   int err;                                                                \
-  err = subsystem_file_contents(subsystem,                                \
-                                filename,                                 \
-                                scan_fmt,                                 \
-                                variable);                                \
+  err = subsystem_file_line_contents(subsystem,                           \
+                                     filename,                            \
+                                     NULL,                                \
+                                     scan_fmt,                            \
+                                     variable);                           \
   if (err != 0)                                                           \
     return (return_type) NULL;                                            \
                                                                           \
   log_trace(os, container)(logstring, variable);                          \
 }
 
+#define GET_CONTAINER_INFO_LINE(return_type, subsystem, filename,         \
+                           matchline, logstring, scan_fmt, variable)      \
+  return_type variable;                                                   \
+{                                                                         \
+  int err;                                                                \
+  err = subsystem_file_line_contents(subsystem,                           \
+                                filename,                                 \
+                                matchline,                                \
+                                scan_fmt,                                 \
+                                &variable);                               \
+  if (err != 0)                                                           \
+    return (return_type) OSCONTAINER_ERROR;                               \
+                                                                          \
+  log_trace(os, container)(logstring, variable);                          \
+}
+
 /* init
  *
  * Initialize the container support and determine if
@@ -266,7 +321,7 @@
     }
     while ((token = strsep(&cptr, ",")) != NULL) {
       if (strcmp(token, "memory") == 0) {
-        memory = new CgroupSubsystem(tmproot, tmpmount);
+        memory = new CgroupMemorySubsystem(tmproot, tmpmount);
       } else if (strcmp(token, "cpuset") == 0) {
         cpuset = new CgroupSubsystem(tmproot, tmpmount);
       } else if (strcmp(token, "cpu") == 0) {
@@ -344,6 +399,10 @@
     while ((token = strsep(&controllers, ",")) != NULL) {
       if (strcmp(token, "memory") == 0) {
         memory->set_subsystem_path(base);
+        jlong hierarchy = uses_mem_hierarchy();
+        if (hierarchy > 0) {
+          memory->set_hierarchical(true);
+        }
       } else if (strcmp(token, "cpuset") == 0) {
         cpuset->set_subsystem_path(base);
       } else if (strcmp(token, "cpu") == 0) {
@@ -360,6 +419,7 @@
   // command line arguments have been processed.
   if ((mem_limit = memory_limit_in_bytes()) > 0) {
     os::Linux::set_physical_memory(mem_limit);
+    log_info(os, container)("Memory Limit is: " JLONG_FORMAT, mem_limit);
   }
 
   _is_containerized = true;
@@ -374,6 +434,21 @@
   }
 }
 
+/* uses_mem_hierarchy
+ *
+ * Return whether or not hierarchical cgroup accounting is being
+ * done.
+ *
+ * return:
+ *    A number > 0 if true, or
+ *    OSCONTAINER_ERROR for not supported
+ */
+jlong OSContainer::uses_mem_hierarchy() {
+  GET_CONTAINER_INFO(jlong, memory, "/memory.use_hierarchy",
+                    "Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
+  return use_hierarchy;
+}
+
 
 /* memory_limit_in_bytes
  *
@@ -389,7 +464,18 @@
                      "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
 
   if (memlimit >= _unlimited_memory) {
-    log_trace(os, container)("Memory Limit is: Unlimited");
+    log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");
+    if (memory->is_hierarchical()) {
+      const char* matchline = "hierarchical_memory_limit";
+      char* format = "%s " JULONG_FORMAT;
+      GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
+                             "Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit)
+      if (hier_memlimit >= _unlimited_memory) {
+        log_trace(os, container)("Hierarchical Memory Limit is: Unlimited");
+      } else {
+        return (jlong)hier_memlimit;
+      }
+    }
     return (jlong)-1;
   }
   else {
@@ -401,7 +487,18 @@
   GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
                      "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
   if (memswlimit >= _unlimited_memory) {
-    log_trace(os, container)("Memory and Swap Limit is: Unlimited");
+    log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");
+    if (memory->is_hierarchical()) {
+      const char* matchline = "hierarchical_memsw_limit";
+      char* format = "%s " JULONG_FORMAT;
+      GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
+                             "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit)
+      if (hier_memlimit >= _unlimited_memory) {
+        log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");
+      } else {
+        return (jlong)hier_memlimit;
+      }
+    }
     return (jlong)-1;
   } else {
     return (jlong)memswlimit;
--- a/src/hotspot/os/linux/osContainer_linux.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/linux/osContainer_linux.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -42,6 +42,7 @@
   static inline bool is_containerized();
   static const char * container_type();
 
+  static jlong uses_mem_hierarchy();
   static jlong memory_limit_in_bytes();
   static jlong memory_and_swap_limit_in_bytes();
   static jlong memory_soft_limit_in_bytes();
--- a/src/hotspot/os/windows/os_windows.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -5000,17 +5000,13 @@
                           char *addr, size_t bytes, bool read_only,
                           bool allow_exec) {
   // This OS does not allow existing memory maps to be remapped so we
-  // have to unmap the memory before we remap it.
-  if (!os::unmap_memory(addr, bytes)) {
-    return NULL;
-  }
-
-  // There is a very small theoretical window between the unmap_memory()
-  // call above and the map_memory() call below where a thread in native
-  // code may be able to access an address that is no longer mapped.
-
-  return os::map_memory(fd, file_name, file_offset, addr, bytes,
-                        read_only, allow_exec);
+  // would have to unmap the memory before we remap it.
+
+  // Because there is a small window between unmapping memory and mapping
+  // it in again with different protections, CDS archives are mapped RW
+  // on windows, so this function isn't called.
+  ShouldNotReachHere();
+  return NULL;
 }
 
 
--- a/src/hotspot/share/adlc/formssel.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/adlc/formssel.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -774,10 +774,16 @@
        !strcmp(_matrule->_rChild->_opType,"CheckCastPP")  ||
        !strcmp(_matrule->_rChild->_opType,"GetAndSetP")   ||
        !strcmp(_matrule->_rChild->_opType,"GetAndSetN")   ||
+#if INCLUDE_ZGC
+       !strcmp(_matrule->_rChild->_opType,"LoadBarrierSlowReg") ||
+       !strcmp(_matrule->_rChild->_opType,"LoadBarrierWeakSlowReg") ||
+#endif
+#if INCLUDE_SHENANDOAHGC
+       !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
+       !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
+#endif
        !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
-       !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN") ||
-       !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
-       !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN"))) return true;
+       !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true;
   else if ( is_ideal_load() == Form::idealP )                return true;
   else if ( is_ideal_store() != Form::none  )                return true;
 
--- a/src/hotspot/share/classfile/classFileParser.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -5975,9 +5975,9 @@
   _minor_version = stream->get_u2_fast();
   _major_version = stream->get_u2_fast();
 
-  if (DumpSharedSpaces && _major_version < JAVA_1_5_VERSION) {
+  if (DumpSharedSpaces && _major_version < JAVA_6_VERSION) {
     ResourceMark rm;
-    warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s",
+    warning("Pre JDK 6 class not supported by CDS: %u.%u %s",
             _major_version,  _minor_version, _class_name->as_C_string());
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
--- a/src/hotspot/share/classfile/javaClasses.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -1714,20 +1714,13 @@
 
 
 jlong java_lang_Thread::stackSize(oop java_thread) {
-  if (_stackSize_offset > 0) {
-    return java_thread->long_field(_stackSize_offset);
-  } else {
-    return 0;
-  }
+  return java_thread->long_field(_stackSize_offset);
 }
 
 // Write the thread status value to threadStatus field in java.lang.Thread java class.
 void java_lang_Thread::set_thread_status(oop java_thread,
                                          java_lang_Thread::ThreadStatus status) {
-  // The threadStatus is only present starting in 1.5
-  if (_thread_status_offset > 0) {
-    java_thread->int_field_put(_thread_status_offset, status);
-  }
+  java_thread->int_field_put(_thread_status_offset, status);
 }
 
 // Read thread status value from threadStatus field in java.lang.Thread java class.
@@ -1737,62 +1730,31 @@
   assert(Threads_lock->owned_by_self() || Thread::current()->is_VM_thread() ||
          JavaThread::current()->thread_state() == _thread_in_vm,
          "Java Thread is not running in vm");
-  // The threadStatus is only present starting in 1.5
-  if (_thread_status_offset > 0) {
-    return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
-  } else {
-    // All we can easily figure out is if it is alive, but that is
-    // enough info for a valid unknown status.
-    // These aren't restricted to valid set ThreadStatus values, so
-    // use JVMTI values and cast.
-    JavaThread* thr = java_lang_Thread::thread(java_thread);
-    if (thr == NULL) {
-      // the thread hasn't run yet or is in the process of exiting
-      return NEW;
-    }
-    return (java_lang_Thread::ThreadStatus)JVMTI_THREAD_STATE_ALIVE;
-  }
+  return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
 }
 
 
 jlong java_lang_Thread::thread_id(oop java_thread) {
-  // The thread ID field is only present starting in 1.5
-  if (_tid_offset > 0) {
-    return java_thread->long_field(_tid_offset);
-  } else {
-    return 0;
-  }
+  return java_thread->long_field(_tid_offset);
 }
 
 oop java_lang_Thread::park_blocker(oop java_thread) {
-  assert(JDK_Version::current().supports_thread_park_blocker() &&
-         _park_blocker_offset != 0, "Must support parkBlocker field");
-
-  if (_park_blocker_offset > 0) {
-    return java_thread->obj_field(_park_blocker_offset);
-  }
-
-  return NULL;
+  assert(JDK_Version::current().supports_thread_park_blocker(),
+         "Must support parkBlocker field");
+
+  return java_thread->obj_field(_park_blocker_offset);
 }
 
 jlong java_lang_Thread::park_event(oop java_thread) {
-  if (_park_event_offset > 0) {
-    return java_thread->long_field(_park_event_offset);
-  }
-  return 0;
+  return java_thread->long_field(_park_event_offset);
 }
 
 bool java_lang_Thread::set_park_event(oop java_thread, jlong ptr) {
-  if (_park_event_offset > 0) {
-    java_thread->long_field_put(_park_event_offset, ptr);
-    return true;
-  }
-  return false;
-}
-
+  java_thread->long_field_put(_park_event_offset, ptr);
+  return true;
+}
 
 const char* java_lang_Thread::thread_status_name(oop java_thread) {
-  assert(_thread_status_offset != 0, "Must have thread status");
   ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
   switch (status) {
     case NEW                      : return "NEW";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -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.
+ *
+ */
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
+
+#include "memory/iterator.hpp"
+
+class ShenandoahHeap;
+class ShenandoahMarkingContext;
+class Thread;
+
+class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
+private:
+  ShenandoahMarkingContext* const _mark_context;
+public:
+  inline ShenandoahForwardedIsAliveClosure();
+  inline bool do_object_b(oop obj);
+};
+
+class ShenandoahIsAliveClosure: public BoolObjectClosure {
+private:
+  ShenandoahMarkingContext* const _mark_context;
+public:
+  inline ShenandoahIsAliveClosure();
+  inline bool do_object_b(oop obj);
+};
+
+class ShenandoahIsAliveSelector : public StackObj {
+private:
+  ShenandoahIsAliveClosure _alive_cl;
+  ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
+public:
+  inline BoolObjectClosure* is_alive_closure();
+};
+
+class ShenandoahUpdateRefsClosure: public OopClosure {
+private:
+  ShenandoahHeap* _heap;
+public:
+  inline ShenandoahUpdateRefsClosure();
+  inline void do_oop(oop* p);
+  inline void do_oop(narrowOop* p);
+private:
+  template <class T>
+  inline void do_oop_work(T* p);
+};
+
+class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
+private:
+  ShenandoahHeap* _heap;
+  Thread* _thread;
+public:
+  inline ShenandoahEvacuateUpdateRootsClosure();
+  inline void do_oop(oop* p);
+  inline void do_oop(narrowOop* p);
+
+private:
+  template <class T>
+  inline void do_oop_work(T* p);
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,110 @@
+/*
+ * 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_SHENANDOAHCLOSURES_INLINE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
+
+#include "gc/shenandoah/shenandoahAsserts.hpp"
+#include "gc/shenandoah/shenandoahClosures.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "oops/compressedOops.inline.hpp"
+#include "runtime/thread.hpp"
+
+ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
+  _mark_context(ShenandoahHeap::heap()->marking_context()) {
+}
+
+bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
+  if (CompressedOops::is_null(obj)) {
+    return false;
+  }
+  obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+  shenandoah_assert_not_forwarded_if(NULL, obj,
+                                     (ShenandoahHeap::heap()->is_concurrent_mark_in_progress() ||
+                                     ShenandoahHeap::heap()->is_concurrent_traversal_in_progress()));
+  return _mark_context->is_marked(obj);
+}
+
+ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
+  _mark_context(ShenandoahHeap::heap()->marking_context()) {
+}
+
+bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
+  if (CompressedOops::is_null(obj)) {
+    return false;
+  }
+  shenandoah_assert_not_forwarded(NULL, obj);
+  return _mark_context->is_marked(obj);
+}
+
+BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
+  return ShenandoahHeap::heap()->has_forwarded_objects() ?
+         reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl) :
+         reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
+}
+
+ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() :
+  _heap(ShenandoahHeap::heap()) {
+}
+
+template <class T>
+void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
+  T o = RawAccess<>::oop_load(p);
+  if (!CompressedOops::is_null(o)) {
+    oop obj = CompressedOops::decode_not_null(o);
+    _heap->update_with_forwarded_not_null(p, obj);
+  }
+}
+
+void ShenandoahUpdateRefsClosure::do_oop(oop* p)       { do_oop_work(p); }
+void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
+
+ShenandoahEvacuateUpdateRootsClosure::ShenandoahEvacuateUpdateRootsClosure() :
+  _heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
+}
+
+template <class T>
+void ShenandoahEvacuateUpdateRootsClosure::do_oop_work(T* p) {
+  assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
+
+  T o = RawAccess<>::oop_load(p);
+  if (! CompressedOops::is_null(o)) {
+    oop obj = CompressedOops::decode_not_null(o);
+    if (_heap->in_collection_set(obj)) {
+      shenandoah_assert_marked(p, obj);
+      oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+      if (oopDesc::equals_raw(resolved, obj)) {
+        resolved = _heap->evacuate_object(obj, _thread);
+      }
+      RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
+    }
+  }
+}
+void ShenandoahEvacuateUpdateRootsClosure::do_oop(oop* p) {
+  do_oop_work(p);
+}
+
+void ShenandoahEvacuateUpdateRootsClosure::do_oop(narrowOop* p) {
+  do_oop_work(p);
+}
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -33,6 +33,7 @@
 #include "gc/shared/referenceProcessorPhaseTimes.hpp"
 
 #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
 #include "gc/shenandoah/shenandoahMarkCompact.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -33,6 +33,7 @@
 #include "gc/shenandoah/shenandoahAllocTracker.hpp"
 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
 #include "gc/shenandoah/shenandoahBrooksPointer.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
 #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
@@ -70,8 +71,6 @@
 #include "runtime/vmThread.hpp"
 #include "services/mallocTracker.hpp"
 
-ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() : _heap(ShenandoahHeap::heap()) {}
-
 #ifdef ASSERT
 template <class T>
 void ShenandoahAssertToSpaceClosure::do_oop_work(T* p) {
@@ -940,43 +939,6 @@
   return CollectedHeap::min_dummy_object_size() + ShenandoahBrooksPointer::word_size();
 }
 
-class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
-private:
-  ShenandoahHeap* _heap;
-  Thread* _thread;
-public:
-  ShenandoahEvacuateUpdateRootsClosure() :
-    _heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
-  }
-
-private:
-  template <class T>
-  void do_oop_work(T* p) {
-    assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
-
-    T o = RawAccess<>::oop_load(p);
-    if (! CompressedOops::is_null(o)) {
-      oop obj = CompressedOops::decode_not_null(o);
-      if (_heap->in_collection_set(obj)) {
-        shenandoah_assert_marked(p, obj);
-        oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
-        if (oopDesc::equals_raw(resolved, obj)) {
-          resolved = _heap->evacuate_object(obj, _thread);
-        }
-        RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
-      }
-    }
-  }
-
-public:
-  void do_oop(oop* p) {
-    do_oop_work(p);
-  }
-  void do_oop(narrowOop* p) {
-    do_oop_work(p);
-  }
-};
-
 class ShenandoahConcurrentEvacuateRegionObjectClosure : public ObjectClosure {
 private:
   ShenandoahHeap* const _heap;
@@ -1884,31 +1846,6 @@
   return result;
 }
 
-ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
-  _mark_context(ShenandoahHeap::heap()->marking_context()) {
-}
-
-ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
-  _mark_context(ShenandoahHeap::heap()->marking_context()) {
-}
-
-bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
-  if (CompressedOops::is_null(obj)) {
-    return false;
-  }
-  obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
-  shenandoah_assert_not_forwarded_if(NULL, obj, ShenandoahHeap::heap()->is_concurrent_mark_in_progress() || ShenandoahHeap::heap()->is_concurrent_traversal_in_progress());
-  return _mark_context->is_marked(obj);
-}
-
-bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
-  if (CompressedOops::is_null(obj)) {
-    return false;
-  }
-  shenandoah_assert_not_forwarded(NULL, obj);
-  return _mark_context->is_marked(obj);
-}
-
 void ShenandoahHeap::ref_processing_init() {
   assert(_max_workers > 0, "Sanity");
 
@@ -2879,8 +2816,3 @@
 ptrdiff_t ShenandoahHeap::cell_header_size() const {
   return ShenandoahBrooksPointer::byte_size();
 }
-
-BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
-  return ShenandoahHeap::heap()->has_forwarded_objects() ? reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl)
-                                                         : reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
-}
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -91,19 +91,6 @@
   virtual bool is_thread_safe() { return false; }
 };
 
-class ShenandoahUpdateRefsClosure: public OopClosure {
-private:
-  ShenandoahHeap* _heap;
-
-  template <class T>
-  inline void do_oop_work(T* p);
-
-public:
-  ShenandoahUpdateRefsClosure();
-  inline void do_oop(oop* p);
-  inline void do_oop(narrowOop* p);
-};
-
 #ifdef ASSERT
 class ShenandoahAssertToSpaceClosure : public OopClosure {
 private:
@@ -115,29 +102,6 @@
 };
 #endif
 
-class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
-private:
-  ShenandoahMarkingContext* const _mark_context;
-public:
-  ShenandoahForwardedIsAliveClosure();
-  bool do_object_b(oop obj);
-};
-
-class ShenandoahIsAliveClosure: public BoolObjectClosure {
-private:
-  ShenandoahMarkingContext* const _mark_context;
-public:
-  ShenandoahIsAliveClosure();
-  bool do_object_b(oop obj);
-};
-
-class ShenandoahIsAliveSelector : public StackObj {
-private:
-  ShenandoahIsAliveClosure _alive_cl;
-  ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
-public:
-  BoolObjectClosure* is_alive_closure();
-};
 
 // Shenandoah GC is low-pause concurrent GC that uses Brooks forwarding pointers
 // to encode forwarding data. See BrooksPointer for details on forwarding data encoding.
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -46,17 +46,6 @@
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
 
-template <class T>
-void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
-  T o = RawAccess<>::oop_load(p);
-  if (!CompressedOops::is_null(o)) {
-    oop obj = CompressedOops::decode_not_null(o);
-    _heap->update_with_forwarded_not_null(p, obj);
-  }
-}
-
-void ShenandoahUpdateRefsClosure::do_oop(oop* p)       { do_oop_work(p); }
-void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
 
 inline ShenandoahHeapRegion* ShenandoahRegionIterator::next() {
   size_t new_index = Atomic::add((size_t) 1, &_index);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -27,6 +27,7 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
 #include "gc/shenandoah/shenandoahHeap.hpp"
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
@@ -242,10 +243,7 @@
   _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
   _srs(n_workers),
   _phase(phase),
-  _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
-  _par_state_string(StringTable::weak_storage())
-
-{
+  _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()) {
   heap->phase_timings()->record_workers_start(_phase);
   if (ShenandoahStringDedup::is_enabled()) {
     StringDedup::gc_prologue(false);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -119,7 +119,6 @@
   StrongRootsScope _srs;
   ShenandoahPhaseTimings::Phase _phase;
   ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
-  OopStorage::ParState<false, false> _par_state_string;
 
   enum Shenandoah_evacuate_roots_tasks {
     SHENANDOAH_EVAC_Universe_oops_do,
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -30,6 +30,7 @@
 #include "gc/shared/workgroup.hpp"
 #include "gc/shared/weakProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
--- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -55,11 +55,7 @@
 
   // Heal oops and disarm
   ZNMethodOopClosure cl;
-  nm->oops_do(&cl);
-  nm->fix_oop_relocations();
-
-  OrderAccess::release();
-
+  ZNMethod::nmethod_oops_do(nm, &cl);
   disarm(nm);
 
   return true;
--- a/src/hotspot/share/gc/z/zUnload.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zUnload.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -71,7 +71,7 @@
     ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
     ZLocker<ZReentrantLock> locker(lock);
     ZIsUnloadingOopClosure cl;
-    nm->oops_do(&cl, true /* allow_zombie */);
+    ZNMethod::nmethod_oops_do(nm, &cl);
     return cl.is_unloading();
   }
 };
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -359,7 +359,7 @@
   }
 
   bool ret = false;
-  thread->set_trace_flag();
+  thread->set_trace_flag();  // Provides StoreLoad, needed to keep read of thread state from floating up.
   if (JAVA_SAMPLE == type) {
     if (thread_state_in_java(thread)) {
       ret = sample_thread_in_java(thread, frames, max_frames);
--- a/src/hotspot/share/memory/filemap.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/filemap.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -806,13 +806,14 @@
                                 addr, size, false /* !read_only */,
                                 si->_allow_exec);
   close();
+  // These have to be errors because the shared region is now unmapped.
   if (base == NULL) {
-    fail_continue("Unable to remap shared readonly space (errno=%d).", errno);
-    return false;
+    log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
+    vm_exit(1);
   }
   if (base != addr) {
-    fail_continue("Unable to remap shared readonly space at required address.");
-    return false;
+    log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
+    vm_exit(1);
   }
   si->_read_only = false;
   return true;
@@ -849,10 +850,17 @@
   size_t size = align_up(used, alignment);
   char *requested_addr = region_addr(i);
 
-  // If a tool agent is in use (debugging enabled), we must map the address space RW
-  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
+#ifdef _WINDOWS
+  // Windows cannot remap read-only shared memory to read-write when required for
+  // RedefineClasses, which is also used by JFR.  Always map windows regions as RW.
+  si->_read_only = false;
+#else
+  // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
+  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
+      Arguments::has_jfr_option()) {
     si->_read_only = false;
   }
+#endif // _WINDOWS
 
   // map the contents of the CDS archive in this memory
   char *base = os::map_memory(_fd, _full_path, si->_file_offset,
@@ -868,7 +876,6 @@
   MemTracker::record_virtual_memory_type((address)base, mtClassShared);
 #endif
 
-
   if (!verify_region_checksum(i)) {
     return NULL;
   }
--- a/src/hotspot/share/memory/universe.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/universe.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -1151,6 +1151,8 @@
       verify_flags |= Verify_JNIHandles;
     } else if (strcmp(token, "codecache_oops") == 0) {
       verify_flags |= Verify_CodeCacheOops;
+    } else if (strcmp(token, "resolved_method_table") == 0) {
+      verify_flags |= Verify_ResolvedMethodTable;
     } else {
       vm_exit_during_initialization(err_msg("VerifySubSet: \'%s\' memory sub-system is unknown, please correct it", token));
     }
@@ -1230,6 +1232,10 @@
     log_debug(gc, verify)("CodeCache Oops");
     CodeCache::verify_oops();
   }
+  if (should_verify_subset(Verify_ResolvedMethodTable)) {
+    log_debug(gc, verify)("ResolvedMethodTable Oops");
+    ResolvedMethodTable::verify();
+  }
 
   _verify_in_progress = false;
 }
--- a/src/hotspot/share/memory/universe.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/universe.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -478,6 +478,7 @@
     Verify_MetaspaceUtils = 128,
     Verify_JNIHandles = 256,
     Verify_CodeCacheOops = 512,
+    Verify_ResolvedMethodTable = 1024,
     Verify_All = -1
   };
   static void initialize_verify_flags();
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -346,16 +346,6 @@
 // cleaning. Note it might trigger a resize instead.
 void ResolvedMethodTable::finish_dead_counter() {
   check_concurrent_work();
-
-#ifdef ASSERT
-  if (SafepointSynchronize::is_at_safepoint()) {
-    size_t fail_cnt = verify_and_compare_entries();
-    if (fail_cnt != 0) {
-      tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt);
-      guarantee(fail_cnt == 0, "unexpected ResolvedMethodTable verification failures");
-    }
-  }
-#endif // ASSERT
 }
 
 #if INCLUDE_JVMTI
@@ -402,26 +392,16 @@
 }
 #endif // INCLUDE_JVMTI
 
-// Verification and comp
-class VerifyCompResolvedMethod : StackObj {
-  GrowableArray<oop>* _oops;
+// Verification
+class VerifyResolvedMethod : StackObj {
  public:
-  size_t _errors;
-  VerifyCompResolvedMethod(GrowableArray<oop>* oops) : _oops(oops), _errors(0) {}
   bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
-    oop s = val->peek();
-    if (s == NULL) {
-      return true;
+    oop obj = val->peek();
+    if (obj != NULL) {
+      Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(obj);
+      guarantee(method->is_method(), "Must be");
+      guarantee(!method->is_old(), "Must be");
     }
-    int len = _oops->length();
-    for (int i = 0; i < len; i++) {
-      bool eq = s == _oops->at(i);
-      assert(!eq, "Duplicate entries");
-      if (eq) {
-        _errors++;
-      }
-    }
-    _oops->push(s);
     return true;
   };
 };
@@ -430,16 +410,9 @@
   return _items_count;
 }
 
-size_t ResolvedMethodTable::verify_and_compare_entries() {
-  Thread* thr = Thread::current();
-  GrowableArray<oop>* oops =
-    new (ResourceObj::C_HEAP, mtInternal)
-      GrowableArray<oop>((int)_current_size, true);
-
-  VerifyCompResolvedMethod vcs(oops);
-  if (!_local_table->try_scan(thr, vcs)) {
+void ResolvedMethodTable::verify() {
+  VerifyResolvedMethod vcs;
+  if (!_local_table->try_scan(Thread::current(), vcs)) {
     log_info(membername, table)("verify unavailable at this moment");
   }
-  delete oops;
-  return vcs._errors;
 }
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -96,7 +96,7 @@
 
   // Debugging
   static size_t items_count();
-  static size_t verify_and_compare_entries();
+  static void verify();
 };
 
 #endif // SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
--- a/src/hotspot/share/runtime/arguments.cpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri Apr 19 08:00:42 2019 -0400
@@ -271,17 +271,25 @@
 }
 
 #if INCLUDE_JFR
+static bool _has_jfr_option = false;  // is using JFR
+
 // return true on failure
 static bool match_jfr_option(const JavaVMOption** option) {
   assert((*option)->optionString != NULL, "invariant");
   char* tail = NULL;
   if (match_option(*option, "-XX:StartFlightRecording", (const char**)&tail)) {
+    _has_jfr_option = true;
     return Jfr::on_start_flight_recording_option(option, tail);
   } else if (match_option(*option, "-XX:FlightRecorderOptions", (const char**)&tail)) {
+    _has_jfr_option = true;
     return Jfr::on_flight_recorder_option(option, tail);
   }
   return false;
 }
+
+bool Arguments::has_jfr_option() {
+  return _has_jfr_option;
+}
 #endif
 
 static void logOption(const char* opt) {
--- a/src/hotspot/share/runtime/arguments.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -649,6 +649,8 @@
   static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0;
 
   static bool atojulong(const char *s, julong* result);
+
+  static bool has_jfr_option() NOT_JFR_RETURN_(false);
 };
 
 // Disable options not supported in this release, with a warning if they
--- a/src/hotspot/share/runtime/thread.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/thread.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -1415,7 +1415,7 @@
   // Whenever a thread transitions from native to vm/java it must suspend
   // if external|deopt suspend is present.
   bool is_suspend_after_native() const {
-    return (_suspend_flags & (_external_suspend | _deopt_suspend)) != 0;
+    return (_suspend_flags & (_external_suspend | _deopt_suspend JFR_ONLY(| _trace_flag))) != 0;
   }
 
   // external suspend request is completed
--- a/src/hotspot/share/utilities/macros.hpp	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/utilities/macros.hpp	Fri Apr 19 08:00:42 2019 -0400
@@ -279,8 +279,10 @@
 
 #if INCLUDE_JFR
 #define JFR_ONLY(code) code
+#define NOT_JFR_RETURN_(code) /* next token must be ; */
 #else
 #define JFR_ONLY(code)
+#define NOT_JFR_RETURN_(code) { return code; }
 #endif
 
 #ifndef INCLUDE_JVMCI
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Fri Apr 19 08:00:42 2019 -0400
@@ -25,15 +25,16 @@
 
 package jdk.internal.platform.cgroupv1;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.stream.Stream;
 
+import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
+
 public class Metrics implements jdk.internal.platform.Metrics {
-    private SubSystem memory;
+    private MemorySubSystem memory;
     private SubSystem cpu;
     private SubSystem cpuacct;
     private SubSystem cpuset;
@@ -133,7 +134,7 @@
         for (String subsystemName: subsystemNames) {
             switch (subsystemName) {
                 case "memory":
-                    metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
+                    metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4]));
                     break;
                 case "cpuset":
                     metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
@@ -195,6 +196,11 @@
 
         if (subsystem != null) {
             subsystem.setPath(base);
+            if (subsystem instanceof MemorySubSystem) {
+                MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
+                boolean isHierarchial = getHierarchical(memorySubSystem);
+                memorySubSystem.setHierarchical(isHierarchial);
+            }
             metric.setActiveSubSystems();
         }
         if (subsystem2 != null) {
@@ -203,6 +209,11 @@
     }
 
 
+    private static boolean getHierarchical(MemorySubSystem subsystem) {
+        long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
+        return hierarchical > 0;
+    }
+
     private void setActiveSubSystems() {
         activeSubSystems = true;
     }
@@ -211,7 +222,7 @@
         return activeSubSystems;
     }
 
-    private void setMemorySubSystem(SubSystem memory) {
+    private void setMemorySubSystem(MemorySubSystem memory) {
         this.memory = memory;
     }
 
@@ -366,9 +377,29 @@
 
     public long getMemoryLimit() {
         long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes");
+        if (retval > unlimited_minimum) {
+            if (memory.isHierarchical()) {
+                // memory.limit_in_bytes returned unlimited, attempt
+                // hierarchical memory limit
+                String match = "hierarchical_memory_limit";
+                retval = SubSystem.getLongValueMatchingLine(memory,
+                                                            "memory.stat",
+                                                            match,
+                                                            Metrics::convertHierachicalLimitLine);
+            }
+        }
         return retval > unlimited_minimum ? -1L : retval;
     }
 
+    public static long convertHierachicalLimitLine(String line) {
+        String[] tokens = line.split("\\s");
+        if (tokens.length == 2) {
+            String strVal = tokens[1];
+            return SubSystem.convertStringToLong(strVal);
+        }
+        return unlimited_minimum + 1; // unlimited
+    }
+
     public long getMemoryMaxUsage() {
         return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes");
     }
@@ -417,6 +448,17 @@
 
     public long getMemoryAndSwapLimit() {
         long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
+        if (retval > unlimited_minimum) {
+            if (memory.isHierarchical()) {
+                // memory.memsw.limit_in_bytes returned unlimited, attempt
+                // hierarchical memory limit
+                String match = "hierarchical_memsw_limit";
+                retval = SubSystem.getLongValueMatchingLine(memory,
+                                                            "memory.stat",
+                                                            match,
+                                                            Metrics::convertHierachicalLimitLine);
+            }
+        }
         return retval > unlimited_minimum ? -1L : retval;
     }
 
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Fri Apr 19 08:00:42 2019 -0400
@@ -29,10 +29,11 @@
 import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Stream;
 
 public class SubSystem {
@@ -99,10 +100,32 @@
 
     }
 
+    public static long getLongValueMatchingLine(SubSystem subsystem,
+                                                     String param,
+                                                     String match,
+                                                     Function<String, Long> conversion) {
+        long retval = Metrics.unlimited_minimum + 1; // default unlimited
+        try {
+            List<String> lines = Files.readAllLines(Paths.get(subsystem.path(), param));
+            for (String line: lines) {
+                if (line.contains(match)) {
+                    retval = conversion.apply(line);
+                    break;
+                }
+            }
+        } catch (IOException e) {
+            // Ignore. Default is unlimited.
+        }
+        return retval;
+    }
+
     public static long getLongValue(SubSystem subsystem, String parm) {
         String strval = getStringValue(subsystem, parm);
+        return convertStringToLong(strval);
+    }
+
+    public static long convertStringToLong(String strval) {
         long retval = 0;
-
         if (strval == null) return 0L;
 
         try {
@@ -215,4 +238,22 @@
 
         return ints;
     }
+
+    public static class MemorySubSystem extends SubSystem {
+
+        private boolean hierarchical;
+
+        public MemorySubSystem(String root, String mountPoint) {
+            super(root, mountPoint);
+        }
+
+        boolean isHierarchical() {
+            return hierarchical;
+        }
+
+        void setHierarchical(boolean hierarchical) {
+            this.hierarchical = hierarchical;
+        }
+
+    }
 }
--- a/src/java.base/share/classes/java/lang/String.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/String.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1965,20 +1965,7 @@
         if (str.isEmpty()) {
             return this;
         }
-        if (coder() == str.coder()) {
-            byte[] val = this.value;
-            byte[] oval = str.value;
-            int len = val.length + oval.length;
-            byte[] buf = Arrays.copyOf(val, len);
-            System.arraycopy(oval, 0, buf, val.length, oval.length);
-            return new String(buf, coder);
-        }
-        int len = length();
-        int olen = str.length();
-        byte[] buf = StringUTF16.newBytesFor(len + olen);
-        getBytes(buf, 0, UTF16);
-        str.getBytes(buf, len, UTF16);
-        return new String(buf, UTF16);
+        return StringConcatHelper.simpleConcat(this, str);
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/StringConcatHelper.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
 
 package java.lang;
 
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.ForceInline;
+
 /**
  * Helper for string concatenation. These methods are mostly looked up with private lookups
  * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
@@ -38,8 +41,10 @@
 
     /**
      * Check for overflow, throw exception on overflow.
-     * @param lengthCoder String length and coder
-     * @return lengthCoder
+     *
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @return            the given parameter value, if valid
      */
     private static long checkOverflow(long lengthCoder) {
         if ((int)lengthCoder >= 0) {
@@ -50,76 +55,83 @@
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, boolean value) {
-        return checkOverflow(current + (value ? 4 : 5));
+    static long mix(long lengthCoder, boolean value) {
+        return checkOverflow(lengthCoder + (value ? 4 : 5));
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, byte value) {
-        return mix(current, (int)value);
+    static long mix(long lengthCoder, byte value) {
+        return mix(lengthCoder, (int)value);
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, char value) {
-        return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
+    static long mix(long lengthCoder, char value) {
+        return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, short value) {
-        return mix(current, (int)value);
+    static long mix(long lengthCoder, short value) {
+        return mix(lengthCoder, (int)value);
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, int value) {
-        return checkOverflow(current + Integer.stringSize(value));
+    static long mix(long lengthCoder, int value) {
+        return checkOverflow(lengthCoder + Integer.stringSize(value));
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, long value) {
-        return checkOverflow(current + Long.stringSize(value));
+    static long mix(long lengthCoder, long value) {
+        return checkOverflow(lengthCoder + Long.stringSize(value));
     }
 
     /**
      * Mix value length and coder into current length and coder.
-     * @param current current length
-     * @param value   value to mix in
-     * @return new length and coder
+     * @param lengthCoder String length with coder packed into higher bits
+     *                    the upper word.
+     * @param value       value to mix in
+     * @return            new length and coder
      */
-    static long mix(long current, String value) {
-        current += value.length();
+    static long mix(long lengthCoder, String value) {
+        lengthCoder += value.length();
         if (value.coder() == String.UTF16) {
-            current |= UTF16;
+            lengthCoder |= UTF16;
         }
-        return checkOverflow(current);
+        return checkOverflow(lengthCoder);
     }
 
     /**
@@ -285,10 +297,62 @@
         }
     }
 
+    /**
+     * Perform a simple concatenation between two objects. Added for startup
+     * performance, but also demonstrates the code that would be emitted by
+     * {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy}
+     * for two Object arguments.
+     *
+     * @param first         first argument
+     * @param second        second argument
+     * @return String       resulting string
+     */
+    @ForceInline
+    static String simpleConcat(Object first, Object second) {
+        String s1 = stringOf(first);
+        String s2 = stringOf(second);
+        // start "mixing" in length and coder or arguments, order is not
+        // important
+        long indexCoder = mix(initialCoder(), s2);
+        indexCoder = mix(indexCoder, s1);
+        byte[] buf = newArray(indexCoder);
+        // prepend each argument in reverse order, since we prepending
+        // from the end of the byte array
+        indexCoder = prepend(indexCoder, buf, s2);
+        indexCoder = prepend(indexCoder, buf, s1);
+        return newString(buf, indexCoder);
+    }
+
+    /**
+     * We need some additional conversion for Objects in general, because
+     * {@code String.valueOf(Object)} may return null. String conversion rules
+     * in Java state we need to produce "null" String in this case, so we
+     * provide a customized version that deals with this problematic corner case.
+     */
+    static String stringOf(Object value) {
+        String s;
+        return (value == null || (s = value.toString()) == null) ? "null" : s;
+    }
+
     private static final long LATIN1 = (long)String.LATIN1 << 32;
 
     private static final long UTF16 = (long)String.UTF16 << 32;
 
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+    /**
+     * Allocates an uninitialized byte array based on the length and coder information
+     * in indexCoder
+     * @param indexCoder
+     * @return the newly allocated byte array
+     */
+    @ForceInline
+    static byte[] newArray(long indexCoder) {
+        byte coder = (byte)(indexCoder >> 32);
+        int index = (int)indexCoder;
+        return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
+    }
+
     /**
      * Provides the initial coder for the String.
      * @return initial coder, adjusted into the upper half
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package java.lang.invoke;
 
 import jdk.internal.misc.Unsafe;
+import jdk.internal.misc.VM;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Label;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -191,6 +192,8 @@
      */
     private static final ProxyClassesDumper DUMPER;
 
+    private static final Class<?> STRING_HELPER;
+
     static {
         // In case we need to double-back onto the StringConcatFactory during this
         // static initialization, make sure we have the reasonable defaults to complete
@@ -202,15 +205,20 @@
         // DEBUG = false;        // implied
         // DUMPER = null;        // implied
 
-        Properties props = GetPropertyAction.privilegedGetProperties();
+        try {
+            STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
+        } catch (Throwable e) {
+            throw new AssertionError(e);
+        }
+
         final String strategy =
-                props.getProperty("java.lang.invoke.stringConcat");
+                VM.getSavedProperty("java.lang.invoke.stringConcat");
         CACHE_ENABLE = Boolean.parseBoolean(
-                props.getProperty("java.lang.invoke.stringConcat.cache"));
+                VM.getSavedProperty("java.lang.invoke.stringConcat.cache"));
         DEBUG = Boolean.parseBoolean(
-                props.getProperty("java.lang.invoke.stringConcat.debug"));
+                VM.getSavedProperty("java.lang.invoke.stringConcat.debug"));
         final String dumpPath =
-                props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
+                VM.getSavedProperty("java.lang.invoke.stringConcat.dumpClasses");
 
         STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
         CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
@@ -1519,6 +1527,33 @@
 
         static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
 
+            // Fast-path two-argument Object + Object concatenations
+            if (recipe.getElements().size() == 2) {
+                // Two object arguments
+                if (mt.parameterCount() == 2 &&
+                        !mt.parameterType(0).isPrimitive() &&
+                        !mt.parameterType(1).isPrimitive()) {
+                    return SIMPLE;
+                }
+                // One element is a constant
+                if (mt.parameterCount() == 1 && !mt.parameterType(0).isPrimitive()) {
+                    MethodHandle mh = SIMPLE;
+                    // Insert constant element
+
+                    // First recipe element is a constant
+                    if (recipe.getElements().get(0).getTag() == TAG_CONST &&
+                        recipe.getElements().get(1).getTag() != TAG_CONST) {
+                        return MethodHandles.insertArguments(mh, 0,
+                                recipe.getElements().get(0).getValue());
+                    } else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
+                               recipe.getElements().get(0).getTag() != TAG_CONST) {
+                        return MethodHandles.insertArguments(mh, 1,
+                                recipe.getElements().get(1).getValue());
+                    }
+                    // else... fall-through to slow-path
+                }
+            }
+
             // Create filters and obtain filtered parameter types. Filters would be used in the beginning
             // to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
             // The filtered argument type list is used all over in the combinators below.
@@ -1626,13 +1661,6 @@
             return mh;
         }
 
-        @ForceInline
-        private static byte[] newArray(long indexCoder) {
-            byte coder = (byte)(indexCoder >> 32);
-            int index = (int)indexCoder;
-            return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
-        }
-
         private static MethodHandle prepender(Class<?> cl) {
             return PREPENDERS.computeIfAbsent(cl, PREPEND);
         }
@@ -1659,16 +1687,15 @@
             }
         };
 
+        private static final MethodHandle SIMPLE;
         private static final MethodHandle NEW_STRING;
         private static final MethodHandle NEW_ARRAY;
         private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
         private static final ConcurrentMap<Class<?>, MethodHandle> MIXERS;
         private static final long INITIAL_CODER;
-        static final Class<?> STRING_HELPER;
 
         static {
             try {
-                STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
                 MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", long.class);
                 INITIAL_CODER = (long) initCoder.invoke();
             } catch (Throwable e) {
@@ -1678,8 +1705,9 @@
             PREPENDERS = new ConcurrentHashMap<>();
             MIXERS = new ConcurrentHashMap<>();
 
+            SIMPLE     = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "simpleConcat", String.class, Object.class, Object.class);
             NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, long.class);
-            NEW_ARRAY  = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, long.class);
+            NEW_ARRAY  = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newArray", byte[].class, long.class);
         }
     }
 
@@ -1692,22 +1720,8 @@
             // no instantiation
         }
 
-        private static class ObjectStringifier {
-
-            // We need some additional conversion for Objects in general, because String.valueOf(Object)
-            // may return null. String conversion rules in Java state we need to produce "null" String
-            // in this case, so we provide a customized version that deals with this problematic corner case.
-            private static String valueOf(Object value) {
-                String s;
-                return (value == null || (s = value.toString()) == null) ? "null" : s;
-            }
-
-            // Could have used MethodHandles.lookup() instead of Lookup.IMPL_LOOKUP, if not for the fact
-            // java.lang.invoke Lookups are explicitly forbidden to be retrieved using that API.
-            private static final MethodHandle INSTANCE =
-                    lookupStatic(Lookup.IMPL_LOOKUP, ObjectStringifier.class, "valueOf", String.class, Object.class);
-
-        }
+        private static final MethodHandle OBJECT_INSTANCE =
+            lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "stringOf", String.class, Object.class);
 
         private static class FloatStringifiers {
             private static final MethodHandle FLOAT_INSTANCE =
@@ -1751,7 +1765,7 @@
          */
         static MethodHandle forMost(Class<?> t) {
             if (!t.isPrimitive()) {
-                return ObjectStringifier.INSTANCE;
+                return OBJECT_INSTANCE;
             } else if (t == float.class) {
                 return FloatStringifiers.FLOAT_INSTANCE;
             } else if (t == double.class) {
--- a/src/java.base/share/classes/java/math/BigDecimal.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/math/BigDecimal.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3414,9 +3414,32 @@
      */
     @Override
     public long longValue(){
-        return (intCompact != INFLATED && scale == 0) ?
-            intCompact:
-            toBigInteger().longValue();
+        if (intCompact != INFLATED && scale == 0) {
+            return intCompact;
+        } else {
+            // Fastpath zero and small values
+            if (this.signum() == 0 || fractionOnly() ||
+                // Fastpath very large-scale values that will result
+                // in a truncated value of zero. If the scale is -64
+                // or less, there are at least 64 powers of 10 in the
+                // value of the numerical result. Since 10 = 2*5, in
+                // that case there would also be 64 powers of 2 in the
+                // result, meaning all 64 bits of a long will be zero.
+                scale <= -64) {
+                return 0;
+            } else {
+                return toBigInteger().longValue();
+            }
+        }
+    }
+
+    /**
+     * Return true if a nonzero BigDecimal has an absolute value less
+     * than one; i.e. only has fraction digits.
+     */
+    private boolean fractionOnly() {
+        assert this.signum() != 0;
+        return (this.precision() - this.scale) <= 0;
     }
 
     /**
@@ -3434,15 +3457,20 @@
     public long longValueExact() {
         if (intCompact != INFLATED && scale == 0)
             return intCompact;
+
+        // Fastpath zero
+        if (this.signum() == 0)
+            return 0;
+
+        // Fastpath numbers less than 1.0 (the latter can be very slow
+        // to round if very small)
+        if (fractionOnly())
+            throw new ArithmeticException("Rounding necessary");
+
         // If more than 19 digits in integer part it cannot possibly fit
         if ((precision() - scale) > 19) // [OK for negative scale too]
             throw new java.lang.ArithmeticException("Overflow");
-        // Fastpath zero and < 1.0 numbers (the latter can be very slow
-        // to round if very small)
-        if (this.signum() == 0)
-            return 0;
-        if ((this.precision() - this.scale) <= 0)
-            throw new ArithmeticException("Rounding necessary");
+
         // round to an integer, with Exception if decimal part non-0
         BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
         if (num.precision() >= 19) // need to check carefully
@@ -3486,7 +3514,7 @@
     public int intValue() {
         return  (intCompact != INFLATED && scale == 0) ?
             (int)intCompact :
-            toBigInteger().intValue();
+            (int)longValue();
     }
 
     /**
--- a/src/java.base/share/classes/java/time/chrono/JapaneseEra.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/JapaneseEra.java	Fri Apr 19 08:00:42 2019 -0400
@@ -154,6 +154,8 @@
      * The singleton instance for the 'Reiwa' era (2019-05-01 - )
      * which has the value 3. The end date of this era is not specified, unless
      * the Japanese Government defines it.
+     *
+     * @since 13
      */
     public static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1));
 
--- a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,20 @@
 
 package sun.nio.cs;
 
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.charset.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
 
 public class StreamDecoder extends Reader
 {
@@ -190,8 +200,11 @@
         synchronized (lock) {
             if (closed)
                 return;
-            implClose();
-            closed = true;
+            try {
+                implClose();
+            } finally {
+                closed = true;
+            }
         }
     }
 
--- a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,21 @@
  * questions.
  */
 
-/*
- */
-
 package sun.nio.cs;
 
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.charset.*;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
 
 public class StreamEncoder extends Writer
 {
@@ -158,8 +164,11 @@
         synchronized (lock) {
             if (closed)
                 return;
-            implClose();
-            closed = true;
+            try {
+                implClose();
+            } finally {
+                closed = true;
+            }
         }
     }
 
@@ -337,8 +346,13 @@
                 writeBytes();
             if (ch != null)
                 ch.close();
-            else
-                out.close();
+            else {
+                try {
+                    out.flush();
+                } finally {
+                    out.close();
+                }
+            }
         } catch (IOException x) {
             encoder.reset();
             throw x;
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri Apr 19 08:00:42 2019 -0400
@@ -980,7 +980,7 @@
             }
 
             try {
-                shutdownInput(false);
+                SSLSocketImpl.this.close();
             } catch (IOException ioe) {
                 // ignore the exception
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
@@ -1146,7 +1146,7 @@
             }
 
             try {
-                shutdownOutput();
+                SSLSocketImpl.this.close();
             } catch (IOException ioe) {
                 // ignore the exception
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
--- a/src/java.base/share/native/libjli/java.c	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/native/libjli/java.c	Fri Apr 19 08:00:42 2019 -0400
@@ -204,11 +204,14 @@
  */
 static jlong threadStackSize    = 0;  /* stack size of the new thread */
 static jlong maxHeapSize        = 0;  /* max heap size */
-static jlong initialHeapSize    = 0;  /* inital heap size */
+static jlong initialHeapSize    = 0;  /* initial heap size */
 
 /*
- * A minimum -Xss stack size suitable for all platforms.
- */
+ * A minimum initial-thread stack size suitable for most platforms.
+ * This is the minimum amount of stack needed to load the JVM such
+ * that it can reject a too small -Xss value. If this is too small
+ * JVM initialization would cause a StackOverflowError.
+  */
 #ifndef STACK_SIZE_MINIMUM
 #define STACK_SIZE_MINIMUM (64 * KB)
 #endif
@@ -934,16 +937,18 @@
     options[numOptions].optionString = str;
     options[numOptions++].extraInfo = info;
 
+    /*
+     * -Xss is used both by the JVM and here to establish the stack size of the thread
+     * created to launch the JVM. In the latter case we need to ensure we don't go
+     * below the minimum stack size allowed. If -Xss is zero that tells the JVM to use
+     * 'default' sizes (either from JVM or system configuration, e.g. 'ulimit -s' on linux),
+     * and is not itself a small stack size that will be rejected. So we ignore -Xss0 here.
+     */
     if (JLI_StrCCmp(str, "-Xss") == 0) {
         jlong tmp;
         if (parse_size(str + 4, &tmp)) {
             threadStackSize = tmp;
-            /*
-             * Make sure the thread stack size is big enough that we won't get a stack
-             * overflow before the JVM startup code can check to make sure the stack
-             * is big enough.
-             */
-            if (threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
+            if (threadStackSize > 0 && threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
                 threadStackSize = STACK_SIZE_MINIMUM;
             }
         }
@@ -2322,38 +2327,38 @@
                     int argc, char **argv,
                     int mode, char *what, int ret)
 {
-
-    /*
-     * If user doesn't specify stack size, check if VM has a preference.
-     * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
-     * return its default stack size through the init args structure.
-     */
     if (threadStackSize == 0) {
-      struct JDK1_1InitArgs args1_1;
-      memset((void*)&args1_1, 0, sizeof(args1_1));
-      args1_1.version = JNI_VERSION_1_1;
-      ifn->GetDefaultJavaVMInitArgs(&args1_1);  /* ignore return value */
-      if (args1_1.javaStackSize > 0) {
-         threadStackSize = args1_1.javaStackSize;
-      }
+        /*
+         * If the user hasn't specified a non-zero stack size ask the JVM for its default.
+         * A returned 0 means 'use the system default' for a platform, e.g., Windows.
+         * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
+         * return its default stack size through the init args structure.
+         */
+        struct JDK1_1InitArgs args1_1;
+        memset((void*)&args1_1, 0, sizeof(args1_1));
+        args1_1.version = JNI_VERSION_1_1;
+        ifn->GetDefaultJavaVMInitArgs(&args1_1);  /* ignore return value */
+        if (args1_1.javaStackSize > 0) {
+            threadStackSize = args1_1.javaStackSize;
+        }
     }
 
     { /* Create a new thread to create JVM and invoke main method */
-      JavaMainArgs args;
-      int rslt;
+        JavaMainArgs args;
+        int rslt;
 
-      args.argc = argc;
-      args.argv = argv;
-      args.mode = mode;
-      args.what = what;
-      args.ifn = *ifn;
+        args.argc = argc;
+        args.argv = argv;
+        args.mode = mode;
+        args.what = what;
+        args.ifn = *ifn;
 
-      rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
-      /* If the caller has deemed there is an error we
-       * simply return that, otherwise we return the value of
-       * the callee
-       */
-      return (ret != 0) ? ret : rslt;
+        rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
+        /* If the caller has deemed there is an error we
+         * simply return that, otherwise we return the value of
+         * the callee
+         */
+        return (ret != 0) ? ret : rslt;
     }
 }
 
--- a/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -131,4 +131,18 @@
      * effect
      */
     Locale getLocale();
+
+    /**
+     * Returns {@code true} if <em>preview features</em> are enabled
+     * and {@code false} otherwise.
+     * @return whether or not preview features are enabled
+     *
+     * @implSpec The default implementation of this method returns
+     * {@code false}.
+     *
+     * @since 13
+     */
+    default boolean isPreviewEnabled() {
+        return false;
+    }
 }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,8 @@
         HttpClient client = http1Exchange.client();
 
         // Filter overridable headers from userHeaders
-        userHeaders = HttpHeaders.of(userHeaders.map(), Utils.CONTEXT_RESTRICTED(client));
+        userHeaders = HttpHeaders.of(userHeaders.map(),
+                      connection.contextRestricted(request, client));
 
         final HttpHeaders uh = userHeaders;
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java	Fri Apr 19 08:00:42 2019 -0400
@@ -285,6 +285,16 @@
         }
     }
 
+    BiPredicate<String,String> contextRestricted(HttpRequestImpl request, HttpClient client) {
+        if (!isTunnel() && request.isConnect()) {
+            // establishing a proxy tunnel
+            assert request.proxy() == null;
+            return Utils.PROXY_TUNNEL_RESTRICTED(client);
+        } else {
+            return Utils.CONTEXT_RESTRICTED(client);
+        }
+    }
+
     // Composes a new immutable HttpHeaders that combines the
     // user and system header but only keeps those headers that
     // start with "proxy-"
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Fri Apr 19 08:00:42 2019 -0400
@@ -178,7 +178,12 @@
                 ! (k.equalsIgnoreCase("Authorization")
                         && k.equalsIgnoreCase("Proxy-Authorization"));
     }
+    private static final BiPredicate<String, String> HOST_RESTRICTED = (k,v) -> !"host".equalsIgnoreCase(k);
+    public static final BiPredicate<String, String> PROXY_TUNNEL_RESTRICTED(HttpClient client)  {
+        return CONTEXT_RESTRICTED(client).and(HOST_RESTRICTED);
+    }
 
+    private static final Predicate<String> IS_HOST = "host"::equalsIgnoreCase;
     private static final Predicate<String> IS_PROXY_HEADER = (k) ->
             k != null && k.length() > 6 && "proxy-".equalsIgnoreCase(k.substring(0,6));
     private static final Predicate<String> NO_PROXY_HEADER =
@@ -250,7 +255,8 @@
 
     public static final BiPredicate<String, String> PROXY_TUNNEL_FILTER =
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_TUNNEL_DISABLED_SCHEMES,
-                    IS_PROXY_HEADER);
+                    // Allows Proxy-* and Host headers when establishing the tunnel.
+                    IS_PROXY_HEADER.or(IS_HOST));
     public static final BiPredicate<String, String> PROXY_FILTER =
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_DISABLED_SCHEMES,
                     ALL_HEADERS);
--- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,24 @@
 
     public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
             throws java.lang.Exception {
-        if (hash != interfaceHash)
-            throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+        if (opnum < 0) {
+            if (hash == 7583982177005850366L) {
+                opnum = 0;
+            } else if (hash == 2571371476350237748L) {
+                opnum = 1;
+            } else if (hash == -7538657168040752697L) {
+                opnum = 2;
+            } else if (hash == -8381844669958460146L) {
+                opnum = 3;
+            } else if (hash == 7305022919901907578L) {
+                opnum = 4;
+            } else {
+                throw new java.rmi.UnmarshalException("invalid method hash");
+            }
+        } else {
+            if (hash != interfaceHash)
+                throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+        }
 
         sun.rmi.registry.RegistryImpl server = (sun.rmi.registry.RegistryImpl) obj;
         switch (opnum) {
--- a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
 import java.rmi.ServerException;
 import java.rmi.UnmarshalException;
 import java.rmi.server.ExportException;
+import java.rmi.server.Operation;
 import java.rmi.server.RemoteCall;
 import java.rmi.server.RemoteRef;
 import java.rmi.server.RemoteStub;
@@ -292,15 +293,14 @@
                 throw new UnmarshalException("error unmarshalling call header",
                                              readEx);
             }
-            if (num >= 0) {
-                if (skel != null) {
+            if (skel != null) {
+                // If there is a skeleton, use it
                     oldDispatch(obj, call, num);
                     return;
-                } else {
-                    throw new UnmarshalException(
-                        "skeleton class not found but required " +
-                        "for client version");
-                }
+
+            } else if (num >= 0){
+                throw new UnmarshalException(
+                        "skeleton class not found but required for client version");
             }
             try {
                 op = in.readLong();
@@ -428,8 +428,8 @@
 
     /**
      * Handle server-side dispatch using the RMI 1.1 stub/skeleton
-     * protocol, given a non-negative operation number that has
-     * already been read from the call stream.
+     * protocol, given a non-negative operation number or negative method hash
+     * that has already been read from the call stream.
      * Exceptions are handled by the caller to be sent to the remote client.
      *
      * @param obj the target remote object for the call
@@ -461,7 +461,8 @@
         }
 
         // if calls are being logged, write out object id and operation
-        logCall(obj, skel.getOperations()[op]);
+        Operation[] operations = skel.getOperations();
+        logCall(obj, op >= 0 && op < operations.length ?  operations[op] : "op: " + op);
         unmarshalCustomCallData(in);
         // dispatch to skeleton for remote object
         skel.dispatch(obj, call, op, hash);
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -22,6 +22,7 @@
 
 import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
 import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
+import com.sun.org.apache.xerces.internal.impl.io.UTF16Reader;
 import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
@@ -89,7 +90,7 @@
  * @author K.Venugopal SUN Microsystems
  * @author Neeraj Bajaj SUN Microsystems
  * @author Sunitha Reddy SUN Microsystems
- * @LastModified: Nov 2018
+ * @LastModified: Apr 2019
  */
 public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
 
@@ -412,9 +413,6 @@
     /** Augmentations for entities. */
     private final Augmentations fEntityAugs = new AugmentationsImpl();
 
-    /** Pool of character buffers. */
-    private CharacterBufferPool fBufferPool = new CharacterBufferPool(fBufferSize, DEFAULT_INTERNAL_BUFFER_SIZE);
-
     /** indicate whether Catalog should be used for resolving external resources */
     private boolean fUseCatalog = true;
     CatalogFeatures fCatalogFeatures;
@@ -694,7 +692,8 @@
             }
 
             // wrap this stream in RewindableInputStream
-            stream = new RewindableInputStream(stream);
+            RewindableInputStream rewindableStream = new RewindableInputStream(stream);
+            stream = rewindableStream;
 
             // perform auto-detect of encoding if necessary
             if (encoding == null) {
@@ -702,27 +701,30 @@
                 final byte[] b4 = new byte[4];
                 int count = 0;
                 for (; count<4; count++ ) {
-                    b4[count] = (byte)stream.read();
+                    b4[count] = (byte)rewindableStream.readAndBuffer();
                 }
                 if (count == 4) {
-                    Object [] encodingDesc = getEncodingName(b4, count);
-                    encoding = (String)(encodingDesc[0]);
-                    isBigEndian = (Boolean)(encodingDesc[1]);
-
+                    final EncodingInfo info = getEncodingInfo(b4, count);
+                    encoding = info.autoDetectedEncoding;
+                    final String readerEncoding = info.readerEncoding;
+                    isBigEndian = info.isBigEndian;
                     stream.reset();
-                    // Special case UTF-8 files with BOM created by Microsoft
-                    // tools. It's more efficient to consume the BOM than make
-                    // the reader perform extra checks. -Ac
-                    if (count > 2 && encoding.equals("UTF-8")) {
-                        int b0 = b4[0] & 0xFF;
-                        int b1 = b4[1] & 0xFF;
-                        int b2 = b4[2] & 0xFF;
-                        if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
-                            // ignore first three bytes...
+                    if (info.hasBOM) {
+                        // Special case UTF-8 files with BOM created by Microsoft
+                        // tools. It's more efficient to consume the BOM than make
+                        // the reader perform extra checks. -Ac
+                        if (EncodingInfo.STR_UTF8.equals(readerEncoding)) {
+                            // UTF-8 BOM: 0xEF 0xBB 0xBF
                             stream.skip(3);
                         }
+                        // It's also more efficient to consume the UTF-16 BOM.
+                        else if (EncodingInfo.STR_UTF16.equals(readerEncoding)) {
+                            // UTF-16 BE BOM: 0xFE 0xFF
+                            // UTF-16 LE BOM: 0xFF 0xFE
+                            stream.skip(2);
+                        }
                     }
-                    reader = createReader(stream, encoding, isBigEndian);
+                    reader = createReader(stream, readerEncoding, isBigEndian);
                 } else {
                     reader = createReader(stream, encoding, isBigEndian);
                 }
@@ -733,11 +735,11 @@
                 encoding = encoding.toUpperCase(Locale.ENGLISH);
 
                 // If encoding is UTF-8, consume BOM if one is present.
-                if (encoding.equals("UTF-8")) {
+                if (EncodingInfo.STR_UTF8.equals(encoding)) {
                     final int[] b3 = new int[3];
                     int count = 0;
                     for (; count < 3; ++count) {
-                        b3[count] = stream.read();
+                        b3[count] = rewindableStream.readAndBuffer();
                         if (b3[count] == -1)
                             break;
                     }
@@ -750,56 +752,51 @@
                         stream.reset();
                     }
                 }
-                // If encoding is UTF-16, we still need to read the first four bytes
-                // in order to discover the byte order.
-                else if (encoding.equals("UTF-16")) {
+                // If encoding is UTF-16, we still need to read the first
+                // four bytes, in order to discover the byte order.
+                else if (EncodingInfo.STR_UTF16.equals(encoding)) {
                     final int[] b4 = new int[4];
                     int count = 0;
                     for (; count < 4; ++count) {
-                        b4[count] = stream.read();
+                        b4[count] = rewindableStream.readAndBuffer();
                         if (b4[count] == -1)
                             break;
                     }
                     stream.reset();
-
-                    String utf16Encoding = "UTF-16";
                     if (count >= 2) {
                         final int b0 = b4[0];
                         final int b1 = b4[1];
                         if (b0 == 0xFE && b1 == 0xFF) {
                             // UTF-16, big-endian
-                            utf16Encoding = "UTF-16BE";
                             isBigEndian = Boolean.TRUE;
+                            stream.skip(2);
                         }
                         else if (b0 == 0xFF && b1 == 0xFE) {
                             // UTF-16, little-endian
-                            utf16Encoding = "UTF-16LE";
                             isBigEndian = Boolean.FALSE;
+                            stream.skip(2);
                         }
                         else if (count == 4) {
                             final int b2 = b4[2];
                             final int b3 = b4[3];
                             if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
                                 // UTF-16, big-endian, no BOM
-                                utf16Encoding = "UTF-16BE";
                                 isBigEndian = Boolean.TRUE;
                             }
                             if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
                                 // UTF-16, little-endian, no BOM
-                                utf16Encoding = "UTF-16LE";
                                 isBigEndian = Boolean.FALSE;
                             }
                         }
                     }
-                    reader = createReader(stream, utf16Encoding, isBigEndian);
                 }
                 // If encoding is UCS-4, we still need to read the first four bytes
                 // in order to discover the byte order.
-                else if (encoding.equals("ISO-10646-UCS-4")) {
+                else if (EncodingInfo.STR_UCS4.equals(encoding)) {
                     final int[] b4 = new int[4];
                     int count = 0;
                     for (; count < 4; ++count) {
-                        b4[count] = stream.read();
+                        b4[count] = rewindableStream.readAndBuffer();
                         if (b4[count] == -1)
                             break;
                     }
@@ -819,11 +816,11 @@
                 }
                 // If encoding is UCS-2, we still need to read the first four bytes
                 // in order to discover the byte order.
-                else if (encoding.equals("ISO-10646-UCS-2")) {
+                else if (EncodingInfo.STR_UCS2.equals(encoding)) {
                     final int[] b4 = new int[4];
                     int count = 0;
                     for (; count < 4; ++count) {
-                        b4[count] = stream.read();
+                        b4[count] = rewindableStream.readAndBuffer();
                         if (b4[count] == -1)
                             break;
                     }
@@ -1798,7 +1795,6 @@
                     bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) {
                     fBufferSize = bufferSize.intValue();
                     fEntityScanner.setBufferSize(fBufferSize);
-                    fBufferPool.setExternalBufferSize(fBufferSize);
                 }
             }
             if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() &&
@@ -2425,14 +2421,12 @@
      *
      * @param b4    The first four bytes of the input.
      * @param count The number of bytes actually read.
-     * @return a 2-element array:  the first element, an IANA-encoding string,
-     *  the second element a Boolean which is true iff the document is big endian, false
-     *  if it's little-endian, and null if the distinction isn't relevant.
+     * @return an instance of EncodingInfo which represents the auto-detected encoding.
      */
-    protected Object[] getEncodingName(byte[] b4, int count) {
+    protected EncodingInfo getEncodingInfo(byte[] b4, int count) {
 
         if (count < 2) {
-            return defaultEncoding;
+            return EncodingInfo.UTF_8;
         }
 
         // UTF-16, with BOM
@@ -2440,69 +2434,70 @@
         int b1 = b4[1] & 0xFF;
         if (b0 == 0xFE && b1 == 0xFF) {
             // UTF-16, big-endian
-            return new Object [] {"UTF-16BE", true};
+            return EncodingInfo.UTF_16_BIG_ENDIAN_WITH_BOM;
         }
         if (b0 == 0xFF && b1 == 0xFE) {
             // UTF-16, little-endian
-            return new Object [] {"UTF-16LE", false};
+            return EncodingInfo.UTF_16_LITTLE_ENDIAN_WITH_BOM;
         }
 
         // default to UTF-8 if we don't have enough bytes to make a
         // good determination of the encoding
         if (count < 3) {
-            return defaultEncoding;
+            return EncodingInfo.UTF_8;
         }
 
         // UTF-8 with a BOM
         int b2 = b4[2] & 0xFF;
         if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
-            return defaultEncoding;
+            return EncodingInfo.UTF_8_WITH_BOM;
         }
 
         // default to UTF-8 if we don't have enough bytes to make a
         // good determination of the encoding
         if (count < 4) {
-            return defaultEncoding;
+            return EncodingInfo.UTF_8;
         }
 
         // other encodings
         int b3 = b4[3] & 0xFF;
         if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
             // UCS-4, big endian (1234)
-            return new Object [] {"ISO-10646-UCS-4", true};
+            return EncodingInfo.UCS_4_BIG_ENDIAN;
         }
         if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
             // UCS-4, little endian (4321)
-            return new Object [] {"ISO-10646-UCS-4", false};
+            return EncodingInfo.UCS_4_LITTLE_ENDIAN;
         }
         if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
             // UCS-4, unusual octet order (2143)
             // REVISIT: What should this be?
-            return new Object [] {"ISO-10646-UCS-4", null};
+            return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
         }
         if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
             // UCS-4, unusual octect order (3412)
             // REVISIT: What should this be?
-            return new Object [] {"ISO-10646-UCS-4", null};
+            return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
         }
         if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
             // UTF-16, big-endian, no BOM
             // (or could turn out to be UCS-2...
             // REVISIT: What should this be?
-            return new Object [] {"UTF-16BE", true};
+            return EncodingInfo.UTF_16_BIG_ENDIAN;
         }
         if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
             // UTF-16, little-endian, no BOM
             // (or could turn out to be UCS-2...
-            return new Object [] {"UTF-16LE", false};
+            return EncodingInfo.UTF_16_LITTLE_ENDIAN;
         }
         if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
             // EBCDIC
             // a la xerces1, return CP037 instead of EBCDIC here
-            return new Object [] {"CP037", null};
+            return EncodingInfo.EBCDIC;
         }
 
-        return defaultEncoding;
+        // default encoding
+        return EncodingInfo.UTF_8;
 
     } // getEncodingName(byte[],int):Object[]
 
@@ -2517,95 +2512,95 @@
      *                     encoding name may be a Java encoding name;
      *                     otherwise, it is an ianaEncoding name.
      * @param isBigEndian   For encodings (like uCS-4), whose names cannot
-     *                      specify a byte order, this tells whether the order is bigEndian.  null menas
-     *                      unknown or not relevant.
+     *                      specify a byte order, this tells whether the order
+     *                      is bigEndian.  null if unknown or irrelevant.
      *
      * @return Returns a reader.
      */
     protected Reader createReader(InputStream inputStream, String encoding, Boolean isBigEndian)
-    throws IOException {
-
-        // normalize encoding name
-        if (encoding == null) {
-            encoding = "UTF-8";
-        }
-
-        // try to use an optimized reader
-        String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
-        if (ENCODING.equals("UTF-8")) {
-            if (DEBUG_ENCODINGS) {
-                System.out.println("$$$ creating UTF8Reader");
-            }
-            return new UTF8Reader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale() );
-        }
-        if (ENCODING.equals("US-ASCII")) {
-            if (DEBUG_ENCODINGS) {
-                System.out.println("$$$ creating ASCIIReader");
-            }
-            return new ASCIIReader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale());
-        }
-        if(ENCODING.equals("ISO-10646-UCS-4")) {
-            if(isBigEndian != null) {
-                boolean isBE = isBigEndian.booleanValue();
-                if(isBE) {
-                    return new UCSReader(inputStream, UCSReader.UCS4BE);
+        throws IOException {
+
+        String enc = (encoding != null) ? encoding : EncodingInfo.STR_UTF8;
+        enc = enc.toUpperCase(Locale.ENGLISH);
+        MessageFormatter f = fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN);
+        Locale l = fErrorReporter.getLocale();
+        switch (enc) {
+            case EncodingInfo.STR_UTF8:
+                return new UTF8Reader(inputStream, fBufferSize, f, l);
+            case EncodingInfo.STR_UTF16:
+                if (isBigEndian != null) {
+                    return new UTF16Reader(inputStream, fBufferSize, isBigEndian, f, l);
+                }
+                break;
+            case EncodingInfo.STR_UTF16BE:
+                return new UTF16Reader(inputStream, fBufferSize, true, f, l);
+            case EncodingInfo.STR_UTF16LE:
+                return new UTF16Reader(inputStream, fBufferSize, false, f, l);
+            case EncodingInfo.STR_UCS4:
+                if(isBigEndian != null) {
+                    if(isBigEndian) {
+                        return new UCSReader(inputStream, UCSReader.UCS4BE);
+                    } else {
+                        return new UCSReader(inputStream, UCSReader.UCS4LE);
+                    }
                 } else {
-                    return new UCSReader(inputStream, UCSReader.UCS4LE);
+                    fErrorReporter.reportError(this.getEntityScanner(),
+                            XMLMessageFormatter.XML_DOMAIN,
+                            "EncodingByteOrderUnsupported",
+                            new Object[] { encoding },
+                            XMLErrorReporter.SEVERITY_FATAL_ERROR);
                 }
-            } else {
-                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
-                        "EncodingByteOrderUnsupported",
-                        new Object[] { encoding },
-                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
-            }
-        }
-        if(ENCODING.equals("ISO-10646-UCS-2")) {
-            if(isBigEndian != null) { // sould never happen with this encoding...
-                boolean isBE = isBigEndian.booleanValue();
-                if(isBE) {
-                    return new UCSReader(inputStream, UCSReader.UCS2BE);
+                break;
+            case EncodingInfo.STR_UCS2:
+                if(isBigEndian != null) {
+                    if(isBigEndian) {
+                        return new UCSReader(inputStream, UCSReader.UCS2BE);
+                    } else {
+                        return new UCSReader(inputStream, UCSReader.UCS2LE);
+                    }
                 } else {
-                    return new UCSReader(inputStream, UCSReader.UCS2LE);
+                    fErrorReporter.reportError(this.getEntityScanner(),
+                            XMLMessageFormatter.XML_DOMAIN,
+                            "EncodingByteOrderUnsupported",
+                            new Object[] { encoding },
+                            XMLErrorReporter.SEVERITY_FATAL_ERROR);
                 }
-            } else {
-                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
-                        "EncodingByteOrderUnsupported",
-                        new Object[] { encoding },
-                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
-            }
+                break;
         }
 
         // check for valid name
         boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
         boolean validJava = XMLChar.isValidJavaEncoding(encoding);
         if (!validIANA || (fAllowJavaEncodings && !validJava)) {
-            fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
+            fErrorReporter.reportError(this.getEntityScanner(),
+                    XMLMessageFormatter.XML_DOMAIN,
                     "EncodingDeclInvalid",
                     new Object[] { encoding },
                     XMLErrorReporter.SEVERITY_FATAL_ERROR);
-                    // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
-                    //       because every byte is a valid ISO Latin 1 character.
-                    //       It may not translate correctly but if we failed on
-                    //       the encoding anyway, then we're expecting the content
-                    //       of the document to be bad. This will just prevent an
-                    //       invalid UTF-8 sequence to be detected. This is only
-                    //       important when continue-after-fatal-error is turned
-                    //       on. -Ac
+            // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
+            //       because every byte is a valid ISO Latin 1 character.
+            //       It may not translate correctly but if we failed on
+            //       the encoding anyway, then we're expecting the content
+            //       of the document to be bad. This will just prevent an
+            //       invalid UTF-8 sequence to be detected. This is only
+            //       important when continue-after-fatal-error is turned
+            //       on. -Ac
                     encoding = "ISO-8859-1";
         }
 
         // try to use a Java reader
-        String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
+        String javaEncoding = EncodingMap.getIANA2JavaMapping(enc);
         if (javaEncoding == null) {
-            if(fAllowJavaEncodings) {
+            if (fAllowJavaEncodings) {
                 javaEncoding = encoding;
             } else {
-                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
+                fErrorReporter.reportError(this.getEntityScanner(),
+                        XMLMessageFormatter.XML_DOMAIN,
                         "EncodingDeclInvalid",
                         new Object[] { encoding },
                         XMLErrorReporter.SEVERITY_FATAL_ERROR);
-                        // see comment above.
-                        javaEncoding = "ISO8859_1";
+                // see comment above.
+                javaEncoding = "ISO8859_1";
             }
         }
         if (DEBUG_ENCODINGS) {
@@ -2898,108 +2893,78 @@
     } // print()
 
     /**
-     * Buffer used in entity manager to reuse character arrays instead
-     * of creating new ones every time.
-     *
-     * @xerces.internal
-     *
-     * @author Ankit Pasricha, IBM
-     */
-    private static class CharacterBuffer {
-
-        /** character buffer */
-        private char[] ch;
-
-        /** whether the buffer is for an external or internal scanned entity */
-        private boolean isExternal;
-
-        public CharacterBuffer(boolean isExternal, int size) {
-            this.isExternal = isExternal;
-            ch = new char[size];
-        }
-    }
-
-
-     /**
-     * Stores a number of character buffers and provides it to the entity
-     * manager to use when an entity is seen.
+     * Information about auto-detectable encodings.
      *
      * @xerces.internal
      *
-     * @author Ankit Pasricha, IBM
+     * @author Michael Glavassevich, IBM
      */
-    private static class CharacterBufferPool {
-
-        private static final int DEFAULT_POOL_SIZE = 3;
-
-        private CharacterBuffer[] fInternalBufferPool;
-        private CharacterBuffer[] fExternalBufferPool;
-
-        private int fExternalBufferSize;
-        private int fInternalBufferSize;
-        private int poolSize;
-
-        private int fInternalTop;
-        private int fExternalTop;
-
-        public CharacterBufferPool(int externalBufferSize, int internalBufferSize) {
-            this(DEFAULT_POOL_SIZE, externalBufferSize, internalBufferSize);
-        }
-
-        public CharacterBufferPool(int poolSize, int externalBufferSize, int internalBufferSize) {
-            fExternalBufferSize = externalBufferSize;
-            fInternalBufferSize = internalBufferSize;
-            this.poolSize = poolSize;
-            init();
-        }
-
-        /** Initializes buffer pool. **/
-        private void init() {
-            fInternalBufferPool = new CharacterBuffer[poolSize];
-            fExternalBufferPool = new CharacterBuffer[poolSize];
-            fInternalTop = -1;
-            fExternalTop = -1;
-        }
-
-        /** Retrieves buffer from pool. **/
-        public CharacterBuffer getBuffer(boolean external) {
-            if (external) {
-                if (fExternalTop > -1) {
-                    return fExternalBufferPool[fExternalTop--];
-                }
-                else {
-                    return new CharacterBuffer(true, fExternalBufferSize);
-                }
-            }
-            else {
-                if (fInternalTop > -1) {
-                    return fInternalBufferPool[fInternalTop--];
-                }
-                else {
-                    return new CharacterBuffer(false, fInternalBufferSize);
-                }
-            }
-        }
-
-        /** Returns buffer to pool. **/
-        public void returnToPool(CharacterBuffer buffer) {
-            if (buffer.isExternal) {
-                if (fExternalTop < fExternalBufferPool.length - 1) {
-                    fExternalBufferPool[++fExternalTop] = buffer;
-                }
-            }
-            else if (fInternalTop < fInternalBufferPool.length - 1) {
-                fInternalBufferPool[++fInternalTop] = buffer;
-            }
-        }
-
-        /** Sets the size of external buffers and dumps the old pool. **/
-        public void setExternalBufferSize(int bufferSize) {
-            fExternalBufferSize = bufferSize;
-            fExternalBufferPool = new CharacterBuffer[poolSize];
-            fExternalTop = -1;
-        }
-    }
+    private static class EncodingInfo {
+        public static final String STR_UTF8 = "UTF-8";
+        public static final String STR_UTF16 = "UTF-16";
+        public static final String STR_UTF16BE = "UTF-16BE";
+        public static final String STR_UTF16LE = "UTF-16LE";
+        public static final String STR_UCS4 = "ISO-10646-UCS-4";
+        public static final String STR_UCS2 = "ISO-10646-UCS-2";
+        public static final String STR_CP037 = "CP037";
+
+        /** UTF-8 **/
+        public static final EncodingInfo UTF_8 =
+                new EncodingInfo(STR_UTF8, null, false);
+
+        /** UTF-8, with BOM **/
+        public static final EncodingInfo UTF_8_WITH_BOM =
+                new EncodingInfo(STR_UTF8, null, true);
+
+        /** UTF-16, big-endian **/
+        public static final EncodingInfo UTF_16_BIG_ENDIAN =
+                new EncodingInfo(STR_UTF16BE, STR_UTF16, Boolean.TRUE, false);
+
+        /** UTF-16, big-endian with BOM **/
+        public static final EncodingInfo UTF_16_BIG_ENDIAN_WITH_BOM =
+                new EncodingInfo(STR_UTF16BE, STR_UTF16, Boolean.TRUE, true);
+
+        /** UTF-16, little-endian **/
+        public static final EncodingInfo UTF_16_LITTLE_ENDIAN =
+                new EncodingInfo(STR_UTF16LE, STR_UTF16, Boolean.FALSE, false);
+
+        /** UTF-16, little-endian with BOM **/
+        public static final EncodingInfo UTF_16_LITTLE_ENDIAN_WITH_BOM =
+                new EncodingInfo(STR_UTF16LE, STR_UTF16, Boolean.FALSE, true);
+
+        /** UCS-4, big-endian **/
+        public static final EncodingInfo UCS_4_BIG_ENDIAN =
+                new EncodingInfo(STR_UCS4, Boolean.TRUE, false);
+
+        /** UCS-4, little-endian **/
+        public static final EncodingInfo UCS_4_LITTLE_ENDIAN =
+                new EncodingInfo(STR_UCS4, Boolean.FALSE, false);
+
+        /** UCS-4, unusual byte-order (2143) or (3412) **/
+        public static final EncodingInfo UCS_4_UNUSUAL_BYTE_ORDER =
+                new EncodingInfo(STR_UCS4, null, false);
+
+        /** EBCDIC **/
+        public static final EncodingInfo EBCDIC = new EncodingInfo(STR_CP037, null, false);
+
+        public final String autoDetectedEncoding;
+        public final String readerEncoding;
+        public final Boolean isBigEndian;
+        public final boolean hasBOM;
+
+        private EncodingInfo(String autoDetectedEncoding, Boolean isBigEndian, boolean hasBOM) {
+            this(autoDetectedEncoding, autoDetectedEncoding, isBigEndian, hasBOM);
+        } // <init>(String,Boolean,boolean)
+
+        private EncodingInfo(String autoDetectedEncoding, String readerEncoding,
+                Boolean isBigEndian, boolean hasBOM) {
+            this.autoDetectedEncoding = autoDetectedEncoding;
+            this.readerEncoding = readerEncoding;
+            this.isBigEndian = isBigEndian;
+            this.hasBOM = hasBOM;
+        } // <init>(String,String,Boolean,boolean)
+
+    } // class EncodingInfo
 
     /**
     * This class wraps the byte inputstreams we're presented with.
@@ -3052,20 +3017,13 @@
             fOffset = fStartOffset;
         }
 
-        public int read() throws IOException {
-            int b = 0;
-            if (fOffset < fLength) {
-                return fData[fOffset++] & 0xff;
-            }
-            if (fOffset == fEndOffset) {
-                return -1;
-            }
+        public int readAndBuffer() throws IOException {
             if (fOffset == fData.length) {
                 byte[] newData = new byte[fOffset << 1];
                 System.arraycopy(fData, 0, newData, 0, fOffset);
                 fData = newData;
             }
-            b = fInputStream.read();
+            final int b = fInputStream.read();
             if (b == -1) {
                 fEndOffset = fOffset;
                 return -1;
@@ -3075,18 +3033,27 @@
             return b & 0xff;
         }
 
+        public int read() throws IOException {
+            if (fOffset < fLength) {
+                return fData[fOffset++] & 0xff;
+            }
+            if (fOffset == fEndOffset) {
+                return -1;
+            }
+            if (fCurrentEntity.mayReadChunks) {
+                return fInputStream.read();
+            }
+            return readAndBuffer();
+        }
+
         public int read(byte[] b, int off, int len) throws IOException {
-            int bytesLeft = fLength - fOffset;
+            final int bytesLeft = fLength - fOffset;
             if (bytesLeft == 0) {
                 if (fOffset == fEndOffset) {
                     return -1;
                 }
 
-                /**
-                 * //System.out.println("fCurrentEntitty = " + fCurrentEntity );
-                 * //System.out.println("fInputStream = " + fInputStream );
-                 * // better get some more for the voracious reader... */
-
+                // read a block of data as requested
                 if(fCurrentEntity.mayReadChunks || !fCurrentEntity.xmlDeclChunkRead) {
 
                     if (!fCurrentEntity.xmlDeclChunkRead)
@@ -3096,15 +3063,13 @@
                     }
                     return fInputStream.read(b, off, len);
                 }
-
-                int returnedVal = read();
-                if(returnedVal == -1) {
-                  fEndOffset = fOffset;
-                  return -1;
+                int returnedVal = readAndBuffer();
+                if (returnedVal == -1) {
+                    fEndOffset = fOffset;
+                    return -1;
                 }
                 b[off] = (byte)returnedVal;
                 return 1;
-
             }
             if (len < bytesLeft) {
                 if (len <= 0) {
@@ -3120,8 +3085,7 @@
             return len;
         }
 
-        public long skip(long n)
-        throws IOException {
+        public long skip(long n) throws IOException {
             int bytesLeft;
             if (n <= 0) {
                 return 0;
@@ -3142,7 +3106,7 @@
                 return bytesLeft;
             }
             n -= bytesLeft;
-            /*
+           /*
             * In a manner of speaking, when this class isn't permitting more
             * than one byte at a time to be read, it is "blocking".  The
             * available() method should indicate how much can be read without
@@ -3154,13 +3118,13 @@
         }
 
         public int available() throws IOException {
-            int bytesLeft = fLength - fOffset;
+            final int bytesLeft = fLength - fOffset;
             if (bytesLeft == 0) {
                 if (fOffset == fEndOffset) {
                     return -1;
                 }
                 return fCurrentEntity.mayReadChunks ? fInputStream.available()
-                : 0;
+                                                    : 0;
             }
             return bytesLeft;
         }
@@ -3171,7 +3135,6 @@
 
         public void reset() {
             fOffset = fMark;
-            //test();
         }
 
         public boolean markSupported() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Apr 19 08:00:42 2019 -0400
@@ -55,6 +55,7 @@
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
 import com.sun.tools.javac.jvm.*;
+import com.sun.tools.javac.jvm.PoolConstant;
 import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.tree.JCTree.Tag;
@@ -91,7 +92,7 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public abstract class Symbol extends AnnoConstruct implements Element {
+public abstract class Symbol extends AnnoConstruct implements PoolConstant, Element {
 
     /** The kind of this symbol.
      *  @see Kinds
@@ -286,6 +287,11 @@
         this.name = name;
     }
 
+    @Override
+    public int poolTag() {
+        throw new AssertionError("Invalid pool entry");
+    }
+
     /** Clone this symbol with new owner.
      *  Legal only for fields and methods.
      */
@@ -971,6 +977,11 @@
             this.type = new ModuleType(this);
         }
 
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_Module;
+        }
+
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
         public Name getSimpleName() {
             return Convert.shortName(name);
@@ -1137,6 +1148,11 @@
             return members_field;
         }
 
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_Package;
+        }
+
         public long flags() {
             complete();
             return flags_field;
@@ -1237,10 +1253,6 @@
          */
         public List<ClassSymbol> trans_local;
 
-        /** the constant pool of the class
-         */
-        public Pool pool;
-
         /** the annotation metadata attached to this class */
         private AnnotationTypeMetadata annotationTypeMetadata;
 
@@ -1251,7 +1263,6 @@
             this.flatname = formFlatName(name, owner);
             this.sourcefile = null;
             this.classfile = null;
-            this.pool = null;
             this.annotationTypeMetadata = AnnotationTypeMetadata.notAnAnnotationType();
         }
 
@@ -1543,6 +1554,11 @@
             super(VAR, flags, name, type, owner);
         }
 
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_Fieldref;
+        }
+
         /** Clone this symbol with new owner.
          */
         public VarSymbol clone(Symbol newOwner) {
@@ -1551,6 +1567,11 @@
                 public Symbol baseSymbol() {
                     return VarSymbol.this;
                 }
+
+                @Override
+                public Object poolKey(Types types) {
+                    return new Pair<>(newOwner, baseSymbol());
+                }
             };
             v.pos = pos;
             v.adr = adr;
@@ -1711,6 +1732,11 @@
                 public Symbol baseSymbol() {
                     return MethodSymbol.this;
                 }
+
+                @Override
+                public Object poolKey(Types types) {
+                    return new Pair<>(newOwner, baseSymbol());
+                }
             };
             m.code = code;
             return m;
@@ -1740,10 +1766,25 @@
             }
         }
 
+        @Override
+        public int poolTag() {
+            return owner.isInterface() ?
+                    ClassFile.CONSTANT_InterfaceMethodref : ClassFile.CONSTANT_Methodref;
+        }
+
         public boolean isDynamic() {
             return false;
         }
 
+        public boolean isHandle() {
+            return false;
+        }
+
+
+        public MethodHandleSymbol asHandle() {
+            return new MethodHandleSymbol(this);
+        }
+
         /** find a symbol that this (proxy method) symbol implements.
          *  @param    c       The class whose members are searched for
          *                    implementations
@@ -2027,16 +2068,14 @@
 
     /** A class for invokedynamic method calls.
      */
-    public static class DynamicMethodSymbol extends MethodSymbol {
+    public static class DynamicMethodSymbol extends MethodSymbol implements Dynamic {
 
-        public Object[] staticArgs;
-        public Symbol bsm;
-        public int bsmKind;
+        public LoadableConstant[] staticArgs;
+        public MethodHandleSymbol bsm;
 
-        public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
+        public DynamicMethodSymbol(Name name, Symbol owner, MethodHandleSymbol bsm, Type type, LoadableConstant[] staticArgs) {
             super(0, name, type, owner);
             this.bsm = bsm;
-            this.bsmKind = bsmKind;
             this.staticArgs = staticArgs;
         }
 
@@ -2044,6 +2083,83 @@
         public boolean isDynamic() {
             return true;
         }
+
+        @Override
+        public LoadableConstant[] staticArgs() {
+            return staticArgs;
+        }
+
+        @Override
+        public MethodHandleSymbol bootstrapMethod() {
+            return bsm;
+        }
+
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_InvokeDynamic;
+        }
+
+        @Override
+        public Type dynamicType() {
+            return type;
+        }
+    }
+
+    /** A class for method handles.
+     */
+    public static class MethodHandleSymbol extends MethodSymbol implements LoadableConstant {
+
+        private Symbol refSym;
+
+        public MethodHandleSymbol(Symbol msym) {
+            super(msym.flags_field, msym.name, msym.type, msym.owner);
+            this.refSym = msym;
+        }
+
+        /**
+         * Returns the kind associated with this method handle.
+         */
+        public int referenceKind() {
+            if (refSym.isConstructor()) {
+                return ClassFile.REF_newInvokeSpecial;
+            } else {
+                if (refSym.isStatic()) {
+                    return ClassFile.REF_invokeStatic;
+                } else if ((refSym.flags() & PRIVATE) != 0) {
+                    return ClassFile.REF_invokeSpecial;
+                } else if (refSym.enclClass().isInterface()) {
+                    return ClassFile.REF_invokeInterface;
+                } else {
+                    return ClassFile.REF_invokeVirtual;
+                }
+            }
+        }
+
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_MethodHandle;
+        }
+
+        @Override
+        public Object poolKey(Types types) {
+            return new Pair<>(baseSymbol(), referenceKind());
+        }
+
+        @Override
+        public MethodHandleSymbol asHandle() {
+            return this;
+        }
+
+        @Override
+        public Symbol baseSymbol() {
+            return refSym;
+        }
+
+
+        @Override
+        public boolean isHandle() {
+            return true;
+        }
     }
 
     /** A class for predefined operators.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Apr 19 08:00:42 2019 -0400
@@ -36,7 +36,10 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.TypeMetadata.Entry;
 import com.sun.tools.javac.code.Types.TypeMapping;
+import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.comp.Infer.IncorporationAction;
+import com.sun.tools.javac.jvm.ClassFile;
+import com.sun.tools.javac.jvm.PoolConstant;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 
@@ -73,7 +76,7 @@
  *
  *  @see TypeTag
  */
-public abstract class Type extends AnnoConstruct implements TypeMirror {
+public abstract class Type extends AnnoConstruct implements TypeMirror, PoolConstant {
 
     /**
      * Type metadata,  Should be {@code null} for the default value.
@@ -125,6 +128,16 @@
      */
     public TypeSymbol tsym;
 
+    @Override
+    public int poolTag() {
+        throw new AssertionError("Invalid pool entry");
+    }
+
+    @Override
+    public Object poolKey(Types types) {
+        return new UniqueType(this, types);
+    }
+
     /**
      * Checks if the current type tag is equal to the given tag.
      * @return true if tag is equal to the current type tag.
@@ -930,7 +943,7 @@
         }
     }
 
-    public static class ClassType extends Type implements DeclaredType,
+    public static class ClassType extends Type implements DeclaredType, LoadableConstant,
                                                           javax.lang.model.type.ErrorType {
 
         /** The enclosing type of this type. If this is the type of an inner
@@ -975,6 +988,10 @@
             this.interfaces_field = null;
         }
 
+        public int poolTag() {
+            return ClassFile.CONSTANT_Class;
+        }
+
         @Override
         public ClassType cloneWithMetadata(TypeMetadata md) {
             return new ClassType(outer_field, typarams_field, tsym, md) {
@@ -1277,7 +1294,7 @@
     }
 
     public static class ArrayType extends Type
-            implements javax.lang.model.type.ArrayType {
+            implements LoadableConstant, javax.lang.model.type.ArrayType {
 
         public Type elemtype;
 
@@ -1297,6 +1314,10 @@
             this(that.elemtype, that.tsym, that.getMetadata());
         }
 
+        public int poolTag() {
+            return ClassFile.CONSTANT_Class;
+        }
+
         @Override
         public ArrayType cloneWithMetadata(TypeMetadata md) {
             return new ArrayType(elemtype, tsym, md) {
@@ -1412,7 +1433,7 @@
         }
     }
 
-    public static class MethodType extends Type implements ExecutableType {
+    public static class MethodType extends Type implements ExecutableType, LoadableConstant {
 
         public List<Type> argtypes;
         public Type restype;
@@ -1479,6 +1500,11 @@
                 restype != null && restype.isErroneous();
         }
 
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_MethodType;
+        }
+
         public boolean contains(Type elem) {
             return elem.equalsIgnoreMetadata(this) || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem);
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 19 08:00:42 2019 -0400
@@ -48,6 +48,8 @@
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.LambdaToMethod;
+import com.sun.tools.javac.jvm.ClassFile;
 import com.sun.tools.javac.util.*;
 
 import static com.sun.tools.javac.code.BoundKind.*;
@@ -5181,6 +5183,29 @@
             }
         }
     }
+
+    public Type constantType(LoadableConstant c) {
+        switch (c.poolTag()) {
+            case ClassFile.CONSTANT_Class:
+                return syms.classType;
+            case ClassFile.CONSTANT_String:
+                return syms.stringType;
+            case ClassFile.CONSTANT_Integer:
+                return syms.intType;
+            case ClassFile.CONSTANT_Float:
+                return syms.floatType;
+            case ClassFile.CONSTANT_Long:
+                return syms.longType;
+            case ClassFile.CONSTANT_Double:
+                return syms.doubleType;
+            case ClassFile.CONSTANT_MethodHandle:
+                return syms.methodHandleType;
+            case ClassFile.CONSTANT_MethodType:
+                return syms.methodTypeType;
+            default:
+                throw new AssertionError("Not a loadable constant: " + c.poolTag());
+        }
+    }
     // </editor-fold>
 
     public void newRound() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Apr 19 08:00:42 2019 -0400
@@ -25,7 +25,9 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.tree.*;
@@ -59,7 +61,6 @@
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
@@ -70,13 +71,10 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
-import static com.sun.tools.javac.jvm.Pool.DynamicMethod;
 
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.type.TypeKind;
 
-import com.sun.tools.javac.code.Type.IntersectionClassType;
-import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
 import com.sun.tools.javac.main.Option;
 
 /**
@@ -214,7 +212,7 @@
 
         private Map<DedupedLambda, DedupedLambda> dedupedLambdas;
 
-        private Map<DynamicMethod, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
+        private Map<Object, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
 
         /**
          * list of deserialization cases
@@ -439,11 +437,8 @@
         //then, determine the arguments to the indy call
         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 
-        //build a sam instance using an indy call to the meta-factory
-        int refKind = referenceKind(sym);
-
         //convert to an invokedynamic call
-        result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
+        result = makeMetafactoryIndyCall(context, sym.asHandle(), indy_args);
     }
 
     // where
@@ -488,7 +483,7 @@
 
         //first determine the method symbol to be used to generate the sam instance
         //this is either the method reference symbol, or the bridged reference symbol
-        Symbol refSym = tree.sym;
+        MethodSymbol refSym = (MethodSymbol)tree.sym;
 
         //the qualifying expression is treated as a special captured arg
         JCExpression init;
@@ -522,7 +517,7 @@
 
 
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
+        result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
     }
 
     /**
@@ -765,8 +760,8 @@
                 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil()));
      }
 
-    private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
-            DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
+    private void addDeserializationCase(MethodHandleSymbol refSym, Type targetType, MethodSymbol samSym,
+                                        DiagnosticPosition pos, List<LoadableConstant> staticArgs, MethodType indyType) {
         String functionalInterfaceClass = classSig(targetType);
         String functionalInterfaceMethodName = samSym.getSimpleName().toString();
         String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
@@ -774,7 +769,8 @@
         String implMethodName = refSym.getQualifiedName().toString();
         String implMethodSignature = typeSig(types.erasure(refSym.type));
 
-        JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
+        JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType),
+                make.Literal(refSym.referenceKind()));
         ListBuffer<JCExpression> serArgs = new ListBuffer<>();
         int i = 0;
         for (Type t : indyType.getParameterTypes()) {
@@ -1106,13 +1102,13 @@
      * Generate an indy method call to the meta factory
      */
     private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
-            int refKind, Symbol refSym, List<JCExpression> indy_args) {
+            MethodHandleSymbol refSym, List<JCExpression> indy_args) {
         JCFunctionalExpression tree = context.tree;
         //determine the static bsm args
         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
-        List<Object> staticArgs = List.of(
+        List<LoadableConstant> staticArgs = List.of(
                 typeToMethodType(samSym.type),
-                new Pool.MethodHandle(refKind, refSym, types),
+                ((MethodSymbol)refSym).asHandle(),
                 typeToMethodType(tree.getDescriptorType(types)));
 
         //computed indy arg types
@@ -1131,7 +1127,7 @@
                 names.altMetafactory : names.metafactory;
 
         if (context.needsAltMetafactory()) {
-            ListBuffer<Object> markers = new ListBuffer<>();
+            ListBuffer<Type> markers = new ListBuffer<>();
             List<Type> targets = tree.target.isIntersection() ?
                     types.directSupertypes(tree.target) :
                     List.nil();
@@ -1140,7 +1136,7 @@
                 if (t.tsym != syms.serializableType.tsym &&
                     t.tsym != tree.type.tsym &&
                     t.tsym != syms.objectType.tsym) {
-                    markers.append(t.tsym);
+                    markers.append(t);
                 }
             }
             int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
@@ -1152,17 +1148,17 @@
             if (hasBridges) {
                 flags |= FLAG_BRIDGES;
             }
-            staticArgs = staticArgs.append(flags);
+            staticArgs = staticArgs.append(LoadableConstant.Int(flags));
             if (hasMarkers) {
-                staticArgs = staticArgs.append(markers.length());
-                staticArgs = staticArgs.appendList(markers.toList());
+                staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
+                staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
             }
             if (hasBridges) {
-                staticArgs = staticArgs.append(context.bridges.length() - 1);
+                staticArgs = staticArgs.append(LoadableConstant.Int(context.bridges.length() - 1));
                 for (Symbol s : context.bridges) {
                     Type s_erasure = s.erasure(types);
                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
-                        staticArgs = staticArgs.append(s.erasure(types));
+                        staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
                     }
                 }
             }
@@ -1170,7 +1166,7 @@
                 int prevPos = make.pos;
                 try {
                     make.at(kInfo.clazz);
-                    addDeserializationCase(refKind, refSym, tree.type, samSym,
+                    addDeserializationCase(refSym, tree.type, samSym,
                             tree, staticArgs, indyType);
                 } finally {
                     make.at(prevPos);
@@ -1186,14 +1182,14 @@
      * arguments types
      */
     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
-            List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
-            Name methName) {
+                                      List<LoadableConstant> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
+                                      Name methName) {
         int prevPos = make.pos;
         try {
             make.at(pos);
             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
-                    syms.stringType,
-                    syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
+                syms.stringType,
+                syms.methodTypeType).appendList(staticArgs.map(types::constantType));
 
             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
                     bsmName, bsm_staticArgs, List.nil());
@@ -1201,15 +1197,12 @@
             DynamicMethodSymbol dynSym =
                     new DynamicMethodSymbol(methName,
                                             syms.noSymbol,
-                                            bsm.isStatic() ?
-                                                ClassFile.REF_invokeStatic :
-                                                ClassFile.REF_invokeVirtual,
-                                            (MethodSymbol)bsm,
+                                            ((MethodSymbol)bsm).asHandle(),
                                             indyType,
-                                            staticArgs.toArray());
+                                            staticArgs.toArray(new LoadableConstant[staticArgs.length()]));
             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
             DynamicMethodSymbol existing = kInfo.dynMethSyms.putIfAbsent(
-                    new DynamicMethod(dynSym, types), dynSym);
+                    dynSym.poolKey(types), dynSym);
             qualifier.sym = existing != null ? existing : dynSym;
             qualifier.type = indyType.getReturnType();
 
@@ -1220,57 +1213,6 @@
             make.at(prevPos);
         }
     }
-    //where
-    private List<Type> bsmStaticArgToTypes(List<Object> args) {
-        ListBuffer<Type> argtypes = new ListBuffer<>();
-        for (Object arg : args) {
-            argtypes.append(bsmStaticArgToType(arg));
-        }
-        return argtypes.toList();
-    }
-
-    private Type bsmStaticArgToType(Object arg) {
-        Assert.checkNonNull(arg);
-        if (arg instanceof ClassSymbol) {
-            return syms.classType;
-        } else if (arg instanceof Integer) {
-            return syms.intType;
-        } else if (arg instanceof Long) {
-            return syms.longType;
-        } else if (arg instanceof Float) {
-            return syms.floatType;
-        } else if (arg instanceof Double) {
-            return syms.doubleType;
-        } else if (arg instanceof String) {
-            return syms.stringType;
-        } else if (arg instanceof Pool.MethodHandle) {
-            return syms.methodHandleType;
-        } else if (arg instanceof MethodType) {
-            return syms.methodTypeType;
-        } else {
-            Assert.error("bad static arg " + arg.getClass());
-            return null;
-        }
-    }
-
-    /**
-     * Get the opcode associated with this method reference
-     */
-    private int referenceKind(Symbol refSym) {
-        if (refSym.isConstructor()) {
-            return ClassFile.REF_newInvokeSpecial;
-        } else {
-            if (refSym.isStatic()) {
-                return ClassFile.REF_invokeStatic;
-            } else if ((refSym.flags() & PRIVATE) != 0) {
-                return ClassFile.REF_invokeSpecial;
-            } else if (refSym.enclClass().isInterface()) {
-                return ClassFile.REF_invokeInterface;
-            } else {
-                return ClassFile.REF_invokeVirtual;
-            }
-        }
-    }
 
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
     /**
@@ -2312,13 +2254,6 @@
                 this.isSuper = tree.hasKind(ReferenceKind.SUPER);
             }
 
-            /**
-             * Get the opcode associated with this method reference
-             */
-            int referenceKind() {
-                return LambdaToMethod.this.referenceKind(tree.sym);
-            }
-
             boolean needsVarArgsConversion() {
                 return tree.varargsElement != null;
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Apr 19 08:00:42 2019 -0400
@@ -93,7 +93,6 @@
     private final Attr attr;
     private TreeMaker make;
     private DiagnosticPosition make_pos;
-    private final ClassWriter writer;
     private final ConstFold cfolder;
     private final Target target;
     private final Source source;
@@ -116,7 +115,6 @@
         chk = Check.instance(context);
         attr = Attr.instance(context);
         make = TreeMaker.instance(context);
-        writer = ClassWriter.instance(context);
         cfolder = ConstFold.instance(context);
         target = Target.instance(context);
         source = Source.instance(context);
@@ -475,7 +473,7 @@
                 .fromString(target.syntheticNameChar() +
                             "SwitchMap" +
                             target.syntheticNameChar() +
-                            writer.xClassName(forEnum.type).toString()
+                            names.fromUtf(ClassWriter.externalize(forEnum.type.tsym.flatName())).toString()
                             .replace('/', '.')
                             .replace('.', target.syntheticNameChar()));
             ClassSymbol outerCacheClass = outerCacheClass();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Fri Apr 19 08:00:42 2019 -0400
@@ -25,9 +25,6 @@
 
 package com.sun.tools.javac.jvm;
 
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.util.Name;
 
 
@@ -189,38 +186,4 @@
     public static byte[] externalize(Name name) {
         return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
     }
-
-/************************************************************************
- * Name-and-type
- ***********************************************************************/
-
-    /** A class for the name-and-type signature of a method or field.
-     */
-    public static class NameAndType {
-        Name name;
-        UniqueType uniqueType;
-        Types types;
-
-        NameAndType(Name name, Type type, Types types) {
-            this.name = name;
-            this.uniqueType = new UniqueType(type, types);
-            this.types = types;
-        }
-
-        void setType(Type type) {
-            this.uniqueType = new UniqueType(type, types);
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            return (other instanceof NameAndType &&
-                    name == ((NameAndType) other).name &&
-                        uniqueType.equals(((NameAndType) other).uniqueType));
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode() * uniqueType.hashCode();
-        }
-    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.IntFunction;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
@@ -55,8 +56,8 @@
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.file.PathFileObject;
-import com.sun.tools.javac.jvm.ClassFile.NameAndType;
 import com.sun.tools.javac.jvm.ClassFile.Version;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
 import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
@@ -100,11 +101,6 @@
      */
     boolean verbose;
 
-    /** Switch: read constant pool and code sections. This switch is initially
-     *  set to false but can be turned on from outside.
-     */
-    public boolean readAllOfClassFile = false;
-
     /** Switch: allow modules.
      */
     boolean allowModules;
@@ -170,20 +166,15 @@
 
     /** The buffer containing the currently read class file.
      */
-    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+    ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
 
     /** The current input pointer.
      */
     protected int bp;
 
-    /** The objects of the constant pool.
+    /** The pool reader.
      */
-    Object[] poolObj;
-
-    /** For every constant pool entry, an index into buf where the
-     *  defining section of the entry is found.
-     */
-    int[] poolIdx;
+    PoolReader poolReader;
 
     /** The major version number of the class file being read. */
     int majorVersion;
@@ -323,294 +314,29 @@
     /** Read a character.
      */
     char nextChar() {
-        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+        char res = buf.getChar(bp);
+        bp += 2;
+        return res;
     }
 
     /** Read a byte.
      */
     int nextByte() {
-        return buf[bp++] & 0xFF;
+        return buf.getByte(bp++) & 0xFF;
     }
 
     /** Read an integer.
      */
     int nextInt() {
-        return
-            ((buf[bp++] & 0xFF) << 24) +
-            ((buf[bp++] & 0xFF) << 16) +
-            ((buf[bp++] & 0xFF) << 8) +
-            (buf[bp++] & 0xFF);
-    }
-
-    /** Extract a character at position bp from buf.
-     */
-    char getChar(int bp) {
-        return
-            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
-    }
-
-    /** Extract an integer at position bp from buf.
-     */
-    int getInt(int bp) {
-        return
-            ((buf[bp] & 0xFF) << 24) +
-            ((buf[bp+1] & 0xFF) << 16) +
-            ((buf[bp+2] & 0xFF) << 8) +
-            (buf[bp+3] & 0xFF);
-    }
-
-
-    /** Extract a long integer at position bp from buf.
-     */
-    long getLong(int bp) {
-        DataInputStream bufin =
-            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
-        try {
-            return bufin.readLong();
-        } catch (IOException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    /** Extract a float at position bp from buf.
-     */
-    float getFloat(int bp) {
-        DataInputStream bufin =
-            new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
-        try {
-            return bufin.readFloat();
-        } catch (IOException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    /** Extract a double at position bp from buf.
-     */
-    double getDouble(int bp) {
-        DataInputStream bufin =
-            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
-        try {
-            return bufin.readDouble();
-        } catch (IOException e) {
-            throw new AssertionError(e);
-        }
+        int res = buf.getInt(bp);
+        bp += 4;
+        return res;
     }
 
 /************************************************************************
  * Constant Pool Access
  ***********************************************************************/
 
-    /** Index all constant pool entries, writing their start addresses into
-     *  poolIdx.
-     */
-    void indexPool() {
-        poolIdx = new int[nextChar()];
-        poolObj = new Object[poolIdx.length];
-        int i = 1;
-        while (i < poolIdx.length) {
-            poolIdx[i++] = bp;
-            byte tag = buf[bp++];
-            switch (tag) {
-            case CONSTANT_Utf8: case CONSTANT_Unicode: {
-                int len = nextChar();
-                bp = bp + len;
-                break;
-            }
-            case CONSTANT_Class:
-            case CONSTANT_String:
-            case CONSTANT_MethodType:
-            case CONSTANT_Module:
-            case CONSTANT_Package:
-                bp = bp + 2;
-                break;
-            case CONSTANT_MethodHandle:
-                bp = bp + 3;
-                break;
-            case CONSTANT_Fieldref:
-            case CONSTANT_Methodref:
-            case CONSTANT_InterfaceMethodref:
-            case CONSTANT_NameandType:
-            case CONSTANT_Integer:
-            case CONSTANT_Float:
-            case CONSTANT_Dynamic:
-            case CONSTANT_InvokeDynamic:
-                bp = bp + 4;
-                break;
-            case CONSTANT_Long:
-            case CONSTANT_Double:
-                bp = bp + 8;
-                i++;
-                break;
-            default:
-                throw badClassFile("bad.const.pool.tag.at",
-                                   Byte.toString(tag),
-                                   Integer.toString(bp -1));
-            }
-        }
-    }
-
-    /** Read constant pool entry at start address i, use pool as a cache.
-     */
-    Object readPool(int i) {
-        Object result = poolObj[i];
-        if (result != null) return result;
-
-        int index = poolIdx[i];
-        if (index == 0) return null;
-
-        byte tag = buf[index];
-        switch (tag) {
-        case CONSTANT_Utf8:
-            poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
-            break;
-        case CONSTANT_Unicode:
-            throw badClassFile("unicode.str.not.supported");
-        case CONSTANT_Class:
-            poolObj[i] = readClassOrType(getChar(index + 1));
-            break;
-        case CONSTANT_String:
-            // FIXME: (footprint) do not use toString here
-            poolObj[i] = readName(getChar(index + 1)).toString();
-            break;
-        case CONSTANT_Fieldref: {
-            ClassSymbol owner = readClassSymbol(getChar(index + 1));
-            NameAndType nt = readNameAndType(getChar(index + 3));
-            poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
-            break;
-        }
-        case CONSTANT_Methodref:
-        case CONSTANT_InterfaceMethodref: {
-            ClassSymbol owner = readClassSymbol(getChar(index + 1));
-            NameAndType nt = readNameAndType(getChar(index + 3));
-            poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
-            break;
-        }
-        case CONSTANT_NameandType:
-            poolObj[i] = new NameAndType(
-                readName(getChar(index + 1)),
-                readType(getChar(index + 3)), types);
-            break;
-        case CONSTANT_Integer:
-            poolObj[i] = getInt(index + 1);
-            break;
-        case CONSTANT_Float:
-            poolObj[i] = Float.valueOf(getFloat(index + 1));
-            break;
-        case CONSTANT_Long:
-            poolObj[i] = Long.valueOf(getLong(index + 1));
-            break;
-        case CONSTANT_Double:
-            poolObj[i] = Double.valueOf(getDouble(index + 1));
-            break;
-        case CONSTANT_MethodHandle:
-            skipBytes(4);
-            break;
-        case CONSTANT_MethodType:
-            skipBytes(3);
-            break;
-        case CONSTANT_Dynamic:
-        case CONSTANT_InvokeDynamic:
-            skipBytes(5);
-            break;
-        case CONSTANT_Module:
-        case CONSTANT_Package:
-            // this is temporary for now: treat as a simple reference to the underlying Utf8.
-            poolObj[i] = readName(getChar(index + 1));
-            break;
-        default:
-            throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
-        }
-        return poolObj[i];
-    }
-
-    /** Read signature and convert to type.
-     */
-    Type readType(int i) {
-        int index = poolIdx[i];
-        return sigToType(buf, index + 3, getChar(index + 1));
-    }
-
-    /** If name is an array type or class signature, return the
-     *  corresponding type; otherwise return a ClassSymbol with given name.
-     */
-    Object readClassOrType(int i) {
-        int index =  poolIdx[i];
-        int len = getChar(index + 1);
-        int start = index + 3;
-        Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
-        // by the above assertion, the following test can be
-        // simplified to (buf[start] == '[')
-        return (buf[start] == '[' || buf[start + len - 1] == ';')
-            ? (Object)sigToType(buf, start, len)
-            : (Object)enterClass(names.fromUtf(internalize(buf, start,
-                                                           len)));
-    }
-
-    /** Read signature and convert to type parameters.
-     */
-    List<Type> readTypeParams(int i) {
-        int index = poolIdx[i];
-        return sigToTypeParams(buf, index + 3, getChar(index + 1));
-    }
-
-    /** Read class entry.
-     */
-    ClassSymbol readClassSymbol(int i) {
-        Object obj = readPool(i);
-        if (obj != null && !(obj instanceof ClassSymbol))
-            throw badClassFile("bad.const.pool.entry",
-                               currentClassFile.toString(),
-                               "CONSTANT_Class_info", i);
-        return (ClassSymbol)obj;
-    }
-
-    Name readClassName(int i) {
-        int index = poolIdx[i];
-        if (index == 0) return null;
-        byte tag = buf[index];
-        if (tag != CONSTANT_Class) {
-            throw badClassFile("bad.const.pool.entry",
-                               currentClassFile.toString(),
-                               "CONSTANT_Class_info", i);
-        }
-        int nameIndex =  poolIdx[getChar(index + 1)];
-        int len = getChar(nameIndex + 1);
-        int start = nameIndex + 3;
-        if (buf[start] == '[' || buf[start + len - 1] == ';')
-            throw badClassFile("wrong class name"); //TODO: proper diagnostics
-        return names.fromUtf(internalize(buf, start, len));
-    }
-
-    /** Read name.
-     */
-    Name readName(int i) {
-        Object obj = readPool(i);
-        if (obj != null && !(obj instanceof Name))
-            throw badClassFile("bad.const.pool.entry",
-                               currentClassFile.toString(),
-                               "CONSTANT_Utf8_info or CONSTANT_String_info", i);
-        return (Name)obj;
-    }
-
-    /** Read name and type.
-     */
-    NameAndType readNameAndType(int i) {
-        Object obj = readPool(i);
-        if (obj != null && !(obj instanceof NameAndType))
-            throw badClassFile("bad.const.pool.entry",
-                               currentClassFile.toString(),
-                               "CONSTANT_NameAndType_info", i);
-        return (NameAndType)obj;
-    }
-
-    /** Read the name of a module.
-     * The name is stored in a CONSTANT_Module entry, in
-     * JVMS 4.2 binary form (using ".", not "/")
-     */
-    Name readModuleName(int i) {
-        return readName(i);
-    }
-
     /** Read module_flags.
      */
     Set<ModuleFlags> readModuleFlags(int flags) {
@@ -762,7 +488,7 @@
             List<Type> argtypes = sigToTypes(')');
             Type restype = sigToType();
             List<Type> thrown = List.nil();
-            while (signature[sigp] == '^') {
+            while (sigp < siglimit && signature[sigp] == '^') {
                 sigp++;
                 thrown = thrown.prepend(sigToType());
             }
@@ -855,7 +581,7 @@
                     };
                 switch (signature[sigp++]) {
                 case ';':
-                    if (sigp < signature.length && signature[sigp] == '.') {
+                    if (sigp < siglimit && signature[sigp] == '.') {
                         // support old-style GJC signatures
                         // The signature produced was
                         // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
@@ -1049,7 +775,7 @@
 
             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
-                    if (readAllOfClassFile || saveParameterNames)
+                    if (saveParameterNames)
                         ((MethodSymbol)sym).code = readCode(sym);
                     else
                         bp = bp + attrLen;
@@ -1058,7 +784,7 @@
 
             new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
-                    Object v = readPool(nextChar());
+                    Object v = poolReader.getConstant(nextChar());
                     // Ignore ConstantValue attribute if field not final.
                     if ((sym.flags() & FINAL) == 0) {
                         return;
@@ -1115,7 +841,7 @@
                     int nexceptions = nextChar();
                     List<Type> thrown = List.nil();
                     for (int j = 0; j < nexceptions; j++)
-                        thrown = thrown.prepend(readClassSymbol(nextChar()).type);
+                        thrown = thrown.prepend(poolReader.getClass(nextChar()).type);
                     if (sym.type.getThrownTypes().isEmpty())
                         sym.type.asMethodType().thrown = thrown.reverse();
                 }
@@ -1173,7 +899,7 @@
             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
-                    Name n = readName(nextChar());
+                    Name n = poolReader.getName(nextChar());
                     c.sourcefile = new SourceFileObject(n);
                     // If the class is a toplevel class, originating from a Java source file,
                     // but the class name does not match the file name, then it is
@@ -1211,7 +937,8 @@
                         try {
                             ClassType ct1 = (ClassType)c.type;
                             Assert.check(c == currentOwner);
-                            ct1.typarams_field = readTypeParams(nextChar());
+                            ct1.typarams_field = poolReader.getName(nextChar())
+                                    .map(ClassReader.this::sigToTypeParams);
                             ct1.supertype_field = sigToType();
                             ListBuffer<Type> is = new ListBuffer<>();
                             while (sigp != siglimit) is.append(sigToType());
@@ -1221,7 +948,7 @@
                         }
                     } else {
                         List<Type> thrown = sym.type.getThrownTypes();
-                        sym.type = readType(nextChar());
+                        sym.type = poolReader.getType(nextChar());
                         //- System.err.println(" # " + sym.type);
                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
                             sym.type.asMethodType().thrown = thrown;
@@ -1342,19 +1069,19 @@
                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
                         ListBuffer<Directive> directives = new ListBuffer<>();
 
-                        Name moduleName = readModuleName(nextChar());
+                        Name moduleName = poolReader.peekModuleName(nextChar(), names::fromUtf);
                         if (currentModule.name != moduleName) {
                             throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
                         }
 
                         Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar());
                         msym.flags.addAll(moduleFlags);
-                        msym.version = readName(nextChar());
+                        msym.version = optPoolEntry(nextChar(), poolReader::getName, null);
 
                         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
                         int nrequires = nextChar();
                         for (int i = 0; i < nrequires; i++) {
-                            ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
+                            ModuleSymbol rsym = poolReader.getModule(nextChar());
                             Set<RequiresFlag> flags = readRequiresFlags(nextChar());
                             if (rsym == syms.java_base && majorVersion >= V54.major) {
                                 if (flags.contains(RequiresFlag.TRANSITIVE)) {
@@ -1373,8 +1100,7 @@
                         ListBuffer<ExportsDirective> exports = new ListBuffer<>();
                         int nexports = nextChar();
                         for (int i = 0; i < nexports; i++) {
-                            Name n = readName(nextChar());
-                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            PackageSymbol p = poolReader.getPackage(nextChar());
                             Set<ExportsFlag> flags = readExportsFlags(nextChar());
                             int nto = nextChar();
                             List<ModuleSymbol> to;
@@ -1383,7 +1109,7 @@
                             } else {
                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
                                 for (int t = 0; t < nto; t++)
-                                    lb.append(syms.enterModule(readModuleName(nextChar())));
+                                    lb.append(poolReader.getModule(nextChar()));
                                 to = lb.toList();
                             }
                             exports.add(new ExportsDirective(p, to, flags));
@@ -1396,8 +1122,7 @@
                             throw badClassFile("module.non.zero.opens", currentModule.name);
                         }
                         for (int i = 0; i < nopens; i++) {
-                            Name n = readName(nextChar());
-                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            PackageSymbol p = poolReader.getPackage(nextChar());
                             Set<OpensFlag> flags = readOpensFlags(nextChar());
                             int nto = nextChar();
                             List<ModuleSymbol> to;
@@ -1406,7 +1131,7 @@
                             } else {
                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
                                 for (int t = 0; t < nto; t++)
-                                    lb.append(syms.enterModule(readModuleName(nextChar())));
+                                    lb.append(poolReader.getModule(nextChar()));
                                 to = lb.toList();
                             }
                             opens.add(new OpensDirective(p, to, flags));
@@ -1419,7 +1144,7 @@
                         ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
                         int nuses = nextChar();
                         for (int i = 0; i < nuses; i++) {
-                            Name srvc = readClassName(nextChar());
+                            Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
                             uses.add(new InterimUsesDirective(srvc));
                         }
                         interimUses = uses.toList();
@@ -1427,17 +1152,21 @@
                         ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
                         int nprovides = nextChar();
                         for (int p = 0; p < nprovides; p++) {
-                            Name srvc = readClassName(nextChar());
+                            Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
                             int nimpls = nextChar();
                             ListBuffer<Name> impls = new ListBuffer<>();
                             for (int i = 0; i < nimpls; i++) {
-                                impls.append(readClassName(nextChar()));
+                                impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper));
                             provides.add(new InterimProvidesDirective(srvc, impls.toList()));
                             }
                         }
                         interimProvides = provides.toList();
                     }
                 }
+
+                private Name classNameMapper(byte[] arr, int offset, int length) {
+                    return names.fromUtf(ClassFile.internalize(arr, offset, length));
+                }
             },
 
             new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
@@ -1464,8 +1193,8 @@
         // the scope specified by the attribute
         sym.owner.members().remove(sym);
         ClassSymbol self = (ClassSymbol)sym;
-        ClassSymbol c = readClassSymbol(nextChar());
-        NameAndType nt = readNameAndType(nextChar());
+        ClassSymbol c = poolReader.getClass(nextChar());
+        NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
 
         if (c.members_field == null || c.kind != TYP)
             throw badClassFile("bad.enclosing.class", self, c);
@@ -1520,7 +1249,7 @@
         if (nt == null)
             return null;
 
-        MethodType type = nt.uniqueType.type.asMethodType();
+        MethodType type = nt.type.asMethodType();
 
         for (Symbol sym : scope.getSymbolsByName(nt.name)) {
             if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
@@ -1533,15 +1262,15 @@
         if ((flags & INTERFACE) != 0)
             // no enclosing instance
             return null;
-        if (nt.uniqueType.type.getParameterTypes().isEmpty())
+        if (nt.type.getParameterTypes().isEmpty())
             // no parameters
             return null;
 
         // A constructor of an inner class.
         // Remove the first argument (the enclosing instance)
-        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
-                                 nt.uniqueType.type.getReturnType(),
-                                 nt.uniqueType.type.getThrownTypes(),
+        nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
+                                 nt.type.getReturnType(),
+                                 nt.type.getThrownTypes(),
                                  syms.methodClass));
         // Try searching again
         return findMethod(nt, scope, flags);
@@ -1578,7 +1307,7 @@
     void readAttrs(Symbol sym, AttributeKind kind) {
         char ac = nextChar();
         for (int i = 0; i < ac; i++) {
-            Name attrName = readName(nextChar());
+            Name attrName = poolReader.getName(nextChar());
             int attrLen = nextInt();
             AttributeReader r = attributeReaders.get(attrName);
             if (r != null && r.accepts(kind))
@@ -1681,7 +1410,7 @@
     /** Read parameter annotations.
      */
     void readParameterAnnotations(Symbol meth) {
-        int numParameters = buf[bp++] & 0xFF;
+        int numParameters = buf.getByte(bp++) & 0xFF;
         if (parameterAnnotations == null) {
             parameterAnnotations = new ParameterAnnotations[numParameters];
         } else if (parameterAnnotations.length != numParameters) {
@@ -1725,39 +1454,30 @@
 
     Type readTypeOrClassSymbol(int i) {
         // support preliminary jsr175-format class files
-        if (buf[poolIdx[i]] == CONSTANT_Class)
-            return readClassSymbol(i).type;
-        return readTypeToProxy(i);
-    }
-    Type readEnumType(int i) {
-        // support preliminary jsr175-format class files
-        int index = poolIdx[i];
-        int length = getChar(index + 1);
-        if (buf[index + length + 2] != ';')
-            return enterClass(readName(i)).type;
+        if (poolReader.hasTag(i, CONSTANT_Class))
+            return poolReader.getClass(i).type;
         return readTypeToProxy(i);
     }
     Type readTypeToProxy(int i) {
         if (currentModule.module_info == currentOwner) {
-            int index = poolIdx[i];
-            return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+            return new ProxyType(i);
         } else {
-            return readType(i);
+            return poolReader.getType(i);
         }
     }
 
     CompoundAnnotationProxy readCompoundAnnotation() {
         Type t;
         if (currentModule.module_info == currentOwner) {
-            int index = poolIdx[nextChar()];
-            t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+            int cpIndex = nextChar();
+            t = new ProxyType(cpIndex);
         } else {
             t = readTypeOrClassSymbol(nextChar());
         }
         int numFields = nextChar();
         ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
         for (int i=0; i<numFields; i++) {
-            Name name = readName(nextChar());
+            Name name = poolReader.getName(nextChar());
             Attribute value = readAttributeValue();
             pairs.append(new Pair<>(name, value));
         }
@@ -1970,29 +1690,40 @@
 
     }
 
+    /**
+     * Helper function to read an optional pool entry (with given function); this is used while parsing
+     * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor,
+     * as per JVMS.
+     */
+    <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) {
+        return (index == 0) ?
+                defaultValue :
+                poolFunc.apply(index);
+    }
+
     Attribute readAttributeValue() {
-        char c = (char) buf[bp++];
+        char c = (char) buf.getByte(bp++);
         switch (c) {
         case 'B':
-            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
+            return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar()));
         case 'C':
-            return new Attribute.Constant(syms.charType, readPool(nextChar()));
+            return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar()));
         case 'D':
-            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
+            return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar()));
         case 'F':
-            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
+            return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar()));
         case 'I':
-            return new Attribute.Constant(syms.intType, readPool(nextChar()));
+            return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar()));
         case 'J':
-            return new Attribute.Constant(syms.longType, readPool(nextChar()));
+            return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar()));
         case 'S':
-            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
+            return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar()));
         case 'Z':
-            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
+            return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar()));
         case 's':
-            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
+            return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString());
         case 'e':
-            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
+            return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar()));
         case 'c':
             return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
         case '[': {
@@ -2401,8 +2132,8 @@
      */
     VarSymbol readField() {
         long flags = adjustFieldFlags(nextChar());
-        Name name = readName(nextChar());
-        Type type = readType(nextChar());
+        Name name = poolReader.getName(nextChar());
+        Type type = poolReader.getType(nextChar());
         VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
         readMemberAttrs(v);
         return v;
@@ -2412,8 +2143,8 @@
      */
     MethodSymbol readMethod() {
         long flags = adjustMethodFlags(nextChar());
-        Name name = readName(nextChar());
-        Type type = readType(nextChar());
+        Name name = poolReader.getName(nextChar());
+        Type type = poolReader.getType(nextChar());
         if (currentOwner.isInterface() &&
                 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
             if (majorVersion > Version.V52.major ||
@@ -2592,7 +2323,7 @@
         Name argName;
         if (parameterNameIndices != null && index < parameterNameIndices.length
                 && parameterNameIndices[index] != 0) {
-            argName = readName(parameterNameIndices[index]);
+            argName = optPoolEntry(parameterNameIndices[index], poolReader::getName, names.empty);
             flags |= NAME_FILLED;
         } else {
             String prefix = "arg";
@@ -2681,7 +2412,7 @@
             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
             // read own class name and check that it matches
             currentModule = c.packge().modle;
-            ClassSymbol self = readClassSymbol(nextChar());
+            ClassSymbol self = poolReader.getClass(nextChar());
             if (c != self) {
                 throw badClassFile("class.file.wrong.class",
                                    self.flatname);
@@ -2710,11 +2441,6 @@
         for (int i = 0; i < methodCount; i++) skipMember();
         readClassAttrs(c);
 
-        if (readAllOfClassFile) {
-            for (int i = 1; i < poolObj.length; i++) readPool(i);
-            c.pool = new Pool(poolObj.length, poolObj, types);
-        }
-
         // reset and read rest of classinfo
         bp = startbp;
         int n = nextChar();
@@ -2722,13 +2448,12 @@
             throw badClassFile("module.info.invalid.super.class");
         }
         if (ct.supertype_field == null)
-            ct.supertype_field = (n == 0)
-                ? Type.noType
-                : readClassSymbol(n).erasure(types);
+            ct.supertype_field =
+                    optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType);
         n = nextChar();
         List<Type> is = List.nil();
         for (int i = 0; i < n; i++) {
-            Type _inter = readClassSymbol(nextChar()).erasure(types);
+            Type _inter = poolReader.getClass(nextChar()).erasure(types);
             is = is.prepend(_inter);
         }
         if (ct.interfaces_field == null)
@@ -2749,8 +2474,10 @@
         int n = nextChar();
         for (int i = 0; i < n; i++) {
             nextChar(); // skip inner class symbol
-            ClassSymbol outer = readClassSymbol(nextChar());
-            Name name = readName(nextChar());
+            int outerIdx = nextChar();
+            int nameIdx = nextChar();
+            ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
+            Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
             if (name == null) name = names.empty;
             long flags = adjustClassFlags(nextChar());
             if (outer != null) { // we have a member class
@@ -2804,7 +2531,8 @@
             }
         }
 
-        indexPool();
+        poolReader = new PoolReader(this, names, syms);
+        bp = poolReader.readPool(buf, bp);
         if (signatureBuffer.length < bp) {
             int ns = Integer.highestOneBit(bp) << 1;
             signatureBuffer = new byte[ns];
@@ -2821,7 +2549,8 @@
         repeatable = null;
         try {
             bp = 0;
-            buf = readInputStream(buf, c.classfile.openInputStream());
+            buf.reset();
+            buf.appendStream(c.classfile.openInputStream());
             readClassBuffer(c);
             if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
                 List<Type> missing = missingTypeVariables;
@@ -2875,43 +2604,6 @@
             filling = false;
         }
     }
-    // where
-        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
-            try {
-                buf = ensureCapacity(buf, s.available());
-                int r = s.read(buf);
-                int bp = 0;
-                while (r != -1) {
-                    bp += r;
-                    buf = ensureCapacity(buf, bp);
-                    r = s.read(buf, bp, buf.length - bp);
-                }
-                return buf;
-            } finally {
-                try {
-                    s.close();
-                } catch (IOException e) {
-                    /* Ignore any errors, as this stream may have already
-                     * thrown a related exception which is the one that
-                     * should be reported.
-                     */
-                }
-            }
-        }
-        /*
-         * ensureCapacity will increase the buffer as needed, taking note that
-         * the new buffer will always be greater than the needed and never
-         * exactly equal to the needed size or bp. If equal then the read (above)
-         * will infinitely loop as buf.length - bp == 0.
-         */
-        private static byte[] ensureCapacity(byte[] buf, int needed) {
-            if (buf.length <= needed) {
-                byte[] old = buf;
-                buf = new byte[Integer.highestOneBit(needed) << 1];
-                System.arraycopy(old, 0, buf, 0, old.length);
-            }
-            return buf;
-        }
 
     /** We can only read a single class file at a time; this
      *  flag keeps track of when we are currently reading a class
@@ -3098,11 +2790,11 @@
 
     private class ProxyType extends Type {
 
-        private final byte[] content;
+        private final Name name;
 
-        public ProxyType(byte[] content) {
+        public ProxyType(int index) {
             super(syms.noSymbol, TypeMetadata.EMPTY);
-            this.content = content;
+            this.name = poolReader.getName(index);
         }
 
         @Override
@@ -3116,7 +2808,7 @@
         }
 
         public Type resolve() {
-            return sigToType(content, 0, content.length);
+            return name.map(ClassReader.this::sigToType);
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -29,9 +29,7 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
-import java.util.stream.Collectors;
 
 import javax.tools.JavaFileManager;
 import javax.tools.FileObject;
@@ -44,13 +42,10 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
-import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.file.PathFileObject;
-import com.sun.tools.javac.jvm.Pool.DynamicMethod;
-import com.sun.tools.javac.jvm.Pool.Method;
-import com.sun.tools.javac.jvm.Pool.MethodHandle;
-import com.sun.tools.javac.jvm.Pool.Variable;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.util.*;
@@ -121,7 +116,7 @@
      *  Sizes are increased when buffers get full.
      */
     static final int DATA_BUF_SIZE = 0x0fff0;
-    static final int POOL_BUF_SIZE = 0x1fff0;
+    static final int CLASS_BUF_SIZE = 0x1fff0;
 
     /** An output buffer for member info.
      */
@@ -129,25 +124,11 @@
 
     /** An output buffer for the constant pool.
      */
-    ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
-
-    /** The constant pool.
-     */
-    Pool pool;
-
-    /** The inner classes to be written, as a set.
-     */
-    Set<ClassSymbol> innerClasses;
+    ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 
-    /** The inner classes to be written, as a queue where
-     *  enclosing classes come first.
+    /** The constant pool writer.
      */
-    ListBuffer<ClassSymbol> innerClassesQueue;
-
-    /** The bootstrap methods to be written in the corresponding class attribute
-     *  (one for each invokedynamic)
-     */
-    Map<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> bootstrapMethods;
+    final PoolWriter poolWriter;
 
     /** The log to use for verbose output.
      */
@@ -159,9 +140,6 @@
     /** Access to files. */
     private final JavaFileManager fileManager;
 
-    /** Sole signature generator */
-    private final CWSignatureGenerator signatureGen;
-
     /** The tags and constants used in compressed stackmap. */
     static final int SAME_FRAME_SIZE = 64;
     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
@@ -191,7 +169,7 @@
         types = Types.instance(context);
         check = Check.instance(context);
         fileManager = context.get(JavaFileManager.class);
-        signatureGen = new CWSignatureGenerator(types);
+        poolWriter = Gen.instance(context).poolWriter;
 
         verbose        = options.isSet(VERBOSE);
         genCrt         = options.isSet(XJCOV);
@@ -272,108 +250,17 @@
         buf.elems[adr+3] = (byte)((x      ) & 0xFF);
     }
 
-    /**
-     * Signature Generation
-     */
-    private class CWSignatureGenerator extends Types.SignatureGenerator {
-
-        /**
-         * An output buffer for type signatures.
-         */
-        ByteBuffer sigbuf = new ByteBuffer();
-
-        CWSignatureGenerator(Types types) {
-            super(types);
-        }
-
-        /**
-         * Assemble signature of given type in string buffer.
-         * Check for uninitialized types before calling the general case.
-         */
-        @Override
-        public void assembleSig(Type type) {
-            switch (type.getTag()) {
-                case UNINITIALIZED_THIS:
-                case UNINITIALIZED_OBJECT:
-                    // we don't yet have a spec for uninitialized types in the
-                    // local variable table
-                    assembleSig(types.erasure(((UninitializedType)type).qtype));
-                    break;
-                default:
-                    super.assembleSig(type);
-            }
-        }
-
-        @Override
-        protected void append(char ch) {
-            sigbuf.appendByte(ch);
-        }
-
-        @Override
-        protected void append(byte[] ba) {
-            sigbuf.appendBytes(ba);
-        }
-
-        @Override
-        protected void append(Name name) {
-            sigbuf.appendName(name);
-        }
-
-        @Override
-        protected void classReference(ClassSymbol c) {
-            enterInner(c);
-        }
-
-        private void reset() {
-            sigbuf.reset();
-        }
-
-        private Name toName() {
-            return sigbuf.toName(names);
-        }
-
-        private boolean isEmpty() {
-            return sigbuf.length == 0;
-        }
-    }
-
-    /**
-     * Return signature of given type
-     */
-    Name typeSig(Type type) {
-        Assert.check(signatureGen.isEmpty());
-        //- System.out.println(" ? " + type);
-        signatureGen.assembleSig(type);
-        Name n = signatureGen.toName();
-        signatureGen.reset();
-        //- System.out.println("   " + n);
-        return n;
-    }
-
-    /** Given a type t, return the extended class name of its erasure in
-     *  external representation.
-     */
-    public Name xClassName(Type t) {
-        if (t.hasTag(CLASS)) {
-            return names.fromUtf(externalize(t.tsym.flatName()));
-        } else if (t.hasTag(ARRAY)) {
-            return typeSig(types.erasure(t));
-        } else {
-            throw new AssertionError("xClassName expects class or array type, got " + t);
-        }
-    }
-
 /******************************************************************
  * Writing the Constant Pool
  ******************************************************************/
 
     /** Thrown when the constant pool is over full.
      */
-    public static class PoolOverflow extends Exception {
+    public static class PoolOverflow extends RuntimeException {
         private static final long serialVersionUID = 0;
         public PoolOverflow() {}
     }
-    public static class StringOverflow extends Exception {
+    public static class StringOverflow extends RuntimeException {
         private static final long serialVersionUID = 0;
         public final String value;
         public StringOverflow(String s) {
@@ -381,137 +268,6 @@
         }
     }
 
-    /** Write constant pool to pool buffer.
-     *  Note: during writing, constant pool
-     *  might grow since some parts of constants still need to be entered.
-     */
-    void writePool(Pool pool) throws PoolOverflow, StringOverflow {
-        int poolCountIdx = poolbuf.length;
-        poolbuf.appendChar(0);
-        int i = 1;
-        while (i < pool.pp) {
-            Object value = pool.pool[i];
-            Assert.checkNonNull(value);
-            if (value instanceof Method || value instanceof Variable)
-                value = ((DelegatedSymbol)value).getUnderlyingSymbol();
-
-            if (value instanceof MethodSymbol) {
-                MethodSymbol m = (MethodSymbol)value;
-                if (!m.isDynamic()) {
-                    poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
-                              ? CONSTANT_InterfaceMethodref
-                              : CONSTANT_Methodref);
-                    poolbuf.appendChar(pool.put(m.owner));
-                    poolbuf.appendChar(pool.put(nameType(m)));
-                } else {
-                    //invokedynamic
-                    DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
-                    MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
-                    DynamicMethod.BootstrapMethodsKey key = new DynamicMethod.BootstrapMethodsKey(dynSym, types);
-
-                    // Figure out the index for existing BSM; create a new BSM if no key
-                    DynamicMethod.BootstrapMethodsValue val = bootstrapMethods.get(key);
-                    if (val == null) {
-                        int index = bootstrapMethods.size();
-                        val = new DynamicMethod.BootstrapMethodsValue(handle, index);
-                        bootstrapMethods.put(key, val);
-                    }
-
-                    //init cp entries
-                    pool.put(names.BootstrapMethods);
-                    pool.put(handle);
-                    for (Object staticArg : dynSym.staticArgs) {
-                        pool.put(staticArg);
-                    }
-                    poolbuf.appendByte(CONSTANT_InvokeDynamic);
-                    poolbuf.appendChar(val.index);
-                    poolbuf.appendChar(pool.put(nameType(dynSym)));
-                }
-            } else if (value instanceof VarSymbol) {
-                VarSymbol v = (VarSymbol)value;
-                poolbuf.appendByte(CONSTANT_Fieldref);
-                poolbuf.appendChar(pool.put(v.owner));
-                poolbuf.appendChar(pool.put(nameType(v)));
-            } else if (value instanceof Name) {
-                poolbuf.appendByte(CONSTANT_Utf8);
-                byte[] bs = ((Name)value).toUtf();
-                poolbuf.appendChar(bs.length);
-                poolbuf.appendBytes(bs, 0, bs.length);
-                if (bs.length > Pool.MAX_STRING_LENGTH)
-                    throw new StringOverflow(value.toString());
-            } else if (value instanceof ClassSymbol) {
-                ClassSymbol c = (ClassSymbol)value;
-                if (c.owner.kind == TYP) pool.put(c.owner);
-                poolbuf.appendByte(CONSTANT_Class);
-                if (c.type.hasTag(ARRAY)) {
-                    poolbuf.appendChar(pool.put(typeSig(c.type)));
-                } else {
-                    poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
-                    enterInner(c);
-                }
-            } else if (value instanceof NameAndType) {
-                NameAndType nt = (NameAndType)value;
-                poolbuf.appendByte(CONSTANT_NameandType);
-                poolbuf.appendChar(pool.put(nt.name));
-                poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
-            } else if (value instanceof Integer) {
-                poolbuf.appendByte(CONSTANT_Integer);
-                poolbuf.appendInt(((Integer)value).intValue());
-            } else if (value instanceof Long) {
-                poolbuf.appendByte(CONSTANT_Long);
-                poolbuf.appendLong(((Long)value).longValue());
-                i++;
-            } else if (value instanceof Float) {
-                poolbuf.appendByte(CONSTANT_Float);
-                poolbuf.appendFloat(((Float)value).floatValue());
-            } else if (value instanceof Double) {
-                poolbuf.appendByte(CONSTANT_Double);
-                poolbuf.appendDouble(((Double)value).doubleValue());
-                i++;
-            } else if (value instanceof String) {
-                poolbuf.appendByte(CONSTANT_String);
-                poolbuf.appendChar(pool.put(names.fromString((String)value)));
-            } else if (value instanceof UniqueType) {
-                Type type = ((UniqueType)value).type;
-                if (type.hasTag(METHOD)) {
-                    poolbuf.appendByte(CONSTANT_MethodType);
-                    poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
-                } else {
-                    Assert.check(type.hasTag(ARRAY));
-                    poolbuf.appendByte(CONSTANT_Class);
-                    poolbuf.appendChar(pool.put(xClassName(type)));
-                }
-            } else if (value instanceof MethodHandle) {
-                MethodHandle ref = (MethodHandle)value;
-                poolbuf.appendByte(CONSTANT_MethodHandle);
-                poolbuf.appendByte(ref.refKind);
-                poolbuf.appendChar(pool.put(ref.refSym));
-            } else if (value instanceof ModuleSymbol) {
-                ModuleSymbol m = (ModuleSymbol)value;
-                poolbuf.appendByte(CONSTANT_Module);
-                poolbuf.appendChar(pool.put(m.name));
-            } else if (value instanceof PackageSymbol) {
-                PackageSymbol m = (PackageSymbol)value;
-                poolbuf.appendByte(CONSTANT_Package);
-                poolbuf.appendChar(pool.put(names.fromUtf(externalize(m.fullname))));
-            } else {
-                Assert.error("writePool " + value);
-            }
-            i++;
-        }
-        if (pool.pp > Pool.MAX_ENTRIES)
-            throw new PoolOverflow();
-        putChar(poolbuf, poolCountIdx, pool.pp);
-    }
-
-    /** Given a symbol, return its name-and-type.
-     */
-    NameAndType nameType(Symbol sym) {
-        return new NameAndType(sym.name, sym.externalType(types), types);
-        // the NameAndType is generated from a symbol reference, and the
-        // adjustment of adding an additional this$n parameter needs to be made.
-    }
-
 /******************************************************************
  * Writing Attributes
  ******************************************************************/
@@ -520,7 +276,8 @@
      *  position past attribute length index.
      */
     int writeAttr(Name attrName) {
-        databuf.appendChar(pool.put(attrName));
+        int index = poolWriter.putName(attrName);
+        databuf.appendChar(index);
         databuf.appendInt(0);
         return databuf.length;
     }
@@ -567,8 +324,8 @@
              || c.owner.kind != MTH) // or member init
             ? null
             : (MethodSymbol)c.owner;
-        databuf.appendChar(pool.put(enclClass));
-        databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner)));
+        databuf.appendChar(poolWriter.putClass(enclClass));
+        databuf.appendChar(enclMethod == null ? 0 : poolWriter.putNameAndType(c.owner));
         endAttr(alenIdx);
         return 1;
     }
@@ -594,11 +351,11 @@
         if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
             (flags & ANONCONSTR) == 0 &&
             (!types.isSameType(sym.type, sym.erasure(types)) ||
-             signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
+             poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
             // note that a local class with captured variables
             // will get a signature attribute
             int alenIdx = writeAttr(names.Signature);
-            databuf.appendChar(pool.put(typeSig(sym.type)));
+            databuf.appendChar(poolWriter.putSignature(sym));
             endAttr(alenIdx);
             acount++;
         }
@@ -621,7 +378,7 @@
                 final int flags =
                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
                     ((int) m.flags() & SYNTHETIC);
-                databuf.appendChar(pool.put(s.name));
+                databuf.appendChar(poolWriter.putName(s.name));
                 databuf.appendChar(flags);
             }
             // Now write the real parameters
@@ -629,7 +386,7 @@
                 final int flags =
                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
                     ((int) m.flags() & SYNTHETIC);
-                databuf.appendChar(pool.put(s.name));
+                databuf.appendChar(poolWriter.putName(s.name));
                 databuf.appendChar(flags);
             }
             // Now write the captured locals
@@ -637,7 +394,7 @@
                 final int flags =
                     ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
                     ((int) m.flags() & SYNTHETIC);
-                databuf.appendChar(pool.put(s.name));
+                databuf.appendChar(poolWriter.putName(s.name));
                 databuf.appendChar(flags);
             }
             endAttr(attrIndex);
@@ -803,50 +560,51 @@
      */
     class AttributeWriter implements Attribute.Visitor {
         public void visitConstant(Attribute.Constant _value) {
-            Object value = _value.value;
-            switch (_value.type.getTag()) {
-            case BYTE:
-                databuf.appendByte('B');
-                break;
-            case CHAR:
-                databuf.appendByte('C');
-                break;
-            case SHORT:
-                databuf.appendByte('S');
-                break;
-            case INT:
-                databuf.appendByte('I');
-                break;
-            case LONG:
-                databuf.appendByte('J');
-                break;
-            case FLOAT:
-                databuf.appendByte('F');
-                break;
-            case DOUBLE:
-                databuf.appendByte('D');
-                break;
-            case BOOLEAN:
-                databuf.appendByte('Z');
-                break;
-            case CLASS:
-                Assert.check(value instanceof String);
+            if (_value.type.getTag() == CLASS) {
+                Assert.check(_value.value instanceof String);
+                String s = (String)_value.value;
                 databuf.appendByte('s');
-                value = names.fromString(value.toString()); // CONSTANT_Utf8
-                break;
-            default:
-                throw new AssertionError(_value.type);
+                databuf.appendChar(poolWriter.putName(names.fromString(s)));
+            } else {
+                switch (_value.type.getTag()) {
+                    case BYTE:
+                        databuf.appendByte('B');
+                        break;
+                    case CHAR:
+                        databuf.appendByte('C');
+                        break;
+                    case SHORT:
+                        databuf.appendByte('S');
+                        break;
+                    case INT:
+                        databuf.appendByte('I');
+                        break;
+                    case LONG:
+                        databuf.appendByte('J');
+                        break;
+                    case FLOAT:
+                        databuf.appendByte('F');
+                        break;
+                    case DOUBLE:
+                        databuf.appendByte('D');
+                        break;
+                    case BOOLEAN:
+                        databuf.appendByte('Z');
+                        break;
+                    default:
+                        throw new AssertionError(_value.type);
+                }
+                databuf.appendChar(poolWriter.putConstant(_value.value));
             }
-            databuf.appendChar(pool.put(value));
         }
         public void visitEnum(Attribute.Enum e) {
             databuf.appendByte('e');
-            databuf.appendChar(pool.put(typeSig(e.value.type)));
-            databuf.appendChar(pool.put(e.value.name));
+            databuf.appendChar(poolWriter.putDescriptor(e.value.type));
+            databuf.appendChar(poolWriter.putName(e.value.name));
         }
         public void visitClass(Attribute.Class clazz) {
             databuf.appendByte('c');
-            databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
+            databuf.appendChar(poolWriter.putDescriptor(clazz.classType));
         }
         public void visitCompound(Attribute.Compound compound) {
             databuf.appendByte('@');
@@ -867,10 +625,10 @@
 
     /** Write a compound attribute excluding the '@' marker. */
     void writeCompoundAttribute(Attribute.Compound c) {
-        databuf.appendChar(pool.put(typeSig(c.type)));
+        databuf.appendChar(poolWriter.putDescriptor(c.type));
         databuf.appendChar(c.values.length());
         for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
-            databuf.appendChar(pool.put(p.fst.name));
+            databuf.appendChar(poolWriter.putName(p.fst.name));
             p.snd.accept(awriter);
         }
     }
@@ -974,9 +732,9 @@
 
         int alenIdx = writeAttr(names.Module);
 
-        databuf.appendChar(pool.put(m));
+        databuf.appendChar(poolWriter.putModule(m));
         databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
-        databuf.appendChar(m.version != null ? pool.put(m.version) : 0);
+        databuf.appendChar(m.version != null ? poolWriter.putName(m.version) : 0);
 
         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
         for (RequiresDirective r: m.requires) {
@@ -985,22 +743,22 @@
         }
         databuf.appendChar(requires.size());
         for (RequiresDirective r: requires) {
-            databuf.appendChar(pool.put(r.module));
+            databuf.appendChar(poolWriter.putModule(r.module));
             databuf.appendChar(RequiresFlag.value(r.flags));
-            databuf.appendChar(r.module.version != null ? pool.put(r.module.version) : 0);
+            databuf.appendChar(r.module.version != null ? poolWriter.putName(r.module.version) : 0);
         }
 
         List<ExportsDirective> exports = m.exports;
         databuf.appendChar(exports.size());
         for (ExportsDirective e: exports) {
-            databuf.appendChar(pool.put(e.packge));
+            databuf.appendChar(poolWriter.putPackage(e.packge));
             databuf.appendChar(ExportsFlag.value(e.flags));
             if (e.modules == null) {
                 databuf.appendChar(0);
             } else {
                 databuf.appendChar(e.modules.size());
                 for (ModuleSymbol msym: e.modules) {
-                    databuf.appendChar(pool.put(msym));
+                    databuf.appendChar(poolWriter.putModule(msym));
                 }
             }
         }
@@ -1008,14 +766,14 @@
         List<OpensDirective> opens = m.opens;
         databuf.appendChar(opens.size());
         for (OpensDirective o: opens) {
-            databuf.appendChar(pool.put(o.packge));
+            databuf.appendChar(poolWriter.putPackage(o.packge));
             databuf.appendChar(OpensFlag.value(o.flags));
             if (o.modules == null) {
                 databuf.appendChar(0);
             } else {
                 databuf.appendChar(o.modules.size());
                 for (ModuleSymbol msym: o.modules) {
-                    databuf.appendChar(pool.put(msym));
+                    databuf.appendChar(poolWriter.putModule(msym));
                 }
             }
         }
@@ -1023,7 +781,7 @@
         List<UsesDirective> uses = m.uses;
         databuf.appendChar(uses.size());
         for (UsesDirective s: uses) {
-            databuf.appendChar(pool.put(s.service));
+            databuf.appendChar(poolWriter.putClass(s.service));
         }
 
         // temporary fix to merge repeated provides clause for same service;
@@ -1035,9 +793,9 @@
         }
         databuf.appendChar(mergedProvides.size());
         mergedProvides.forEach((srvc, impls) -> {
-            databuf.appendChar(pool.put(srvc));
+            databuf.appendChar(poolWriter.putClass(srvc));
             databuf.appendChar(impls.size());
-            impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
+            impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
         });
 
         endAttr(alenIdx);
@@ -1048,46 +806,12 @@
  * Writing Objects
  **********************************************************************/
 
-    /** Enter an inner class into the `innerClasses' set/queue.
-     */
-    void enterInner(ClassSymbol c) {
-        if (c.type.isCompound()) {
-            throw new AssertionError("Unexpected intersection type: " + c.type);
-        }
-        try {
-            c.complete();
-        } catch (CompletionFailure ex) {
-            System.err.println("error: " + c + ": " + ex.getMessage());
-            throw ex;
-        }
-        if (!c.type.hasTag(CLASS)) return; // arrays
-        if (pool != null && // pool might be null if called from xClassName
-            c.owner.enclClass() != null &&
-            (innerClasses == null || !innerClasses.contains(c))) {
-//          log.errWriter.println("enter inner " + c);//DEBUG
-            enterInner(c.owner.enclClass());
-            pool.put(c);
-            if (c.name != names.empty)
-                pool.put(c.name);
-            if (innerClasses == null) {
-                innerClasses = new HashSet<>();
-                innerClassesQueue = new ListBuffer<>();
-                pool.put(names.InnerClasses);
-            }
-            innerClasses.add(c);
-            innerClassesQueue.append(c);
-        }
-    }
-
     /** Write "inner classes" attribute.
      */
     void writeInnerClasses() {
         int alenIdx = writeAttr(names.InnerClasses);
-        databuf.appendChar(innerClassesQueue.length());
-        for (List<ClassSymbol> l = innerClassesQueue.toList();
-             l.nonEmpty();
-             l = l.tail) {
-            ClassSymbol inner = l.head;
+        databuf.appendChar(poolWriter.innerClasses.size());
+        for (ClassSymbol inner : poolWriter.innerClasses) {
             inner.markAbstractIfNeeded(types);
             char flags = (char) adjustFlags(inner.flags_field);
             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
@@ -1097,11 +821,11 @@
                 pw.println("INNERCLASS  " + inner.name);
                 pw.println("---" + flagNames(flags));
             }
-            databuf.appendChar(pool.get(inner));
+            databuf.appendChar(poolWriter.putClass(inner));
             databuf.appendChar(
-                inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0);
+                inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
             databuf.appendChar(
-                !inner.name.isEmpty() ? pool.get(inner.name) : 0);
+                !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
             databuf.appendChar(flags);
         }
         endAttr(alenIdx);
@@ -1111,14 +835,14 @@
      * Write NestMembers attribute (if needed)
      */
     int writeNestMembersIfNeeded(ClassSymbol csym) {
-        ListBuffer<Symbol> nested = new ListBuffer<>();
+        ListBuffer<ClassSymbol> nested = new ListBuffer<>();
         listNested(csym, nested);
-        Set<Symbol> nestedUnique = new LinkedHashSet<>(nested);
+        Set<ClassSymbol> nestedUnique = new LinkedHashSet<>(nested);
         if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
             int alenIdx = writeAttr(names.NestMembers);
             databuf.appendChar(nestedUnique.size());
-            for (Symbol s : nestedUnique) {
-                databuf.appendChar(pool.put(s));
+            for (ClassSymbol s : nestedUnique) {
+                databuf.appendChar(poolWriter.putClass(s));
             }
             endAttr(alenIdx);
             return 1;
@@ -1132,14 +856,14 @@
     int writeNestHostIfNeeded(ClassSymbol csym) {
         if (csym.owner.kind != PCK) {
             int alenIdx = writeAttr(names.NestHost);
-            databuf.appendChar(pool.put(csym.outermostClass()));
+            databuf.appendChar(poolWriter.putClass(csym.outermostClass()));
             endAttr(alenIdx);
             return 1;
         }
         return 0;
     }
 
-    private void listNested(Symbol sym, ListBuffer<Symbol> seen) {
+    private void listNested(Symbol sym, ListBuffer<ClassSymbol> seen) {
         if (sym.kind != TYP) return;
         ClassSymbol csym = (ClassSymbol)sym;
         if (csym.owner.kind != PCK) {
@@ -1161,17 +885,16 @@
      */
     void writeBootstrapMethods() {
         int alenIdx = writeAttr(names.BootstrapMethods);
-        databuf.appendChar(bootstrapMethods.size());
-        for (Map.Entry<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> entry : bootstrapMethods.entrySet()) {
-            DynamicMethod.BootstrapMethodsKey bsmKey = entry.getKey();
+        databuf.appendChar(poolWriter.bootstrapMethods.size());
+        for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {
             //write BSM handle
-            databuf.appendChar(pool.get(entry.getValue().mh));
-            Object[] uniqueArgs = bsmKey.getUniqueArgs();
+            databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
+            LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
             //write static args length
             databuf.appendChar(uniqueArgs.length);
             //write static args array
-            for (Object o : uniqueArgs) {
-                databuf.appendChar(pool.get(o));
+            for (LoadableConstant arg : uniqueArgs) {
+                databuf.appendChar(poolWriter.putConstant(arg));
             }
         }
         endAttr(alenIdx);
@@ -1187,13 +910,13 @@
             pw.println("FIELD  " + v.name);
             pw.println("---" + flagNames(v.flags()));
         }
-        databuf.appendChar(pool.put(v.name));
-        databuf.appendChar(pool.put(typeSig(v.erasure(types))));
+        databuf.appendChar(poolWriter.putName(v.name));
+        databuf.appendChar(poolWriter.putDescriptor(v));
         int acountIdx = beginAttrs();
         int acount = 0;
         if (v.getConstValue() != null) {
             int alenIdx = writeAttr(names.ConstantValue);
-            databuf.appendChar(pool.put(v.getConstValue()));
+            databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
             endAttr(alenIdx);
             acount++;
         }
@@ -1211,8 +934,8 @@
             pw.println("METHOD  " + m.name);
             pw.println("---" + flagNames(m.flags()));
         }
-        databuf.appendChar(pool.put(m.name));
-        databuf.appendChar(pool.put(typeSig(m.externalType(types))));
+        databuf.appendChar(poolWriter.putName(m.name));
+        databuf.appendChar(poolWriter.putDescriptor(m));
         int acountIdx = beginAttrs();
         int acount = 0;
         if (m.code != null) {
@@ -1227,7 +950,7 @@
             int alenIdx = writeAttr(names.Exceptions);
             databuf.appendChar(thrown.length());
             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
-                databuf.appendChar(pool.put(l.head.tsym));
+                databuf.appendChar(poolWriter.putClass(l.head));
             endAttr(alenIdx);
             acount++;
         }
@@ -1303,9 +1026,8 @@
                             && (r.start_pc + r.length) <= code.cp);
                     databuf.appendChar(r.length);
                     VarSymbol sym = var.sym;
-                    databuf.appendChar(pool.put(sym.name));
-                    Type vartype = sym.erasure(types);
-                    databuf.appendChar(pool.put(typeSig(vartype)));
+                    databuf.appendChar(poolWriter.putName(sym.name));
+                    databuf.appendChar(poolWriter.putDescriptor(sym));
                     databuf.appendChar(var.reg);
                     if (needsLocalVariableTypeEntry(var.sym.type)) {
                         nGenericVars++;
@@ -1329,8 +1051,8 @@
                         // write variable info
                         databuf.appendChar(r.start_pc);
                         databuf.appendChar(r.length);
-                        databuf.appendChar(pool.put(sym.name));
-                        databuf.appendChar(pool.put(typeSig(sym.type)));
+                        databuf.appendChar(poolWriter.putName(sym.name));
+                        databuf.appendChar(poolWriter.putSignature(sym));
                         databuf.appendChar(var.reg);
                         count++;
                     }
@@ -1457,14 +1179,10 @@
                 break;
             case CLASS:
             case ARRAY:
-                if (debugstackmap) System.out.print("object(" + t + ")");
-                databuf.appendByte(7);
-                databuf.appendChar(pool.put(t));
-                break;
             case TYPEVAR:
                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
                 databuf.appendByte(7);
-                databuf.appendChar(pool.put(types.erasure(t).tsym));
+                databuf.appendChar(poolWriter.putClass(types.erasure(t)));
                 break;
             case UNINITIALIZED_THIS:
                 if (debugstackmap) System.out.print("uninit_this");
@@ -1763,11 +1481,6 @@
         Assert.check((c.flags() & COMPOUND) == 0);
         databuf.reset();
         poolbuf.reset();
-        signatureGen.reset();
-        pool = c.pool;
-        innerClasses = null;
-        innerClassesQueue = null;
-        bootstrapMethods = new LinkedHashMap<>();
 
         Type supertype = types.supertype(c.type);
         List<Type> interfaces = types.interfaces(c.type);
@@ -1793,14 +1506,14 @@
 
         if (c.owner.kind == MDL) {
             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
-            databuf.appendChar(pool.put(new ClassSymbol(0, names.module_info, unnamed)));
+            databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
         } else {
-            databuf.appendChar(pool.put(c));
+            databuf.appendChar(poolWriter.putClass(c));
         }
-        databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
+        databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
         databuf.appendChar(interfaces.length());
         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
-            databuf.appendChar(pool.put(l.head.tsym));
+            databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
         int fieldsCount = 0;
         int methodsCount = 0;
         for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
@@ -1808,14 +1521,14 @@
             case VAR: fieldsCount++; break;
             case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
                       break;
-            case TYP: enterInner((ClassSymbol)sym); break;
+            case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
             default : Assert.error();
             }
         }
 
         if (c.trans_local != null) {
             for (ClassSymbol local : c.trans_local) {
-                enterInner(local);
+                poolWriter.enterInner(local);
             }
         }
 
@@ -1833,12 +1546,7 @@
             sigReq = l.head.allparams().length() != 0;
         if (sigReq) {
             int alenIdx = writeAttr(names.Signature);
-            if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams);
-            signatureGen.assembleSig(supertype);
-            for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
-                signatureGen.assembleSig(l.head);
-            databuf.appendChar(pool.put(signatureGen.toName()));
-            signatureGen.reset();
+            databuf.appendChar(poolWriter.putSignature(c));
             endAttr(alenIdx);
             acount++;
         }
@@ -1848,9 +1556,8 @@
             // WHM 6/29/1999: Strip file path prefix.  We do it here at
             // the last possible moment because the sourcefile may be used
             // elsewhere in error diagnostics. Fixes 4241573.
-            //databuf.appendChar(c.pool.put(c.sourcefile));
             String simpleName = PathFileObject.getSimpleName(c.sourcefile);
-            databuf.appendChar(c.pool.put(names.fromString(simpleName)));
+            databuf.appendChar(poolWriter.putName(names.fromString(simpleName)));
             endAttr(alenIdx);
             acount++;
         }
@@ -1858,12 +1565,12 @@
         if (genCrt) {
             // Append SourceID attribute
             int alenIdx = writeAttr(names.SourceID);
-            databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
+            databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
             endAttr(alenIdx);
             acount++;
             // Append CompilationID attribute
             alenIdx = writeAttr(names.CompilationID);
-            databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis()))));
+            databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
             endAttr(alenIdx);
             acount++;
         }
@@ -1893,24 +1600,24 @@
             }
         }
 
-        writePool(c.pool);
-
-        if (innerClasses != null) {
-            writeInnerClasses();
+        if (!poolWriter.bootstrapMethods.isEmpty()) {
+            writeBootstrapMethods();
             acount++;
         }
 
-        if (!bootstrapMethods.isEmpty()) {
-            writeBootstrapMethods();
+        if (!poolWriter.innerClasses.isEmpty()) {
+            writeInnerClasses();
             acount++;
         }
 
         endAttrs(acountIdx, acount);
 
-        poolbuf.appendBytes(databuf.elems, 0, databuf.length);
         out.write(poolbuf.elems, 0, poolbuf.length);
 
-        pool = c.pool = null; // to conserve space
+        poolWriter.writePool(out);
+        poolWriter.reset(); // to save space
+
+        out.write(databuf.elems, 0, databuf.length);
      }
 
     /**Allows subclasses to write additional class attributes
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Apr 19 08:00:42 2019 -0400
@@ -27,15 +27,27 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
-import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
+import java.util.function.ToIntBiFunction;
+import java.util.function.ToIntFunction;
+
 import static com.sun.tools.javac.code.TypeTag.BOT;
 import static com.sun.tools.javac.code.TypeTag.INT;
 import static com.sun.tools.javac.jvm.ByteCodes.*;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
+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;
 
@@ -72,6 +84,7 @@
 
     final Types types;
     final Symtab syms;
+    final PoolWriter poolWriter;
 
 /*---------- classfile fields: --------------- */
 
@@ -177,10 +190,6 @@
      */
     Position.LineMap lineMap;
 
-    /** The constant pool of the current class.
-     */
-    final Pool pool;
-
     final MethodSymbol meth;
 
     private int letExprStackPos = 0;
@@ -197,7 +206,7 @@
                 CRTable crt,
                 Symtab syms,
                 Types types,
-                Pool pool) {
+                PoolWriter poolWriter) {
         this.meth = meth;
         this.fatcode = fatcode;
         this.lineMap = lineMap;
@@ -206,6 +215,7 @@
         this.crt = crt;
         this.syms = syms;
         this.types = types;
+        this.poolWriter = poolWriter;
         this.debugCode = debugCode;
         this.stackMap = stackMap;
         switch (stackMap) {
@@ -218,7 +228,6 @@
         }
         state = new State();
         lvar = new LocalVar[20];
-        this.pool = pool;
     }
 
 
@@ -389,12 +398,13 @@
 
     /** Emit a ldc (or ldc_w) instruction, taking into account operand size
     */
-    public void emitLdc(int od) {
+    public void emitLdc(LoadableConstant constant) {
+        int od = poolWriter.putConstant(constant);
         if (od <= 255) {
-            emitop1(ldc1, od);
+            emitop1(ldc1, od, constant);
         }
         else {
-            emitop2(ldc2, od);
+            emitop2(ldc2, od, constant);
         }
     }
 
@@ -431,11 +441,11 @@
 
     /** Emit an invokeinterface instruction.
      */
-    public void emitInvokeinterface(int meth, Type mtype) {
+    public void emitInvokeinterface(Symbol member, Type mtype) {
         int argsize = width(mtype.getParameterTypes());
         emitop(invokeinterface);
         if (!alive) return;
-        emit2(meth);
+        emit2(poolWriter.putMember(member));
         emit1(argsize + 1);
         emit1(0);
         state.pop(argsize + 1);
@@ -444,14 +454,13 @@
 
     /** Emit an invokespecial instruction.
      */
-    public void emitInvokespecial(int meth, Type mtype) {
+    public void emitInvokespecial(Symbol member, Type mtype) {
         int argsize = width(mtype.getParameterTypes());
         emitop(invokespecial);
         if (!alive) return;
-        emit2(meth);
-        Symbol sym = (Symbol)pool.pool[meth];
+        emit2(poolWriter.putMember(member));
         state.pop(argsize);
-        if (sym.isConstructor())
+        if (member.isConstructor())
             state.markInitialized((UninitializedType)state.peek());
         state.pop(1);
         state.push(mtype.getReturnType());
@@ -459,33 +468,33 @@
 
     /** Emit an invokestatic instruction.
      */
-    public void emitInvokestatic(int meth, Type mtype) {
+    public void emitInvokestatic(Symbol member, Type mtype) {
         int argsize = width(mtype.getParameterTypes());
         emitop(invokestatic);
         if (!alive) return;
-        emit2(meth);
+        emit2(poolWriter.putMember(member));
         state.pop(argsize);
         state.push(mtype.getReturnType());
     }
 
     /** Emit an invokevirtual instruction.
      */
-    public void emitInvokevirtual(int meth, Type mtype) {
+    public void emitInvokevirtual(Symbol member, Type mtype) {
         int argsize = width(mtype.getParameterTypes());
         emitop(invokevirtual);
         if (!alive) return;
-        emit2(meth);
+        emit2(poolWriter.putMember(member));
         state.pop(argsize + 1);
         state.push(mtype.getReturnType());
     }
 
     /** Emit an invokedynamic instruction.
      */
-    public void emitInvokedynamic(int desc, Type mtype) {
+    public void emitInvokedynamic(DynamicMethodSymbol dynMember, Type mtype) {
         int argsize = width(mtype.getParameterTypes());
         emitop(invokedynamic);
         if (!alive) return;
-        emit2(desc);
+        emit2(poolWriter.putDynamic(dynMember));
         emit2(0);
         state.pop(argsize);
         state.push(mtype.getReturnType());
@@ -896,6 +905,10 @@
     /** Emit an opcode with a one-byte operand field.
      */
     public void emitop1(int op, int od) {
+        emitop1(op, od, null);
+    }
+
+    public void emitop1(int op, int od, PoolConstant data) {
         emitop(op);
         if (!alive) return;
         emit1(od);
@@ -904,7 +917,7 @@
             state.push(syms.intType);
             break;
         case ldc1:
-            state.push(typeForPool(pool.pool[od]));
+            state.push(types.constantType((LoadableConstant)data));
             break;
         default:
             throw new AssertionError(mnem(op));
@@ -912,25 +925,6 @@
         postop();
     }
 
-    /** The type of a constant pool entry. */
-    private Type typeForPool(Object o) {
-        if (o instanceof Integer) return syms.intType;
-        if (o instanceof Float) return syms.floatType;
-        if (o instanceof String) return syms.stringType;
-        if (o instanceof Long) return syms.longType;
-        if (o instanceof Double) return syms.doubleType;
-        if (o instanceof ClassSymbol) return syms.classType;
-        if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
-        if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
-        if (o instanceof Type) {
-            Type ty = (Type) o;
-
-            if (ty instanceof Type.ArrayType) return syms.classType;
-            if (ty instanceof Type.MethodType) return syms.methodTypeType;
-        }
-        throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
-    }
-
     /** Emit an opcode with a one-byte operand field;
      *  widen if field does not fit in a byte.
      */
@@ -1003,29 +997,31 @@
 
     /** Emit an opcode with a two-byte operand field.
      */
+    public <P extends PoolConstant> void emitop2(int op, P constant, ToIntBiFunction<PoolWriter, P> poolFunc) {
+        int od = poolFunc.applyAsInt(poolWriter, constant);
+        emitop2(op, od, constant);
+    }
+
     public void emitop2(int op, int od) {
+        emitop2(op, od, null);
+    }
+
+    public void emitop2(int op, int od, PoolConstant data) {
         emitop(op);
         if (!alive) return;
         emit2(od);
         switch (op) {
         case getstatic:
-            state.push(((Symbol)(pool.pool[od])).erasure(types));
+            state.push(((Symbol)data).erasure(types));
             break;
         case putstatic:
-            state.pop(((Symbol)(pool.pool[od])).erasure(types));
+            state.pop(((Symbol)data).erasure(types));
             break;
-        case new_:
-            Symbol sym;
-            if (pool.pool[od] instanceof UniqueType) {
-                // Required by change in Gen.makeRef to allow
-                // annotated types.
-                // TODO: is this needed anywhere else?
-                sym = ((UniqueType)(pool.pool[od])).type.tsym;
-            } else {
-                sym = (Symbol)(pool.pool[od]);
-            }
-            state.push(uninitializedObject(sym.erasure(types), cp-3));
+        case new_: {
+            Type t = (Type)data;
+            state.push(uninitializedObject(t.tsym.erasure(types), cp-3));
             break;
+        }
         case sipush:
             state.push(syms.intType);
             break;
@@ -1053,30 +1049,27 @@
             markDead();
             break;
         case putfield:
-            state.pop(((Symbol)(pool.pool[od])).erasure(types));
+            state.pop(((Symbol)data).erasure(types));
             state.pop(1); // object ref
             break;
         case getfield:
             state.pop(1); // object ref
-            state.push(((Symbol)(pool.pool[od])).erasure(types));
+            state.push(((Symbol)data).erasure(types));
             break;
         case checkcast: {
             state.pop(1); // object ref
-            Object o = pool.pool[od];
-            Type t = (o instanceof Symbol)
-                ? ((Symbol)o).erasure(types)
-                : types.erasure((((UniqueType)o).type));
+            Type t = types.erasure((Type)data);
             state.push(t);
             break; }
         case ldc2w:
-            state.push(typeForPool(pool.pool[od]));
+            state.push(types.constantType((LoadableConstant)data));
             break;
         case instanceof_:
             state.pop(1);
             state.push(syms.intType);
             break;
         case ldc2:
-            state.push(typeForPool(pool.pool[od]));
+            state.push(types.constantType((LoadableConstant)data));
             break;
         case jsr:
             break;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Apr 19 08:00:42 2019 -0400
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.jvm;
 
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.tree.TreeInfo.PosKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -88,9 +89,9 @@
         return instance;
     }
 
-    /** Constant pool, reset by genClass.
+    /** Constant pool writer, set by genClass.
      */
-    private final Pool pool;
+    final PoolWriter poolWriter;
 
     protected Gen(Context context) {
         context.put(genKey, this);
@@ -121,7 +122,7 @@
         genCrt = options.isSet(XJCOV);
         debugCode = options.isSet("debug.code");
         disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
-        pool = new Pool(types);
+        poolWriter = new PoolWriter(types, names);
 
         // ignore cldc because we cannot have both stackmap formats
         this.stackMap = StackMapFormat.JSR202;
@@ -252,17 +253,17 @@
      *  @param type   The type for which a reference is inserted.
      */
     int makeRef(DiagnosticPosition pos, Type type) {
-        checkDimension(pos, type);
-        if (type.isAnnotated()) {
-            return pool.put((Object)type);
-        } else {
-            return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
-        }
+        return poolWriter.putClass(checkDimension(pos, type));
     }
 
     /** Check if the given type is an array with too many dimensions.
      */
-    private void checkDimension(DiagnosticPosition pos, Type t) {
+    private Type checkDimension(DiagnosticPosition pos, Type t) {
+        checkDimensionInternal(pos, t);
+        return t;
+    }
+
+    private void checkDimensionInternal(DiagnosticPosition pos, Type t) {
         switch (t.getTag()) {
         case METHOD:
             checkDimension(pos, t.getReturnType());
@@ -516,7 +517,7 @@
         if (nerrs != 0 || // only complain about a long string once
             constValue == null ||
             !(constValue instanceof String) ||
-            ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
+            ((String)constValue).length() < PoolWriter.MAX_STRING_LENGTH)
             return;
         log.error(pos, Errors.LimitString);
         nerrs++;
@@ -806,7 +807,7 @@
         @Override
         public void visitIdent(JCIdent tree) {
             if (tree.sym.owner instanceof ClassSymbol) {
-                pool.put(tree.sym.owner);
+                poolWriter.putClass((ClassSymbol)tree.sym.owner);
             }
         }
 
@@ -1007,8 +1008,8 @@
                                                : null,
                                         syms,
                                         types,
-                                        pool);
-            items = new Items(pool, code, syms, types);
+                                        poolWriter);
+            items = new Items(poolWriter, code, syms, types);
             if (code.debugCode) {
                 System.err.println(meth + " for body " + tree);
             }
@@ -1886,7 +1887,7 @@
         Assert.check(tree.encl == null && tree.def == null);
         setTypeAnnotationPositions(tree.pos);
 
-        code.emitop2(new_, makeRef(tree.pos(), tree.type));
+        code.emitop2(new_, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
         code.emitop0(dup);
 
         // Generate code for all arguments, where the expected types are
@@ -2162,7 +2163,7 @@
         if (!tree.clazz.type.isPrimitive() &&
            !types.isSameType(tree.expr.type, tree.clazz.type) &&
            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
-            code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
+            code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);
         }
     }
 
@@ -2221,7 +2222,7 @@
         Symbol sym = tree.sym;
 
         if (tree.name == names._class) {
-            code.emitLdc(makeRef(tree.pos(), tree.selected.type));
+            code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
             result = items.makeStackItem(pt);
             return;
        }
@@ -2305,7 +2306,7 @@
         code.endScopes(limit);
     }
 
-    private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
+    private void generateReferencesToPrunedTree(ClassSymbol classSymbol) {
         List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
         if (prunedInfo != null) {
             for (JCTree prunedTree: prunedInfo) {
@@ -2331,12 +2332,10 @@
             ClassSymbol c = cdef.sym;
             this.toplevel = env.toplevel;
             this.endPosTable = toplevel.endPositions;
-            c.pool = pool;
-            pool.reset();
             /* method normalizeDefs() can add references to external classes into the constant pool
              */
             cdef.defs = normalizeDefs(cdef.defs, c);
-            generateReferencesToPrunedTree(c, pool);
+            generateReferencesToPrunedTree(c);
             Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
             localEnv.toplevel = env.toplevel;
             localEnv.enclClass = cdef;
@@ -2344,7 +2343,7 @@
             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
                 genDef(l.head, localEnv);
             }
-            if (pool.numEntries() > Pool.MAX_ENTRIES) {
+            if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
                 log.error(cdef.pos(), Errors.LimitPool);
                 nerrs++;
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Apr 19 08:00:42 2019 -0400
@@ -29,6 +29,8 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.jvm.Code.*;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.Assert;
 
@@ -50,9 +52,9 @@
  */
 public class Items {
 
-    /** The current constant pool.
+    /** The current constant pool writer.
      */
-    Pool pool;
+    PoolWriter poolWriter;
 
     /** The current code buffer.
      */
@@ -72,9 +74,9 @@
     private final Item superItem;
     private final Item[] stackItem = new Item[TypeCodeCount];
 
-    public Items(Pool pool, Code code, Symtab syms, Types types) {
+    public Items(PoolWriter poolWriter, Code code, Symtab syms, Types types) {
         this.code = code;
-        this.pool = pool;
+        this.poolWriter = poolWriter;
         this.types = types;
         voidItem = new Item(VOIDcode) {
                 public String toString() { return "void"; }
@@ -444,18 +446,18 @@
         }
 
         Item load() {
-            code.emitop2(getstatic, pool.put(member));
+            code.emitop2(getstatic, member, PoolWriter::putMember);
             return stackItem[typecode];
         }
 
         void store() {
-            code.emitop2(putstatic, pool.put(member));
+            code.emitop2(putstatic, member, PoolWriter::putMember);
         }
 
         Item invoke() {
             MethodType mtype = (MethodType)member.erasure(types);
             int rescode = Code.typecode(mtype.restype);
-            code.emitInvokestatic(pool.put(member), mtype);
+            code.emitInvokestatic(member, mtype);
             return stackItem[rescode];
         }
 
@@ -484,7 +486,7 @@
             // assert target.hasNativeInvokeDynamic();
             MethodType mtype = (MethodType)member.erasure(types);
             int rescode = Code.typecode(mtype.restype);
-            code.emitInvokedynamic(pool.put(member), mtype);
+            code.emitInvokedynamic((DynamicMethodSymbol)member, mtype);
             return stackItem[rescode];
         }
 
@@ -512,23 +514,23 @@
         }
 
         Item load() {
-            code.emitop2(getfield, pool.put(member));
+            code.emitop2(getfield, member, PoolWriter::putMember);
             return stackItem[typecode];
         }
 
         void store() {
-            code.emitop2(putfield, pool.put(member));
+            code.emitop2(putfield, member, PoolWriter::putMember);
         }
 
         Item invoke() {
             MethodType mtype = (MethodType)member.externalType(types);
             int rescode = Code.typecode(mtype.restype);
             if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
-                code.emitInvokeinterface(pool.put(member), mtype);
+                code.emitInvokeinterface(member, mtype);
             } else if (nonvirtual) {
-                code.emitInvokespecial(pool.put(member), mtype);
+                code.emitInvokespecial(member, mtype);
             } else {
-                code.emitInvokevirtual(pool.put(member), mtype);
+                code.emitInvokevirtual(member, mtype);
             }
             return stackItem[rescode];
         }
@@ -560,26 +562,50 @@
 
         /** The literal's value.
          */
-        Object value;
+        final LoadableConstant value;
 
         ImmediateItem(Type type, Object value) {
             super(Code.typecode(type));
-            this.value = value;
+            switch (typecode) {
+                case BYTEcode:
+                case SHORTcode:
+                case CHARcode:
+                case INTcode:
+                    this.value = LoadableConstant.Int((int)value);
+                    break;
+                case LONGcode:
+                    this.value = LoadableConstant.Long((long)value);
+                    break;
+                case FLOATcode:
+                    this.value = LoadableConstant.Float((float)value);
+                    break;
+                case DOUBLEcode:
+                    this.value = LoadableConstant.Double((double)value);
+                    break;
+                case OBJECTcode:
+                    this.value = LoadableConstant.String((String)value);
+                    break;
+                default:
+                    throw new UnsupportedOperationException("unsupported tag: " + typecode);
+            }
         }
 
         private void ldc() {
-            int idx = pool.put(value);
             if (typecode == LONGcode || typecode == DOUBLEcode) {
-                code.emitop2(ldc2w, idx);
+                code.emitop2(ldc2w, value, PoolWriter::putConstant);
             } else {
-                code.emitLdc(idx);
+                code.emitLdc(value);
             }
         }
 
+        private Number numericValue() {
+            return (Number)((BasicConstant)value).data;
+        }
+
         Item load() {
             switch (typecode) {
             case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
-                int ival = ((Number)value).intValue();
+                int ival = numericValue().intValue();
                 if (-1 <= ival && ival <= 5)
                     code.emitop0(iconst_0 + ival);
                 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
@@ -590,14 +616,14 @@
                     ldc();
                 break;
             case LONGcode:
-                long lval = ((Number)value).longValue();
+                long lval = numericValue().longValue();
                 if (lval == 0 || lval == 1)
                     code.emitop0(lconst_0 + (int)lval);
                 else
                     ldc();
                 break;
             case FLOATcode:
-                float fval = ((Number)value).floatValue();
+                float fval = numericValue().floatValue();
                 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
                     code.emitop0(fconst_0 + (int)fval);
                 else {
@@ -605,7 +631,7 @@
                 }
                 break;
             case DOUBLEcode:
-                double dval = ((Number)value).doubleValue();
+                double dval = numericValue().doubleValue();
                 if (isPosZero(dval) || dval == 1.0)
                     code.emitop0(dconst_0 + (int)dval);
                 else
@@ -632,7 +658,7 @@
             }
 
         CondItem mkCond() {
-            int ival = ((Number)value).intValue();
+            int ival = numericValue().intValue();
             return makeCondItem(ival != 0 ? goto_ : dontgoto);
         }
 
@@ -647,31 +673,31 @@
                     else
                         return new ImmediateItem(
                             syms.intType,
-                            ((Number)value).intValue());
+                            numericValue().intValue());
                 case LONGcode:
                     return new ImmediateItem(
                         syms.longType,
-                        ((Number)value).longValue());
+                            numericValue().longValue());
                 case FLOATcode:
                     return new ImmediateItem(
                         syms.floatType,
-                        ((Number)value).floatValue());
+                        numericValue().floatValue());
                 case DOUBLEcode:
                     return new ImmediateItem(
                         syms.doubleType,
-                        ((Number)value).doubleValue());
+                        numericValue().doubleValue());
                 case BYTEcode:
                     return new ImmediateItem(
                         syms.byteType,
-                        (int)(byte)((Number)value).intValue());
+                        (int)(byte)numericValue().intValue());
                 case CHARcode:
                     return new ImmediateItem(
                         syms.charType,
-                        (int)(char)((Number)value).intValue());
+                        (int)(char)numericValue().intValue());
                 case SHORTcode:
                     return new ImmediateItem(
                         syms.shortType,
-                        (int)(short)((Number)value).intValue());
+                        (int)(short)numericValue().intValue());
                 default:
                     return super.coerce(targetcode);
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java	Fri Apr 19 08:00:42 2019 -0400
@@ -24,6 +24,9 @@
  */
 package com.sun.tools.javac.jvm;
 
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.Name.NameMapper;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
@@ -55,16 +58,15 @@
 
     /** The buffer containing the currently read class file.
      */
-    private byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+    private ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
 
     /** The current input pointer.
      */
     private int bp;
 
-    /** For every constant pool entry, an index into buf where the
-     *  defining section of the entry is found.
+    /** The constant pool reader.
      */
-    private int[] poolIdx;
+    private PoolReader reader;
 
     public ModuleNameReader() {
     }
@@ -83,7 +85,8 @@
 
     public String readModuleName(InputStream in) throws IOException, BadClassFile {
         bp = 0;
-        buf = readInputStream(buf, in);
+        buf.reset();
+        buf.appendStream(in);
 
         int magic = nextInt();
         if (magic != JAVA_MAGIC)
@@ -94,7 +97,8 @@
         if (majorVersion < 53)
             throw new BadClassFile("bad major version number for module: " + majorVersion);
 
-        indexPool();
+        reader = new PoolReader(buf);
+        bp = reader.readPool(buf, bp);
 
         int access_flags = nextChar();
         if (access_flags != 0x8000)
@@ -110,8 +114,8 @@
         for (int i = 0; i < attributes_count; i++) {
             int attr_name = nextChar();
             int attr_length = nextInt();
-            if (getUtf8Value(attr_name, false).equals("Module") && attr_length > 2) {
-                return getModuleName(nextChar());
+            if (reader.peekName(attr_name, utf8Mapper(false)).equals("Module") && attr_length > 2) {
+                return reader.peekModuleName(nextChar(), utf8Mapper(true));
             } else {
                 // skip over unknown attributes
                 bp += attr_length;
@@ -125,132 +129,26 @@
             throw new BadClassFile("invalid " + name + " for module: " + count);
     }
 
-    /** Extract a character at position bp from buf.
-     */
-    char getChar(int bp) {
-        return
-            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
-    }
-
     /** Read a character.
      */
     char nextChar() {
-        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+        char res = buf.getChar(bp);
+        bp += 2;
+        return res;
     }
 
     /** Read an integer.
      */
     int nextInt() {
-        return
-            ((buf[bp++] & 0xFF) << 24) +
-            ((buf[bp++] & 0xFF) << 16) +
-            ((buf[bp++] & 0xFF) << 8) +
-            (buf[bp++] & 0xFF);
-    }
-
-    /** Index all constant pool entries, writing their start addresses into
-     *  poolIdx.
-     */
-    void indexPool() throws BadClassFile {
-        poolIdx = new int[nextChar()];
-        int i = 1;
-        while (i < poolIdx.length) {
-            poolIdx[i++] = bp;
-            byte tag = buf[bp++];
-            switch (tag) {
-            case CONSTANT_Utf8: case CONSTANT_Unicode: {
-                int len = nextChar();
-                bp = bp + len;
-                break;
-            }
-            case CONSTANT_Class:
-            case CONSTANT_String:
-            case CONSTANT_MethodType:
-            case CONSTANT_Module:
-            case CONSTANT_Package:
-                bp = bp + 2;
-                break;
-            case CONSTANT_MethodHandle:
-                bp = bp + 3;
-                break;
-            case CONSTANT_Fieldref:
-            case CONSTANT_Methodref:
-            case CONSTANT_InterfaceMethodref:
-            case CONSTANT_NameandType:
-            case CONSTANT_Integer:
-            case CONSTANT_Float:
-            case CONSTANT_InvokeDynamic:
-                bp = bp + 4;
-                break;
-            case CONSTANT_Long:
-            case CONSTANT_Double:
-                bp = bp + 8;
-                i++;
-                break;
-            default:
-                throw new BadClassFile("malformed constant pool");
-            }
-        }
+        int res = buf.getInt(bp);
+        bp += 4;
+        return res;
     }
 
-    String getUtf8Value(int index, boolean internalize) throws BadClassFile {
-        int utf8Index = poolIdx[index];
-        if (buf[utf8Index] == CONSTANT_Utf8) {
-            int len = getChar(utf8Index + 1);
-            int start = utf8Index + 3;
-            if (internalize) {
-                return new String(ClassFile.internalize(buf, start, len));
-            } else {
-                return new String(buf, start, len);
-            }
-        }
-        throw new BadClassFile("bad name at index " + index);
-    }
-
-    String getModuleName(int index) throws BadClassFile {
-        int infoIndex = poolIdx[index];
-        if (buf[infoIndex] == CONSTANT_Module) {
-            return getUtf8Value(getChar(infoIndex + 1), true);
-        } else {
-            throw new BadClassFile("bad module name at index " + index);
-        }
+    NameMapper<String> utf8Mapper(boolean internalize) {
+        return internalize ?
+                (buf, offset, len) -> new String(ClassFile.internalize(buf, offset, len)) :
+                String::new;
     }
 
-    private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
-        try {
-            buf = ensureCapacity(buf, s.available());
-            int r = s.read(buf);
-            int bp = 0;
-            while (r != -1) {
-                bp += r;
-                buf = ensureCapacity(buf, bp);
-                r = s.read(buf, bp, buf.length - bp);
-            }
-            return buf;
-        } finally {
-            try {
-                s.close();
-            } catch (IOException e) {
-                /* Ignore any errors, as this stream may have already
-                 * thrown a related exception which is the one that
-                 * should be reported.
-                 */
-            }
-        }
-    }
-
-    /*
-     * ensureCapacity will increase the buffer as needed, taking note that
-     * the new buffer will always be greater than the needed and never
-     * exactly equal to the needed size or bp. If equal then the read (above)
-     * will infinitely loop as buf.length - bp == 0.
-     */
-    private static byte[] ensureCapacity(byte[] buf, int needed) {
-        if (buf.length <= needed) {
-            byte[] old = buf;
-            buf = new byte[Integer.highestOneBit(needed) << 1];
-            System.arraycopy(old, 0, buf, 0, old.length);
-        }
-        return buf;
-    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.jvm;
-
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Types.UniqueType;
-
-import com.sun.tools.javac.util.ArrayUtils;
-import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.util.Filter;
-import com.sun.tools.javac.util.Name;
-
-import java.util.*;
-
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-
-import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/** An internal structure that corresponds to the constant pool of a classfile.
- *
- *  <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 Pool {
-
-    public static final int MAX_ENTRIES = 0xFFFF;
-    public static final int MAX_STRING_LENGTH = 0xFFFF;
-
-    /** Index of next constant to be entered.
-     */
-    int pp;
-
-    /** The initial pool buffer.
-     */
-    Object[] pool;
-
-    /** A hashtable containing all constants in the pool.
-     */
-    Map<Object,Integer> indices;
-
-    Types types;
-
-    /** Construct a pool with given number of elements and element array.
-     */
-    public Pool(int pp, Object[] pool, Types types) {
-        this.pp = pp;
-        this.pool = pool;
-        this.types = types;
-        this.indices = new HashMap<>(pool.length);
-        for (int i = 1; i < pp; i++) {
-            if (pool[i] != null) indices.put(pool[i], i);
-        }
-    }
-
-    /** Construct an empty pool.
-     */
-    public Pool(Types types) {
-        this(1, new Object[64], types);
-    }
-
-    /** Return the number of entries in the constant pool.
-     */
-    public int numEntries() {
-        return pp;
-    }
-
-    /** Remove everything from this pool.
-     */
-    public void reset() {
-        pp = 1;
-        indices.clear();
-    }
-
-    /** Place an object in the pool, unless it is already there.
-     *  If object is a symbol also enter its owner unless the owner is a
-     *  package.  Return the object's index in the pool.
-     */
-    public int put(Object value) {
-        value = makePoolValue(value);
-        Assert.check(!(value instanceof Type.TypeVar));
-        Assert.check(!(value instanceof Types.UniqueType &&
-                       ((UniqueType) value).type instanceof Type.TypeVar));
-        Integer index = indices.get(value);
-        if (index == null) {
-            index = pp;
-            indices.put(value, index);
-            pool = ArrayUtils.ensureCapacity(pool, pp);
-            pool[pp++] = value;
-            if (value instanceof Long || value instanceof Double) {
-                pool = ArrayUtils.ensureCapacity(pool, pp);
-                pool[pp++] = null;
-            }
-        }
-        return index.intValue();
-    }
-
-    Object makePoolValue(Object o) {
-        if (o instanceof DynamicMethodSymbol) {
-            return new DynamicMethod((DynamicMethodSymbol)o, types);
-        } else if (o instanceof MethodSymbol) {
-            return new Method((MethodSymbol)o, types);
-        } else if (o instanceof VarSymbol) {
-            return new Variable((VarSymbol)o, types);
-        } else if (o instanceof Type) {
-            Type t = (Type)o;
-            // ClassRefs can come from ClassSymbols or from Types.
-            // Return the symbol for these types to avoid duplicates
-            // in the constant pool
-            if (t.hasTag(TypeTag.CLASS))
-                return t.tsym;
-            else
-                return new UniqueType(t, types);
-        } else {
-            return o;
-        }
-    }
-
-    /** Return the given object's index in the pool,
-     *  or -1 if object is not in there.
-     */
-    public int get(Object o) {
-        Integer n = indices.get(o);
-        return n == null ? -1 : n.intValue();
-    }
-
-    static class Method extends DelegatedSymbol<MethodSymbol> {
-        UniqueType uniqueType;
-        Method(MethodSymbol m, Types types) {
-            super(m);
-            this.uniqueType = new UniqueType(m.type, types);
-        }
-        @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean equals(Object any) {
-            if (!(any instanceof Method)) return false;
-            MethodSymbol o = ((Method)any).other;
-            MethodSymbol m = this.other;
-            return
-                o.name == m.name &&
-                o.owner == m.owner &&
-                ((Method)any).uniqueType.equals(uniqueType);
-        }
-        @DefinedBy(Api.LANGUAGE_MODEL)
-        public int hashCode() {
-            MethodSymbol m = this.other;
-            return
-                m.name.hashCode() * 33 +
-                m.owner.hashCode() * 9 +
-                uniqueType.hashCode();
-        }
-    }
-
-    public static class DynamicMethod extends Method {
-        public Object[] uniqueStaticArgs;
-
-        public DynamicMethod(DynamicMethodSymbol m, Types types) {
-            super(m, types);
-            uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
-        }
-
-        @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean equals(Object any) {
-            return equalsImpl(any, true);
-        }
-
-        protected boolean equalsImpl(Object any, boolean includeDynamicArgs) {
-            if (includeDynamicArgs && !super.equals(any)) return false;
-            if (!(any instanceof DynamicMethod)) return false;
-            DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
-            DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
-            return dm1.bsm == dm2.bsm &&
-                        dm1.bsmKind == dm2.bsmKind &&
-                        Arrays.equals(uniqueStaticArgs,
-                            ((DynamicMethod)any).uniqueStaticArgs);
-        }
-
-        @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public int hashCode() {
-            return hashCodeImpl(true);
-        }
-
-        protected int hashCodeImpl(boolean includeDynamicArgs) {
-            int hash = includeDynamicArgs ? super.hashCode() : 0;
-            DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
-            hash += dm.bsmKind * 7 +
-                    dm.bsm.hashCode() * 11;
-            for (int i = 0; i < dm.staticArgs.length; i++) {
-                hash += (uniqueStaticArgs[i].hashCode() * 23);
-            }
-            return hash;
-        }
-
-        private Object[] getUniqueTypeArray(Object[] objects, Types types) {
-            Object[] result = new Object[objects.length];
-            for (int i = 0; i < objects.length; i++) {
-                if (objects[i] instanceof Type) {
-                    result[i] = new UniqueType((Type)objects[i], types);
-                } else {
-                    result[i] = objects[i];
-                }
-            }
-            return result;
-        }
-
-        static class BootstrapMethodsKey extends DynamicMethod {
-            BootstrapMethodsKey(DynamicMethodSymbol m, Types types) {
-                super(m, types);
-            }
-
-            @Override @DefinedBy(Api.LANGUAGE_MODEL)
-            public boolean equals(Object any) {
-                return equalsImpl(any, false);
-            }
-
-            @Override @DefinedBy(Api.LANGUAGE_MODEL)
-            public int hashCode() {
-                return hashCodeImpl(false);
-            }
-
-            Object[] getUniqueArgs() {
-                return uniqueStaticArgs;
-            }
-        }
-
-        static class BootstrapMethodsValue {
-            final MethodHandle mh;
-            final int index;
-
-            public BootstrapMethodsValue(MethodHandle mh, int index) {
-                this.mh = mh;
-                this.index = index;
-            }
-        }
-    }
-
-    static class Variable extends DelegatedSymbol<VarSymbol> {
-        UniqueType uniqueType;
-        Variable(VarSymbol v, Types types) {
-            super(v);
-            this.uniqueType = new UniqueType(v.type, types);
-        }
-        @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean equals(Object any) {
-            if (!(any instanceof Variable)) return false;
-            VarSymbol o = ((Variable)any).other;
-            VarSymbol v = other;
-            return
-                o.name == v.name &&
-                o.owner == v.owner &&
-                ((Variable)any).uniqueType.equals(uniqueType);
-        }
-        @DefinedBy(Api.LANGUAGE_MODEL)
-        public int hashCode() {
-            VarSymbol v = other;
-            return
-                v.name.hashCode() * 33 +
-                v.owner.hashCode() * 9 +
-                uniqueType.hashCode();
-        }
-    }
-
-    public static class MethodHandle {
-
-        /** Reference kind - see ClassFile */
-        int refKind;
-
-        /** Reference symbol */
-        Symbol refSym;
-
-        UniqueType uniqueType;
-
-        public MethodHandle(int refKind, Symbol refSym, Types types) {
-            this.refKind = refKind;
-            this.refSym = refSym;
-            this.uniqueType = new UniqueType(this.refSym.type, types);
-            checkConsistent();
-        }
-        public boolean equals(Object other) {
-            if (!(other instanceof MethodHandle)) return false;
-            MethodHandle mr = (MethodHandle) other;
-            if (mr.refKind != refKind)  return false;
-            Symbol o = mr.refSym;
-            return
-                o.name == refSym.name &&
-                o.owner == refSym.owner &&
-                ((MethodHandle)other).uniqueType.equals(uniqueType);
-        }
-        public int hashCode() {
-            return
-                refKind * 65 +
-                refSym.name.hashCode() * 33 +
-                refSym.owner.hashCode() * 9 +
-                uniqueType.hashCode();
-        }
-
-        /**
-         * Check consistency of reference kind and symbol (see JVMS 4.4.8)
-         */
-        @SuppressWarnings("fallthrough")
-        private void checkConsistent() {
-            boolean staticOk = false;
-            Kind expectedKind = null;
-            Filter<Name> nameFilter = nonInitFilter;
-            boolean interfaceOwner = false;
-            switch (refKind) {
-                case ClassFile.REF_getStatic:
-                case ClassFile.REF_putStatic:
-                    staticOk = true;
-                case ClassFile.REF_getField:
-                case ClassFile.REF_putField:
-                    expectedKind = VAR;
-                    break;
-                case ClassFile.REF_newInvokeSpecial:
-                    nameFilter = initFilter;
-                    expectedKind = MTH;
-                    break;
-                case ClassFile.REF_invokeInterface:
-                    interfaceOwner = true;
-                    expectedKind = MTH;
-                    break;
-                case ClassFile.REF_invokeStatic:
-                    interfaceOwner = true;
-                    staticOk = true;
-                case ClassFile.REF_invokeVirtual:
-                    expectedKind = MTH;
-                    break;
-                case ClassFile.REF_invokeSpecial:
-                    interfaceOwner = true;
-                    expectedKind = MTH;
-                    break;
-            }
-            Assert.check(!refSym.isStatic() || staticOk);
-            Assert.check(refSym.kind == expectedKind);
-            Assert.check(nameFilter.accepts(refSym.name));
-            Assert.check(!refSym.owner.isInterface() || interfaceOwner);
-        }
-        //where
-                Filter<Name> nonInitFilter = n -> (n != n.table.names.init && n != n.table.names.clinit);
-
-                Filter<Name> initFilter = n -> n == n.table.names.init;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.Types.UniqueType;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Pair;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * This interface models all javac entities that can be used to represent constant pool entries.
+ * A pool constant entity must (i) be associated with a constant pool entry tag and have a function
+ * which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the
+ * constant pool).
+ */
+public interface PoolConstant {
+
+    /**
+     * The constant pool entry key.
+     */
+    default Object poolKey(Types types) { return this; }
+
+    /**
+     * The constant pool entry tag.
+     */
+    int poolTag();
+
+    /**
+     * The root of pool constants that can be loaded (e.g. with {@code ldc}, or appear as static
+     * arguments to a bootstrap method.
+     */
+    interface LoadableConstant extends PoolConstant {
+
+        /**
+         * Create a pool constant describing a given {@code int} value.
+         */
+        static LoadableConstant Int(int i) {
+            return new BasicConstant(ClassFile.CONSTANT_Integer, i);
+        }
+
+        /**
+         * Create a pool constant describing a given {@code float} value.
+         */
+        static LoadableConstant Float(float f) {
+            return new BasicConstant(ClassFile.CONSTANT_Float, f);
+        }
+
+        /**
+         * Create a pool constant describing a given {@code long} value.
+         */
+        static LoadableConstant Long(long l) {
+            return new BasicConstant(ClassFile.CONSTANT_Long, l);
+        }
+
+        /**
+         * Create a pool constant describing a given {@code double} value.
+         */
+        static LoadableConstant Double(double d) {
+            return new BasicConstant(ClassFile.CONSTANT_Double, d);
+        }
+
+        /**
+         * Create a pool constant describing a given {@code String} value.
+         */
+        static LoadableConstant String(String s) {
+            return new BasicConstant(ClassFile.CONSTANT_String, s);
+        }
+
+        /**
+         * This class models a pool constant of given basic type, one of {@code int}, {@code float},
+         * {@code long}, {@code double} or {@code String}.
+         */
+        class BasicConstant implements LoadableConstant {
+            int tag;
+            Object data;
+
+            private BasicConstant(int tag, Object data) {
+                this.tag = tag;
+                this.data = data;
+            }
+
+            @Override
+            public int poolTag() {
+                return tag;
+            }
+
+            @Override
+            public Object poolKey(Types types) {
+                return data;
+            }
+        }
+    }
+
+    /**
+     * This interface models a dynamic pool constant (either of kind {@code InvokeDynamic} or
+     * {@code ConstantDynamic}). In addition to the functionalities provided by the base interface,
+     * a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list.
+     * Finally, a dynamic constant must have a way to compute a bootstrap method key - that is,
+     * a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing
+     * the {@code BootstrapMethods} attribute.
+     */
+    interface Dynamic extends PoolConstant {
+
+        /**
+         * The dynamic constant's dynamic type.
+         */
+        PoolConstant dynamicType();
+
+        /**
+         * The dynamic constant's static argument list.
+         */
+        LoadableConstant[] staticArgs();
+
+        /**
+         * The dynamic constant's bootstrap method.
+         */
+        LoadableConstant bootstrapMethod();
+
+        default BsmKey bsmKey(Types types) {
+            return new BsmKey(types, bootstrapMethod(), staticArgs());
+        }
+
+        @Override
+        default Object poolKey(Types types) {
+            return new Pair<>(bsmKey(types), dynamicType().poolKey(types));
+        }
+
+        /**
+         * A class modelling a bootstrap method key.
+         */
+        class BsmKey {
+            /**
+             * The key's bootstrap method constant.
+             */
+            public final LoadableConstant bsm;
+
+            /**
+             * The key's static argument list.
+             */
+            public final LoadableConstant[] staticArgs;
+
+            private final Object bsmKey;
+            private final List<?> staticArgKeys;
+
+            private BsmKey(Types types, LoadableConstant bsm, LoadableConstant[] staticArgs) {
+                this.bsm = bsm;
+                this.bsmKey = bsm.poolKey(types);
+                this.staticArgs = staticArgs;
+                this.staticArgKeys = Stream.of(staticArgs)
+                        .map(p -> p.poolKey(types))
+                        .collect(List.collector());
+            }
+
+            @Override
+            public int hashCode() {
+                return bsmKey.hashCode() +
+                        staticArgKeys.hashCode();
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                if (obj instanceof BsmKey) {
+                    BsmKey other = (BsmKey)obj;
+                    return Objects.equals(bsmKey, other.bsmKey) &&
+                            Objects.equals(staticArgKeys, other.staticArgKeys);
+                } else {
+                    return false;
+                }
+            }
+        }
+    }
+
+    /**
+     * A pool constant implememntation describing a name and type pool entry.
+     */
+    final class NameAndType implements PoolConstant {
+
+        final Name name;
+        final Type type;
+
+        NameAndType(Name name, Type type) {
+            this.name = name;
+            this.type = type;
+        }
+
+        @Override
+        public int poolTag() {
+            return ClassFile.CONSTANT_NameandType;
+        }
+
+        @Override
+        public Object poolKey(Types types) {
+            return new Pair<>(name, new UniqueType(type, types));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Name.NameMapper;
+import com.sun.tools.javac.util.Names;
+
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Dynamic;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InvokeDynamic;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Module;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_NameandType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Package;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Utf8;
+import static com.sun.tools.javac.jvm.ClassFile.internalize;
+
+/**
+ * Pool interface towards {@code ClassReader}. Exposes methods to decode and read javac entities
+ * from the constant pool.
+ *
+ *  <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 PoolReader {
+
+    private final ClassReader reader;
+    private final ByteBuffer buf;
+    private final Names names;
+    private final Symtab syms;
+
+    private ImmutablePoolHelper pool;
+
+    PoolReader(ByteBuffer buf) {
+        this(null, buf, null, null);
+    }
+
+    PoolReader(ClassReader reader, Names names, Symtab syms) {
+        this(reader, reader.buf, names, syms);
+    }
+
+    PoolReader(ClassReader reader, ByteBuffer buf, Names names, Symtab syms) {
+        this.reader = reader;
+        this.buf = buf;
+        this.names = names;
+        this.syms = syms;
+    }
+
+    /**
+     * Get a class symbol from the pool at given index.
+     */
+    ClassSymbol getClass(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    /**
+     * Get class name without resolving
+     */
+    <Z> Z peekClassName(int index, NameMapper<Z> mapper) {
+        return peekName(buf.getChar(pool.offset(index)), mapper);
+    }
+
+    /**
+     * Get package name without resolving
+     */
+    <Z> Z peekPackageName(int index, NameMapper<Z> mapper) {
+        return peekName(buf.getChar(pool.offset(index)), mapper);
+    }
+
+    /**
+     * Get module name without resolving
+     */
+    <Z> Z peekModuleName(int index, NameMapper<Z> mapper) {
+        return peekName(buf.getChar(pool.offset(index)), mapper);
+    }
+
+    /**
+     * Get a module symbol from the pool at given index.
+     */
+    ModuleSymbol getModule(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    /**
+     * Get a module symbol from the pool at given index.
+     */
+    PackageSymbol getPackage(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    /**
+     * Peek a name from the pool at given index without resolving.
+     */
+    <Z> Z peekName(int index, Name.NameMapper<Z> mapper) {
+        return getUtf8(index, mapper);
+    }
+
+    /**
+     * Get a name from the pool at given index.
+     */
+    Name getName(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    /**
+     * Get a type from the pool at given index.
+     */
+    Type getType(int index) {
+        return getName(index).map(reader::sigToType);
+    }
+
+    /**
+     * Get a name and type pair from the pool at given index.
+     */
+    NameAndType getNameAndType(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    /**
+     * Get a class symbol from the pool at given index.
+     */
+    Object getConstant(int index) {
+        return pool.readIfNeeded(index);
+    }
+
+    boolean hasTag(int index, int tag) {
+        return pool.tag(index) == tag;
+    }
+
+    private <Z> Z getUtf8(int index, NameMapper<Z> mapper) {
+        int tag = pool.tag(index);
+        if (tag == CONSTANT_Utf8) {
+            int offset = pool.offset(index);
+            int len = pool.poolbuf.getChar(offset);
+            return mapper.map(pool.poolbuf.elems, offset + 2, len);
+        } else {
+            throw new AssertionError("Unexpected constant tag: " + tag);
+        }
+    }
+
+    private Object resolve(ByteBuffer poolbuf, int tag, int offset) {
+        switch (tag) {
+            case CONSTANT_Utf8: {
+                int len = poolbuf.getChar(offset);
+                return names.fromUtf(poolbuf.elems, offset + 2, len);
+            }
+            case CONSTANT_Class: {
+                int index = poolbuf.getChar(offset);
+                Name name = names.fromUtf(getName(index).map(ClassFile::internalize));
+                return syms.enterClass(reader.currentModule, name);
+            }
+            case CONSTANT_NameandType: {
+                Name name = getName(poolbuf.getChar(offset));
+                Type type = getType(poolbuf.getChar(offset + 2));
+                return new NameAndType(name, type);
+            }
+            case CONSTANT_Integer:
+                return poolbuf.getInt(offset);
+            case CONSTANT_Float:
+                return poolbuf.getFloat(offset);
+            case CONSTANT_Long:
+                return poolbuf.getLong(offset);
+            case CONSTANT_Double:
+                return poolbuf.getDouble(offset);
+            case CONSTANT_String:
+                return getName(poolbuf.getChar(offset)).toString();
+            case CONSTANT_Package: {
+                Name name = getName(poolbuf.getChar(offset));
+                return syms.enterPackage(reader.currentModule, names.fromUtf(internalize(name)));
+            }
+            case CONSTANT_Module: {
+                Name name = getName(poolbuf.getChar(offset));
+                return syms.enterModule(name);
+            }
+            default:
+                throw new AssertionError("Unexpected constant tag: " + tag);
+        }
+    }
+
+    /**
+     * Parse all constant pool entries, and keep track of their offsets. For performance and laziness
+     * reasons, it would be unwise to eagerly turn all pool entries into corresponding javac
+     * entities. First, not all entries are actually going to be read/used by javac; secondly,
+     * there are cases where creating a symbol too early might result in issues (hence methods like
+     * {@link PoolReader#peekClassName(int, NameMapper)}.
+     */
+    int readPool(ByteBuffer poolbuf, int offset) {
+        int poolSize = poolbuf.getChar(offset);
+        int index = 1;
+        offset += 2;
+        int[] offsets = new int[poolSize];
+        while (index < poolSize) {
+            byte tag = poolbuf.getByte(offset++);
+            offsets[index] = offset;
+            switch (tag) {
+                case CONSTANT_Utf8: {
+                    int len = poolbuf.getChar(offset);
+                    offset += 2 + len;
+                    break;
+                }
+                case CONSTANT_Class:
+                case CONSTANT_String:
+                case CONSTANT_Module:
+                case CONSTANT_Package:
+                case CONSTANT_MethodType:
+                    offset += 2;
+                    break;
+                case CONSTANT_MethodHandle:
+                    offset += 3;
+                    break;
+                case CONSTANT_Fieldref:
+                case CONSTANT_Methodref:
+                case CONSTANT_InterfaceMethodref:
+                case CONSTANT_NameandType:
+                case CONSTANT_Integer:
+                case CONSTANT_Float:
+                case CONSTANT_Dynamic:
+                case CONSTANT_InvokeDynamic:
+                    offset += 4;
+                    break;
+                case CONSTANT_Long:
+                case CONSTANT_Double:
+                    offset += 8;
+                    break;
+                default:
+                    throw reader.badClassFile("bad.const.pool.tag.at",
+                            Byte.toString(tag),
+                            Integer.toString(offset - 1));
+            }
+            index += sizeof(tag);
+        }
+        pool = new ImmutablePoolHelper(poolbuf, offsets);
+        return offset;
+    }
+
+    private int sizeof(int tag) {
+        switch (tag) {
+            case ClassFile.CONSTANT_Double: case ClassFile.CONSTANT_Long:
+                return 2;
+            default:
+                return 1;
+        }
+    }
+
+    class ImmutablePoolHelper {
+
+        final Object[] values;
+        final int[] offsets;
+        final ByteBuffer poolbuf;
+
+        public ImmutablePoolHelper(ByteBuffer poolbuf, int[] offsets) {
+            this.offsets = offsets;
+            this.values = new Object[offsets.length];
+            this.poolbuf = poolbuf;
+        }
+
+        private int checkIndex(int index) {
+            if (index <= 0 || index >= offsets.length) {
+                //pool index is outside valid range.
+                throw reader.badClassFile("bad.const.pool.index", reader.currentClassFile,
+                        index, offsets.length);
+            } else {
+                return index;
+            }
+        }
+
+        int offset(int index) {
+            return offsets[checkIndex(index)];
+        }
+
+        @SuppressWarnings("unchecked")
+        <P> P readIfNeeded(int index) {
+            Object v = values[checkIndex(index)];
+            if (v != null) {
+                return (P)v;
+            } else {
+                P p = (P)resolve(poolbuf, tag(index), offset(index));
+                values[index] = p;
+                return p;
+            }
+        }
+
+        int tag(int index) {
+            return poolbuf.elems[offset(index) - 1];
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Kinds.Kind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.jvm.ClassWriter.PoolOverflow;
+import com.sun.tools.javac.jvm.ClassWriter.StringOverflow;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+import static com.sun.tools.javac.code.Kinds.Kind.TYP;
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.externalize;
+
+/**
+ * Pool interface towards {@code ClassWriter}. Exposes methods to encode and write javac entities
+ * into the constant pool.
+ *
+ *  <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 PoolWriter {
+
+    /** Max number of constant pool entries. */
+    public static final int MAX_ENTRIES = 0xFFFF;
+
+    /** Max number of char in a string constant. */
+    public static final int MAX_STRING_LENGTH = 0xFFFF;
+
+    private static final int POOL_BUF_SIZE = 0x7fff;
+
+    private final Types types;
+
+    private final Names names;
+
+    /** Pool helper **/
+    final WriteablePoolHelper pool;
+
+    /** Sole signature generator */
+    final SharedSignatureGenerator signatureGen;
+
+    /** The inner classes to be written, as an ordered set (enclosing first). */
+    LinkedHashSet<ClassSymbol> innerClasses = new LinkedHashSet<>();
+
+    /** The list of entries in the BootstrapMethods attribute. */
+    Map<BsmKey, Integer> bootstrapMethods = new LinkedHashMap<>();
+
+    public PoolWriter(Types types, Names names) {
+        this.types = types;
+        this.names = names;
+        this.signatureGen = new SharedSignatureGenerator(types);
+        this.pool = new WriteablePoolHelper();
+    }
+
+    /**
+     * Puts a class symbol into the pool and return its index.
+     */
+    int putClass(ClassSymbol csym) {
+        return putClass(csym.type);
+    }
+
+    /**
+     * Puts a type into the pool and return its index. The type could be either a class, a type variable
+     * or an array type.
+     */
+    int putClass(Type t) {
+        return pool.writeIfNeeded(types.erasure(t));
+    }
+
+    /**
+     * Puts a member reference into the constant pool. Valid members are either field or method symbols.
+     */
+    int putMember(Symbol s) {
+        return pool.writeIfNeeded(s);
+    }
+
+    /**
+     * Puts a dynamic reference into the constant pool and return its index.
+     */
+    int putDynamic(DynamicMethodSymbol d) {
+        return pool.writeIfNeeded(d);
+    }
+
+    /**
+     * Puts a field or method descriptor into the constant pool and return its index.
+     */
+    int putDescriptor(Type t) {
+        return putName(typeSig(types.erasure(t)));
+    }
+
+    /**
+     * Puts a field or method descriptor into the constant pool and return its index.
+     */
+    int putDescriptor(Symbol s) {
+        return putDescriptor(descriptorType(s));
+    }
+
+    /**
+     * Puts a signature (see {@code Signature} attribute in JVMS 4.4) into the constant pool and
+     * return its index.
+     */
+    int putSignature(Symbol s) {
+        if (s.kind == TYP) {
+            return putName(classSig(s.type));
+        } else {
+            return putName(typeSig(s.type));
+        }
+    }
+
+    /**
+     * Puts a constant value into the pool and return its index. Supported values are int, float, long,
+     * double and String.
+     */
+    int putConstant(Object o) {
+        if (o instanceof Integer) {
+            return putConstant(LoadableConstant.Int((int)o));
+        } else if (o instanceof Float) {
+            return putConstant(LoadableConstant.Float((float)o));
+        } else if (o instanceof Long) {
+            return putConstant(LoadableConstant.Long((long)o));
+        } else if (o instanceof Double) {
+            return putConstant(LoadableConstant.Double((double)o));
+        } else if (o instanceof String) {
+            return putConstant(LoadableConstant.String((String)o));
+        } else {
+            throw new AssertionError("unexpected constant: " + o);
+        }
+    }
+
+    /**
+     * Puts a constant into the pool and return its index.
+     */
+    int putConstant(LoadableConstant c) {
+        switch (c.poolTag()) {
+            case CONSTANT_Class:
+                return putClass((Type)c);
+            case CONSTANT_MethodType:
+                return pool.writeIfNeeded(types.erasure((Type)c));
+            default:
+                return pool.writeIfNeeded(c);
+        }
+    }
+
+    int putName(Name name) {
+        return pool.writeIfNeeded(name);
+    }
+
+    /**
+     * Puts a name and type pair into the pool and returns its index.
+     */
+    int putNameAndType(Symbol s) {
+        return pool.writeIfNeeded(new NameAndType(s.name, descriptorType(s)));
+    }
+
+    /**
+     * Puts a package entry into the pool and returns its index.
+     */
+    int putPackage(PackageSymbol pkg) {
+        return pool.writeIfNeeded(pkg);
+    }
+
+    /**
+     * Puts a module entry into the pool and returns its index.
+     */
+    int putModule(ModuleSymbol mod) {
+        return pool.writeIfNeeded(mod);
+    }
+
+    /**
+     * Enter an inner class into the `innerClasses' set.
+     */
+    void enterInner(ClassSymbol c) {
+        if (c.type.isCompound()) {
+            throw new AssertionError("Unexpected intersection type: " + c.type);
+        }
+        c.complete();
+        if (c.owner.enclClass() != null && !innerClasses.contains(c)) {
+            enterInner(c.owner.enclClass());
+            innerClasses.add(c);
+        }
+    }
+
+    /**
+     * Create a new Utf8 entry representing a descriptor for given (member) symbol.
+     */
+    private Type descriptorType(Symbol s) {
+        return s.kind == Kind.MTH ? s.externalType(types) : s.erasure(types);
+    }
+
+    private int makeBoostrapEntry(Dynamic dynamic) {
+        BsmKey bsmKey = dynamic.bsmKey(types);
+
+        // Figure out the index for existing BSM; create a new BSM if no key
+        Integer index = bootstrapMethods.get(bsmKey);
+        if (index == null) {
+            index = bootstrapMethods.size();
+            bootstrapMethods.put(bsmKey, index);
+        }
+
+        return index;
+    }
+
+    /**
+     * Write pool contents into given byte buffer.
+     */
+    void writePool(OutputStream out) throws IOException, PoolOverflow {
+        if (pool.overflowString != null) {
+            throw new StringOverflow(pool.overflowString);
+        }
+        int size = size();
+        if (size > MAX_ENTRIES) {
+            throw new PoolOverflow();
+        }
+        out.write(size >> 8);
+        out.write(size);
+        out.write(pool.poolbuf.elems, 0, pool.poolbuf.length);
+    }
+
+    /**
+     * Signature Generation
+     */
+    class SharedSignatureGenerator extends Types.SignatureGenerator {
+
+        /**
+         * An output buffer for type signatures.
+         */
+        ByteBuffer sigbuf = new ByteBuffer();
+
+        SharedSignatureGenerator(Types types) {
+            super(types);
+        }
+
+        /**
+         * Assemble signature of given type in string buffer.
+         * Check for uninitialized types before calling the general case.
+         */
+        @Override
+        public void assembleSig(Type type) {
+            switch (type.getTag()) {
+                case UNINITIALIZED_THIS:
+                case UNINITIALIZED_OBJECT:
+                    // we don't yet have a spec for uninitialized types in the
+                    // local variable table
+                    assembleSig(types.erasure(((UninitializedType)type).qtype));
+                    break;
+                default:
+                    super.assembleSig(type);
+            }
+        }
+
+        @Override
+        protected void append(char ch) {
+            sigbuf.appendByte(ch);
+        }
+
+        @Override
+        protected void append(byte[] ba) {
+            sigbuf.appendBytes(ba);
+        }
+
+        @Override
+        protected void append(Name name) {
+            sigbuf.appendName(name);
+        }
+
+        @Override
+        protected void classReference(ClassSymbol c) {
+            enterInner(c);
+        }
+
+        protected void reset() {
+            sigbuf.reset();
+        }
+
+        protected Name toName() {
+            return sigbuf.toName(names);
+        }
+    }
+
+    class WriteablePoolHelper {
+
+        /** Pool entries. */
+        private final Map<Object, Integer> keysToPos = new HashMap<>(64);
+
+        final ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
+
+        int currentIndex = 1;
+
+        ArrayDeque<PoolConstant> todo = new ArrayDeque<>();
+
+        String overflowString = null;
+
+        private <P extends PoolConstant> int writeIfNeeded(P p) {
+            Object key = p.poolKey(types);
+            Integer index = keysToPos.get(key);
+            if (index == null) {
+                keysToPos.put(key, index = currentIndex++);
+                boolean first = todo.isEmpty();
+                todo.addLast(p);
+                if (first) {
+                    while (!todo.isEmpty()) {
+                        writeConstant(todo.peekFirst());
+                        todo.removeFirst();
+                    }
+                }
+            }
+            return index;
+        }
+
+        void writeConstant(PoolConstant c) {
+            int tag = c.poolTag();
+            switch (tag) {
+                case ClassFile.CONSTANT_Class: {
+                    Type ct = (Type)c;
+                    Name name = ct.hasTag(ARRAY) ?
+                            typeSig(ct) :
+                            names.fromUtf(externalize(ct.tsym.flatName()));
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putName(name));
+                    if (ct.hasTag(CLASS)) {
+                        enterInner((ClassSymbol)ct.tsym);
+                    }
+                    break;
+                }
+                case ClassFile.CONSTANT_Utf8: {
+                    Name name = (Name)c;
+                    poolbuf.appendByte(tag);
+                    byte[] bs = name.toUtf();
+                    poolbuf.appendChar(bs.length);
+                    poolbuf.appendBytes(bs, 0, bs.length);
+                    if (overflowString == null && bs.length > MAX_STRING_LENGTH) {
+                        //report error only once
+                        overflowString = new String(bs);
+                    }
+                    break;
+                }
+                case ClassFile.CONSTANT_InterfaceMethodref:
+                case ClassFile.CONSTANT_Methodref:
+                case ClassFile.CONSTANT_Fieldref: {
+                    Symbol sym = (Symbol)c;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putClass((ClassSymbol)sym.owner));
+                    poolbuf.appendChar(putNameAndType(sym));
+                    break;
+                }
+                case ClassFile.CONSTANT_Package: {
+                    PackageSymbol pkg = (PackageSymbol)c;
+                    Name pkgName = names.fromUtf(externalize(pkg.flatName()));
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putName(pkgName));
+                    break;
+                }
+                case ClassFile.CONSTANT_Module: {
+                    ModuleSymbol mod = (ModuleSymbol)c;
+                    int modName = putName(mod.name);
+                    poolbuf.appendByte(mod.poolTag());
+                    poolbuf.appendChar(modName);
+                    break;
+                }
+                case ClassFile.CONSTANT_Integer:
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendInt((int)((BasicConstant)c).data);
+                    break;
+                case ClassFile.CONSTANT_Float:
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendFloat((float)((BasicConstant)c).data);
+                    break;
+                case ClassFile.CONSTANT_Long:
+                    currentIndex++;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendLong((long)((BasicConstant)c).data);
+                    break;
+                case ClassFile.CONSTANT_Double:
+                    currentIndex++;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendDouble((double)((BasicConstant)c).data);
+                    break;
+                case ClassFile.CONSTANT_MethodHandle: {
+                    MethodHandleSymbol h = (MethodHandleSymbol)c;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendByte(h.referenceKind());
+                    poolbuf.appendChar(putMember(h.baseSymbol()));
+                    break;
+                }
+                case ClassFile.CONSTANT_MethodType: {
+                    Type.MethodType mt = (Type.MethodType)c;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putDescriptor(mt.baseType()));
+                    break;
+                }
+                case ClassFile.CONSTANT_String: {
+                    Name utf = names.fromString((String)((BasicConstant)c).data);
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putName(utf));
+                    break;
+                }
+                case ClassFile.CONSTANT_NameandType: {
+                    NameAndType nt = (NameAndType)c;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(putName(nt.name));
+                    poolbuf.appendChar(putDescriptor(nt.type));
+                    break;
+                }
+                case ClassFile.CONSTANT_InvokeDynamic: {
+                    DynamicMethodSymbol d = (DynamicMethodSymbol)c;
+                    poolbuf.appendByte(tag);
+                    poolbuf.appendChar(makeBoostrapEntry(d));
+                    poolbuf.appendChar(putNameAndType(d));
+                    break;
+                }
+                default:
+                    throw new AssertionError("Unexpected constant tag: " + tag);
+            }
+        }
+
+        void reset() {
+            keysToPos.clear();
+            currentIndex = 1;
+            todo.clear();
+            overflowString = null;
+            poolbuf.reset();
+        }
+    }
+
+    int size() {
+        return pool.currentIndex;
+    }
+
+    /**
+     * Return signature of given type
+     */
+    private Name typeSig(Type type) {
+        signatureGen.reset();
+        signatureGen.assembleSig(type);
+        return signatureGen.toName();
+    }
+
+    private Name classSig(Type t) {
+        signatureGen.reset();
+        List<Type> typarams = t.getTypeArguments();
+        if (typarams.nonEmpty()) {
+            signatureGen.assembleParamsSig(typarams);
+        }
+        signatureGen.assembleSig(types.supertype(t));
+        for (Type i : types.interfaces(t))
+            signatureGen.assembleSig(i);
+        return signatureGen.toName();
+    }
+
+    void reset() {
+        innerClasses.clear();
+        bootstrapMethods.clear();
+        pool.reset();
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Fri Apr 19 08:00:42 2019 -0400
@@ -26,7 +26,9 @@
 package com.sun.tools.javac.jvm;
 
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeMaker;
@@ -222,7 +224,7 @@
 
         private JCDiagnostic.DiagnosticPosition newStringBuilder(JCTree tree) {
             JCDiagnostic.DiagnosticPosition pos = tree.pos();
-            gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType));
+            gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType), syms.stringBuilderType);
             gen.getCode().emitop0(dup);
             gen.callMethod(pos, syms.stringBuilderType, names.init, List.nil(), false);
             return pos;
@@ -378,10 +380,9 @@
 
                 Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat,
                         syms.noSymbol,
-                        ClassFile.REF_invokeStatic,
-                        (Symbol.MethodSymbol)bsm,
+                        ((MethodSymbol)bsm).asHandle(),
                         indyType,
-                        List.nil().toArray());
+                        List.nil().toArray(new LoadableConstant[0]));
 
                 Items.Item item = gen.getItems().makeDynamicItem(dynSym);
                 item.invoke();
@@ -416,7 +417,7 @@
 
                 StringBuilder recipe = new StringBuilder(t.size());
                 ListBuffer<Type> dynamicArgs = new ListBuffer<>();
-                ListBuffer<Object> staticArgs = new ListBuffer<>();
+                ListBuffer<LoadableConstant> staticArgs = new ListBuffer<>();
 
                 for (JCTree arg : t) {
                     Object constVal = arg.type.constValue();
@@ -431,7 +432,7 @@
                         String a = arg.type.stringValue();
                         if (a.indexOf(TAG_CONST) != -1 || a.indexOf(TAG_ARG) != -1) {
                             recipe.append(TAG_CONST);
-                            staticArgs.add(a);
+                            staticArgs.add(LoadableConstant.String(a));
                         } else {
                             recipe.append(a);
                         }
@@ -463,7 +464,7 @@
         }
 
         /** Produce the actual invokedynamic call to StringConcatFactory */
-        private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<Object> staticArgs, List<Type> dynamicArgTypes) {
+        private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<LoadableConstant> staticArgs, List<Type> dynamicArgTypes) {
             Type.MethodType indyType = new Type.MethodType(dynamicArgTypes,
                     type,
                     List.nil(),
@@ -474,8 +475,8 @@
                 make.at(pos);
 
                 ListBuffer<Type> constTypes = new ListBuffer<>();
-                ListBuffer<Object> constants = new ListBuffer<>();
-                for (Object t : staticArgs) {
+                ListBuffer<LoadableConstant> constants = new ListBuffer<>();
+                for (LoadableConstant t : staticArgs) {
                     constants.add(t);
                     constTypes.add(syms.stringType);
                 }
@@ -495,10 +496,10 @@
 
                 Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants,
                         syms.noSymbol,
-                        ClassFile.REF_invokeStatic,
-                        (Symbol.MethodSymbol)bsm,
+                        ((MethodSymbol)bsm).asHandle(),
                         indyType,
-                        List.<Object>of(recipe).appendList(constants).toArray());
+                        List.of(LoadableConstant.String(recipe))
+                                .appendList(constants).toArray(new LoadableConstant[constants.size()]));
 
                 Items.Item item = gen.getItems().makeDynamicItem(dynSym);
                 item.invoke();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -188,6 +188,11 @@
 
     private final Context context;
 
+    /**
+     * Support for preview language features.
+     */
+    private final Preview preview;
+
     /** Get the JavacProcessingEnvironment instance for this context. */
     public static JavacProcessingEnvironment instance(Context context) {
         JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
@@ -236,6 +241,7 @@
         enter = Enter.instance(context);
         initialCompleter = ClassFinder.instance(context).getCompleter();
         chk = Check.instance(context);
+        preview = Preview.instance(context);
         initProcessorLoader();
     }
 
@@ -1675,6 +1681,11 @@
         return messages.getCurrentLocale();
     }
 
+    @DefinedBy(Api.ANNOTATION_PROCESSING)
+    public boolean isPreviewEnabled() {
+        return preview.isEnabled();
+    }
+
     public Set<Symbol.PackageSymbol> getSpecifiedPackages() {
         return specifiedPackages;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Apr 19 08:00:42 2019 -0400
@@ -2164,6 +2164,11 @@
     bad constant pool entry in {0}\n\
     expected {1} at index {2}
 
+# 0: file name, 1: number (constant pool index), 2: number (constant pool size)
+compiler.misc.bad.const.pool.index=\
+    bad constant pool index in {0}\n\
+    index {1} is not within pool size {2}.
+
 # 0: file name, 1: message segment
 compiler.misc.bad.class.file.header=\
     bad class file: {0}\n\
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java	Fri Apr 19 08:00:42 2019 -0400
@@ -147,6 +147,90 @@
         appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
     }
 
+     /** Append the content of a given input stream.
+     */
+    public void appendStream(InputStream is) throws IOException {
+        try {
+            int start = length;
+            int initialSize = is.available();
+            elems = ArrayUtils.ensureCapacity(elems, length + initialSize);
+            int r = is.read(elems, start, initialSize);
+            int bp = start;
+            while (r != -1) {
+                bp += r;
+                elems = ArrayUtils.ensureCapacity(elems, bp);
+                r = is.read(elems, bp, elems.length - bp);
+            }
+        } finally {
+            try {
+                is.close();
+            } catch (IOException e) {
+                /* Ignore any errors, as this stream may have already
+                 * thrown a related exception which is the one that
+                 * should be reported.
+                 */
+            }
+        }
+    }
+
+    /** Extract an integer at position bp from elems.
+     */
+    public int getInt(int bp) {
+        return
+            ((elems[bp] & 0xFF) << 24) +
+            ((elems[bp+1] & 0xFF) << 16) +
+            ((elems[bp+2] & 0xFF) << 8) +
+            (elems[bp+3] & 0xFF);
+    }
+
+
+    /** Extract a long integer at position bp from elems.
+     */
+    public long getLong(int bp) {
+        DataInputStream elemsin =
+            new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
+        try {
+            return elemsin.readLong();
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /** Extract a float at position bp from elems.
+     */
+    public float getFloat(int bp) {
+        DataInputStream elemsin =
+            new DataInputStream(new ByteArrayInputStream(elems, bp, 4));
+        try {
+            return elemsin.readFloat();
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /** Extract a double at position bp from elems.
+     */
+    public double getDouble(int bp) {
+        DataInputStream elemsin =
+            new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
+        try {
+            return elemsin.readDouble();
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /** Extract a character at position bp from elems.
+     */
+    public char getChar(int bp) {
+        return
+            (char)(((elems[bp] & 0xFF) << 8) + (elems[bp+1] & 0xFF));
+    }
+
+    public byte getByte(int bp) {
+        return elems[bp];
+    }
+
     /** Reset to zero length.
      */
     public void reset() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java	Fri Apr 19 08:00:42 2019 -0400
@@ -25,6 +25,8 @@
 
 package com.sun.tools.javac.util;
 
+import com.sun.tools.javac.jvm.ClassFile;
+import com.sun.tools.javac.jvm.PoolConstant;
 import com.sun.tools.javac.util.DefinedBy.Api;
 
 /** An abstraction for internal compiler strings. They are stored in
@@ -36,7 +38,7 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public abstract class Name implements javax.lang.model.element.Name {
+public abstract class Name implements javax.lang.model.element.Name, PoolConstant {
 
     public final Table table;
 
@@ -52,6 +54,11 @@
         return toString().equals(cs.toString());
     }
 
+    @Override
+    public int poolTag() {
+        return ClassFile.CONSTANT_Utf8;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -188,6 +195,14 @@
      */
     public abstract int getByteOffset();
 
+    public interface NameMapper<X> {
+        X map(byte[] bytes, int offset, int len);
+    }
+
+    public <X> X map(NameMapper<X> mapper) {
+        return mapper.map(getByteArray(), getByteOffset(), getByteLength());
+    }
+
     /** An abstraction for the hash table used to create unique Name instances.
      */
     public static abstract class Table {
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1137,20 +1137,79 @@
 
     private static long nativeKeyWrapperKeyID = 0;
     private static CK_MECHANISM nativeKeyWrapperMechanism = null;
+    private static long nativeKeyWrapperRefCount = 0;
+    private static Session nativeKeyWrapperSession = null;
 
     private final P11Key p11Key;
     private final byte[] nativeKeyInfo;
+    private boolean wrapperKeyUsed;
 
     // destroyed and recreated when refCount toggles to 1
     private long keyID;
 
-    private boolean isTokenObject;
-
     // phantom reference notification clean up for session keys
     private SessionKeyRef ref;
 
     private int refCount;
 
+    private static void createNativeKeyWrapper(Token token)
+            throws PKCS11Exception {
+        assert(nativeKeyWrapperKeyID == 0);
+        assert(nativeKeyWrapperRefCount == 0);
+        assert(nativeKeyWrapperSession == null);
+        // Create a global wrapping/unwrapping key
+        CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes(O_GENERATE,
+                        CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
+                                new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+                                new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)});
+        Session s = null;
+        try {
+            s = token.getObjSession();
+            nativeKeyWrapperKeyID = token.p11.C_GenerateKey(
+                    s.id(), new CK_MECHANISM(CKM_AES_KEY_GEN),
+                    wrappingAttributes);
+            nativeKeyWrapperSession = s;
+            nativeKeyWrapperSession.addObject();
+            byte[] iv = new byte[16];
+            JCAUtil.getSecureRandom().nextBytes(iv);
+            nativeKeyWrapperMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv);
+        } catch (PKCS11Exception e) {
+            // best effort
+        } finally {
+            token.releaseSession(s);
+        }
+    }
+
+    private static void deleteNativeKeyWrapper() {
+        Token token = nativeKeyWrapperSession.token;
+        if (token.isValid()) {
+            Session s = null;
+            try {
+                s = token.getOpSession();
+                token.p11.C_DestroyObject(s.id(), nativeKeyWrapperKeyID);
+                nativeKeyWrapperSession.removeObject();
+            } catch (PKCS11Exception e) {
+                // best effort
+            } finally {
+                token.releaseSession(s);
+            }
+        }
+        nativeKeyWrapperKeyID = 0;
+        nativeKeyWrapperMechanism = null;
+        nativeKeyWrapperSession = null;
+    }
+
+    static void decWrapperKeyRef() {
+        synchronized(NativeKeyHolder.class) {
+            assert(nativeKeyWrapperKeyID != 0);
+            assert(nativeKeyWrapperRefCount > 0);
+            nativeKeyWrapperRefCount--;
+            if (nativeKeyWrapperRefCount == 0) {
+                deleteNativeKeyWrapper();
+            }
+        }
+    }
+
     NativeKeyHolder(P11Key p11Key, long keyID, Session keySession,
             boolean extractKeyInfo, boolean isTokenObject) {
         this.p11Key = p11Key;
@@ -1160,35 +1219,23 @@
         if (isTokenObject) {
             this.ref = null;
         } else {
-            this.ref = new SessionKeyRef(p11Key, keyID, keySession);
-
             // Try extracting key info, if any error, disable it
             Token token = p11Key.token;
             if (extractKeyInfo) {
                 try {
-                    if (p11Key.sensitive && nativeKeyWrapperKeyID == 0) {
+                    if (p11Key.sensitive) {
+                        // p11Key native key information has to be wrapped
                         synchronized(NativeKeyHolder.class) {
-                            // Create a global wrapping/unwrapping key
-                            CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes
-                                (O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
-                                    new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
-                                    new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3),
-                                });
-                            Session wrappingSession = null;
-                            try {
-                                wrappingSession = token.getObjSession();
-                                nativeKeyWrapperKeyID = token.p11.C_GenerateKey
-                                    (wrappingSession.id(),
-                                    new CK_MECHANISM(CKM_AES_KEY_GEN),
-                                    wrappingAttributes);
-                                byte[] iv = new byte[16];
-                                JCAUtil.getSecureRandom().nextBytes(iv);
-                                nativeKeyWrapperMechanism = new CK_MECHANISM
-                                    (CKM_AES_CBC_PAD, iv);
-                            } catch (PKCS11Exception e) {
-                                // best effort
-                            } finally {
-                                token.releaseSession(wrappingSession);
+                            if (nativeKeyWrapperKeyID == 0) {
+                                createNativeKeyWrapper(token);
+                            }
+                            // If a wrapper-key was successfully created or
+                            // already exists, increment its reference
+                            // counter to keep it alive while native key
+                            // information is being held.
+                            if (nativeKeyWrapperKeyID != 0) {
+                                nativeKeyWrapperRefCount++;
+                                wrapperKeyUsed = true;
                             }
                         }
                     }
@@ -1196,7 +1243,8 @@
                     try {
                         opSession = token.getOpSession();
                         ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(),
-                            keyID, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
+                                keyID, nativeKeyWrapperKeyID,
+                                nativeKeyWrapperMechanism);
                     } catch (PKCS11Exception e) {
                         // best effort
                     } finally {
@@ -1206,6 +1254,8 @@
                     // best effort
                 }
             }
+            this.ref = new SessionKeyRef(p11Key, keyID, wrapperKeyUsed,
+                    keySession);
         }
         this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki);
     }
@@ -1222,18 +1272,15 @@
                         throw new RuntimeException(
                                 "Error: null keyID with non-zero refCount " + cnt);
                     }
-                    if (this.ref != null)  {
-                        throw new RuntimeException(
-                                "Error: null keyID with non-null session ref");
-                    }
                     Token token = p11Key.token;
                     // Create keyID using nativeKeyInfo
                     Session session = null;
                     try {
                         session = token.getObjSession();
                         this.keyID = token.p11.createNativeKey(session.id(),
-                                nativeKeyInfo, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
-                        this.ref = new SessionKeyRef(p11Key, this.keyID, session);
+                                nativeKeyInfo, nativeKeyWrapperKeyID,
+                                nativeKeyWrapperMechanism);
+                        this.ref.registerNativeKey(this.keyID, session);
                     } catch (PKCS11Exception e) {
                         this.refCount--;
                         throw new ProviderException("Error recreating native key", e);
@@ -1263,12 +1310,9 @@
                         throw new RuntimeException("ERROR: null keyID can't be destroyed");
                     }
 
-                    if (this.ref == null) {
-                        throw new RuntimeException("ERROR: null session ref can't be disposed");
-                    }
                     // destroy
                     this.keyID = 0;
-                    this.ref = this.ref.dispose();
+                    this.ref.removeNativeKey();
                 } else {
                     if (cnt < 0) {
                         // should never happen as we start count at 1 and pair get/release calls
@@ -1285,12 +1329,11 @@
  * otherwise the key maybe cleared before other objects which
  * still use these keys during finalization such as SSLSocket.
  */
-final class SessionKeyRef extends PhantomReference<P11Key>
-    implements Comparable<SessionKeyRef> {
+final class SessionKeyRef extends PhantomReference<P11Key> {
     private static ReferenceQueue<P11Key> refQueue =
         new ReferenceQueue<P11Key>();
-    private static Set<SessionKeyRef> refList =
-        Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
+    private static Set<SessionKeyRef> refSet =
+        Collections.synchronizedSet(new HashSet<SessionKeyRef>());
 
     static ReferenceQueue<P11Key> referenceQueue() {
         return refQueue;
@@ -1307,47 +1350,69 @@
     }
 
     // handle to the native key and the session it is generated under
-    private final long keyID;
-    private final Session session;
+    private long keyID;
+    private Session session;
+    private boolean wrapperKeyUsed;
 
-    SessionKeyRef(P11Key p11Key, long keyID, Session session) {
+    SessionKeyRef(P11Key p11Key, long keyID, boolean wrapperKeyUsed,
+            Session session) {
         super(p11Key, refQueue);
         if (session == null) {
             throw new ProviderException("key must be associated with a session");
         }
-        this.keyID = keyID;
-        this.session = session;
-        this.session.addObject();
+        registerNativeKey(keyID, session);
+        this.wrapperKeyUsed = wrapperKeyUsed;
 
-        refList.add(this);
+        refSet.add(this);
         drainRefQueueBounded();
     }
 
-    SessionKeyRef dispose() {
-        Token token = session.token;
-        // If the token is still valid, try to remove the key object
-        if (token.isValid()) {
-            Session s = null;
-            try {
-                s = token.getOpSession();
-                token.p11.C_DestroyObject(s.id(), keyID);
-            } catch (PKCS11Exception e) {
-                // best effort
-            } finally {
-                token.releaseSession(s);
-            }
-        }
-        refList.remove(this);
-        this.clear();
-        session.removeObject();
-        return null;
+    void registerNativeKey(long newKeyID, Session newSession) {
+        assert(newKeyID != 0);
+        assert(newSession != null);
+        updateNativeKey(newKeyID, newSession);
+    }
+
+    void removeNativeKey() {
+        assert(session != null);
+        updateNativeKey(0, null);
     }
 
-    public int compareTo(SessionKeyRef other) {
-        if (this.keyID == other.keyID) {
-            return 0;
+    private void updateNativeKey(long newKeyID, Session newSession) {
+        if (newKeyID == 0) {
+            assert(newSession == null);
+            Token token = session.token;
+            // If the token is still valid, try to remove the key object
+            if (token.isValid()) {
+                Session s = null;
+                try {
+                    s = token.getOpSession();
+                    token.p11.C_DestroyObject(s.id(), this.keyID);
+                } catch (PKCS11Exception e) {
+                    // best effort
+                } finally {
+                    token.releaseSession(s);
+                }
+            }
+            session.removeObject();
         } else {
-            return (this.keyID < other.keyID) ? -1 : 1;
+            newSession.addObject();
         }
+        keyID = newKeyID;
+        session = newSession;
+    }
+
+    // Called when the GC disposes a p11Key
+    void dispose() {
+        if (wrapperKeyUsed) {
+            // Wrapper-key no longer needed for
+            // p11Key native key information
+            NativeKeyHolder.decWrapperKeyRef();
+        }
+        if (keyID != 0) {
+            removeNativeKey();
+        }
+        refSet.remove(this);
+        this.clear();
     }
 }
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c	Fri Apr 19 08:00:42 2019 -0400
@@ -308,7 +308,7 @@
         *(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes)
                 +sensitiveAttributePosition))->pValue) == CK_TRUE) {
         // Key is sensitive. Need to extract it wrapped.
-        if (jWrappingKeyHandle != -1) {
+        if (jWrappingKeyHandle != 0) {
 
             jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
             rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
@@ -351,6 +351,7 @@
                 goto cleanup;
             }
         } else {
+            ckAssertReturnValueOK(env, CKR_KEY_HANDLE_INVALID);
             goto cleanup;
         }
         returnValue = nativeKeyInfoWrappedKeyArray;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java	Fri Apr 19 08:00:42 2019 -0400
@@ -89,7 +89,7 @@
  *         .withNamespace(StandardNamespace.PROPERTY)
  *         .named("color");
  * </pre>
- * <h3>Operations on multiple namespaces</h3>
+ * <h2>Operations on multiple namespaces</h2>
  * If multiple namespaces are specified, the namespaces are treated as
  * alternatives to each other in order of preference. The semantics of
  * such operation is "first applicable".
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.formats.html;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-
-import javax.lang.model.element.ModuleElement;
-import javax.lang.model.element.PackageElement;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-
-/**
- * Abstract class to generate the module overview files.
- *
- *  <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>
- *
- * @author Bhavesh Patel
- */
-public abstract class AbstractModuleIndexWriter extends HtmlDocletWriter {
-
-    /**
-     * Modules to be documented.
-     */
-    protected SortedMap<ModuleElement, Set<PackageElement>> modules;
-
-    protected Navigation navBar;
-
-    /**
-     * Constructor. Also initializes the modules variable.
-     *
-     * @param configuration  The current configuration
-     * @param filename Name of the module index file to be generated.
-     */
-    public AbstractModuleIndexWriter(HtmlConfiguration configuration,
-                                      DocPath filename) {
-        super(configuration, filename);
-        modules = configuration.modulePackages;
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
-    }
-
-    /**
-     * Adds the navigation bar header to the documentation tree.
-     *
-     * @param header the document tree to which the navigation bar header will be added
-     */
-    protected abstract void addNavigationBarHeader(Content header);
-
-    /**
-     * Adds the navigation bar footer to the documentation tree.
-     *
-     * @param footer the document tree to which the navigation bar footer will be added
-     */
-    protected abstract void addNavigationBarFooter(Content footer);
-
-    /**
-     * Adds the overview header to the documentation tree.
-     *
-     * @param main the document tree to which the overview header will be added
-     */
-    protected abstract void addOverviewHeader(Content main);
-
-    /**
-     * Adds the modules list to the documentation tree.
-     *
-     * @param main the document tree to which the modules list will be added
-     */
-    protected abstract void addModulesList(Content main);
-
-    /**
-     * Adds the module packages list to the documentation tree.
-     *
-     * @param modules the set of modules
-     * @param text caption for the table
-     * @param tableSummary summary for the table
-     * @param main the document tree to which the modules list will be added
-     * @param mdle the module being documented
-     */
-    protected abstract void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
-            String tableSummary, Content main, ModuleElement mdle);
-
-    /**
-     * Generate and prints the contents in the module index file.
-     *
-     * @param title the title of the window
-     * @param description the content for the description META tag
-     * @throws DocFileIOException if there is a problem building the module index file
-     */
-    protected void buildModuleIndexFile(String title, String description)
-            throws DocFileIOException {
-        String windowOverview = resources.getText(title);
-        Content body = getBody(getWindowTitle(windowOverview));
-        Content header = HtmlTree.HEADER();
-        addNavigationBarHeader(header);
-        Content main = HtmlTree.MAIN();
-        addOverviewHeader(main);
-        addIndex(header, main);
-        addOverview(main);
-        Content footer = HtmlTree.FOOTER();
-        addNavigationBarFooter(footer);
-        body.add(header);
-        body.add(main);
-        body.add(footer);
-        printHtmlDocument(
-                configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
-                description,
-                body);
-    }
-
-    /**
-     * Generate and prints the contents in the module packages index file.
-     *
-     * @param title the title of the window.
-     * @param description the content for the description META tag
-     * @param mdle the name of the module being documented
-     * @throws DocFileIOException if there is an exception building the module packages index file
-     */
-    protected void buildModulePackagesIndexFile(String title, String description,
-             ModuleElement mdle) throws DocFileIOException {
-        String windowOverview = resources.getText(title);
-        Content body = getBody(getWindowTitle(windowOverview));
-        Content header = HtmlTree.HEADER();
-        addNavigationBarHeader(header);
-        Content main = HtmlTree.MAIN();
-        addOverviewHeader(main);
-        addModulePackagesIndex(header, main, mdle);
-        addOverview(main);
-        Content footer = HtmlTree.FOOTER();
-        addNavigationBarFooter(footer);
-        body.add(header);
-        body.add(main);
-        body.add(footer);
-        printHtmlDocument(
-                configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
-                description,
-                body);
-    }
-
-    /**
-     * Default to no overview, override to add overview.
-     *
-     * @param main the document tree to which the overview will be added
-     */
-    protected void addOverview(Content main) { }
-
-    /**
-     * Adds the module index to the documentation tree.
-     *
-     * @param header the document tree to which the navigational links will be added
-     * @param main the document tree to which the modules list will be added
-     */
-    protected void addIndex(Content header, Content main) {
-        addIndexContents(configuration.modules, "doclet.Module_Summary",
-                resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Module_Summary"),
-                resources.getText("doclet.modules")), header, main);
-    }
-
-    /**
-     * Adds the module packages index to the documentation tree.
-     *
-     * @param header the document tree to which the navigational links will be added
-     * @param main the document tree to which the module packages list will be added
-     * @param mdle the module being documented
-     */
-    protected void addModulePackagesIndex(Content header, Content main, ModuleElement mdle) {
-        addModulePackagesIndexContents("doclet.Module_Summary",
-                resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Module_Summary"),
-                resources.getText("doclet.modules")), header, main, mdle);
-    }
-
-    /**
-     * Adds module index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param modules the modules to be documented
-     * @param text string which will be used as the heading
-     * @param tableSummary summary for the table
-     * @param header the document tree to which the navigational links will be added
-     * @param main the document tree to which the modules list will be added
-     */
-    protected void addIndexContents(Collection<ModuleElement> modules, String text,
-            String tableSummary, Content header, Content main) {
-        addModulesList(main);
-    }
-
-    /**
-     * Adds module packages index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param text string which will be used as the heading
-     * @param tableSummary summary for the table
-     * @param header the document tree to which the navigational links will be added
-     * @param main the document tree to which the module packages list will be added
-     * @param mdle the module being documented
-     */
-    protected void addModulePackagesIndexContents(String text,
-            String tableSummary, Content header, Content main, ModuleElement mdle) {
-        addModulePackagesList(modules, text, tableSummary, main, mdle);
-    }
-
-    /**
-     * Adds the doctitle to the documentation tree, if it is specified on the command line.
-     *
-     * @param body the document tree to which the title will be added
-     */
-    protected void addConfigurationTitle(Content body) {
-        if (configuration.doctitle.length() > 0) {
-            Content title = new RawHtml(configuration.doctitle);
-            Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
-                    HtmlStyle.title, title);
-            Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-            body.add(div);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,165 @@
+/*
+ * 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;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
+import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+
+/**
+ * Abstract class to generate the overview files.
+ *
+ *  <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 abstract class AbstractOverviewIndexWriter extends HtmlDocletWriter {
+
+    protected Navigation navBar;
+
+    /**
+     * Constructs the AbstractOverviewIndexWriter.
+     *
+     * @param configuration  The current configuration
+     * @param filename Name of the module index file to be generated.
+     */
+    public AbstractOverviewIndexWriter(HtmlConfiguration configuration,
+                                      DocPath filename) {
+        super(configuration, filename);
+        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
+    }
+
+    /**
+     * Adds the top text (from the -top option), the upper
+     * navigation bar, and then the title (from the"-title"
+     * option), at the top of page.
+     *
+     * @param header the documentation tree to which the navigation bar header will be added
+     */
+    protected void addNavigationBarHeader(Content header) {
+        addTop(header);
+        navBar.setUserHeader(getUserHeaderFooter(true));
+        header.add(navBar.getContent(true));
+    }
+
+    /**
+     * Adds the lower navigation bar and the bottom text
+     * (from the -bottom option) at the bottom of page.
+     *
+     * @param footer the documentation tree to which the navigation bar footer will be added
+     */
+    protected void addNavigationBarFooter(Content footer) {
+        navBar.setUserFooter(getUserHeaderFooter(false));
+        footer.add(navBar.getContent(false));
+        addBottom(footer);
+    }
+
+    /**
+     * Adds the overview summary comment for this documentation. Add one line
+     * summary at the top of the page and generate a link to the description,
+     * which is added at the end of this page.
+     *
+     * @param main the documentation tree to which the overview header will be added
+     */
+    protected void addOverviewHeader(Content main) {
+        addConfigurationTitle(main);
+        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
+            HtmlTree div = new HtmlTree(HtmlTag.DIV);
+            div.setStyle(HtmlStyle.contentContainer);
+            addOverviewComment(div);
+            main.add(div);
+        }
+    }
+
+    /**
+     * Adds the overview comment as provided in the file specified by the
+     * "-overview" option on the command line.
+     *
+     * @param htmltree the documentation tree to which the overview comment will
+     *                 be added
+     */
+    protected void addOverviewComment(Content htmltree) {
+        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
+            addInlineComment(configuration.overviewElement, htmltree);
+        }
+    }
+
+    /**
+     * Generate and prints the contents in the index file.
+     *
+     * @param title the title of the window
+     * @param description the content for the description META tag
+     * @throws DocFileIOException if there is a problem building the package index file
+     */
+    protected void buildOverviewIndexFile(String title, String description)
+            throws DocFileIOException {
+        String windowOverview = resources.getText(title);
+        Content body = getBody(getWindowTitle(windowOverview));
+        Content header = HtmlTree.HEADER();
+        addNavigationBarHeader(header);
+        Content main = HtmlTree.MAIN();
+        addOverviewHeader(main);
+        addIndex(main);
+        Content footer = HtmlTree.FOOTER();
+        addNavigationBarFooter(footer);
+        body.add(header);
+        body.add(main);
+        body.add(footer);
+        printHtmlDocument(
+                configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
+                description, body);
+    }
+
+    /**
+     * Adds the index to the documentation tree.
+     *
+     * @param main the document tree to which the packages/modules list will be added
+     */
+    protected abstract void addIndex(Content main);
+
+    /**
+     * Adds the doctitle to the documentation tree, if it is specified on the command line.
+     *
+     * @param body the document tree to which the title will be added
+     */
+    protected void addConfigurationTitle(Content body) {
+        if (configuration.doctitle.length() > 0) {
+            Content title = new RawHtml(configuration.doctitle);
+            Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
+                    HtmlStyle.title, title);
+            Content div = HtmlTree.DIV(HtmlStyle.header, heading);
+            body.add(div);
+        }
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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;
-
-import java.util.*;
-
-import javax.lang.model.element.PackageElement;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-
-/**
- * Abstract class to generate the overview files. This will be sub-classed to
- * generate overview-summary.html.
- *
- *  <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>
- *
- * @author Atul M Dambalkar
- * @author Bhavesh Patel (Modified)
- */
-public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter {
-
-    /**
-     * A Set of Packages to be documented.
-     */
-    protected SortedSet<PackageElement> packages;
-
-    protected Navigation navBar;
-
-    /**
-     * Constructor. Also initializes the packages variable.
-     *
-     * @param configuration  The current configuration
-     * @param filename Name of the package index file to be generated.
-     */
-    public AbstractPackageIndexWriter(HtmlConfiguration configuration,
-                                      DocPath filename) {
-        super(configuration, filename);
-        packages = configuration.packages;
-        this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
-    }
-
-    /**
-     * Adds the navigation bar header to the documentation tree.
-     *
-     * @param header the document tree to which the navigation bar header will be added
-     */
-    protected abstract void addNavigationBarHeader(Content header);
-
-    /**
-     * Adds the navigation bar footer to the documentation tree.
-     *
-     * @param body the document tree to which the navigation bar footer will be added
-     */
-    protected abstract void addNavigationBarFooter(Content body);
-
-    /**
-     * Adds the overview header to the documentation tree.
-     *
-     * @param footer the document tree to which the overview header will be added
-     */
-    protected abstract void addOverviewHeader(Content footer);
-
-    /**
-     * Adds the packages list to the documentation tree.
-     *
-     * @param main the document tree to which the packages list will be added
-     */
-    protected abstract void addPackagesList(Content main);
-
-    /**
-     * Generate and prints the contents in the package index file.
-     *
-     * @param title the title of the window
-     * @param description the content for the description META tag
-     * @throws DocFileIOException if there is a problem building the package index file
-     */
-    protected void buildPackageIndexFile(String title, String description)
-            throws DocFileIOException {
-        String windowOverview = resources.getText(title);
-        Content body = getBody(getWindowTitle(windowOverview));
-        Content header = HtmlTree.HEADER();
-        addNavigationBarHeader(header);
-        Content main = HtmlTree.MAIN();
-        addOverviewHeader(main);
-        addIndex(header, main);
-        addOverview(main);
-        Content footer = HtmlTree.FOOTER();
-        addNavigationBarFooter(footer);
-        body.add(header);
-        body.add(main);
-        body.add(footer);
-        printHtmlDocument(
-                configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
-                description, body);
-    }
-
-    /**
-     * Default to no overview, override to add overview.
-     *
-     * @param main the document tree to which the overview will be added
-     */
-    protected void addOverview(Content main) { }
-
-    /**
-     * Adds the package index to the documentation tree.
-     *
-     * @param header the document tree to which the navigation links will be added
-     * @param main the document tree to which the packages list will be added
-     */
-    protected void addIndex(Content header, Content main) {
-        addIndexContents(header, main);
-    }
-
-    /**
-     * Adds package index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param header the document tree to which navigation links will be added
-     * @param main the document tree to which the packages list will be added
-     */
-    protected void addIndexContents(Content header, Content main) {
-        if (!packages.isEmpty()) {
-            HtmlTree htmlTree = HtmlTree.NAV();
-            htmlTree.setStyle(HtmlStyle.indexNav);
-            HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            addAllClassesLink(ul);
-            if (configuration.showModules  && configuration.modules.size() > 1) {
-                addAllModulesLink(ul);
-            }
-            htmlTree.add(ul);
-            header.add(htmlTree);
-            addPackagesList(main);
-        }
-    }
-
-    /**
-     * Adds the doctitle to the documentation tree, if it is specified on the command line.
-     *
-     * @param body the document tree to which the title will be added
-     */
-    protected void addConfigurationTitle(Content body) {
-        if (configuration.doctitle.length() > 0) {
-            Content title = new RawHtml(configuration.doctitle);
-            Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
-                    HtmlStyle.title, title);
-            Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-            body.add(div);
-        }
-    }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param div the document tree to which the all classes link will be added
-     */
-    protected void addAllClassesLink(Content div) {
-    }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param div the document tree to which the all modules link will be added
-     */
-    protected void addAllModulesLink(Content div) {
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -53,15 +53,22 @@
  *
  * @author Bhavesh Patel
  */
-public class ModuleIndexWriter extends AbstractModuleIndexWriter {
+public class ModuleIndexWriter extends AbstractOverviewIndexWriter {
+
+    /**
+     * Modules to be documented.
+     */
+    protected SortedSet<ModuleElement> modules;
 
     /**
      * Construct the ModuleIndexWriter.
+     *
      * @param configuration the configuration object
      * @param filename the name of the generated file
      */
     public ModuleIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
+        modules = configuration.modules;
     }
 
     /**
@@ -73,46 +80,23 @@
     public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
         DocPath filename = DocPaths.INDEX;
         ModuleIndexWriter mdlgen = new ModuleIndexWriter(configuration, filename);
-        mdlgen.buildModuleIndexFile("doclet.Window_Overview_Summary", "module index");
-    }
-
-    /**
-     * Add the module index.
-     *
-     * @param header the documentation tree to which the navigational links will be added
-     * @param main the documentation tree to which the modules list will be added
-     */
-    @Override
-    protected void addIndex(Content header, Content main) {
-        addIndexContents(header, main);
+        mdlgen.buildOverviewIndexFile("doclet.Window_Overview_Summary", "module index");
     }
 
     /**
-     * Adds module index contents.
+     * Adds the list of modules.
      *
-     * @param header the document tree to which the navigational links will be added
-     * @param main the document tree to which the modules list will be added
-     */
-    protected void addIndexContents(Content header, Content main) {
-        addModulesList(main);
-    }
-
-    /**
-     * Add the list of modules.
-     *
-     * @param main the content tree to which the module list will be added
+     * @param main the documentation tree to which the modules list will be added
      */
     @Override
-    protected void addModulesList(Content main) {
+    protected void addIndex(Content main) {
         Map<String, SortedSet<ModuleElement>> groupModuleMap
-                = configuration.group.groupModules(configuration.modules);
+                = configuration.group.groupModules(modules);
 
         if (!groupModuleMap.keySet().isEmpty()) {
-            String tableSummary = resources.getText("doclet.Member_Table_Summary",
-                    resources.getText("doclet.Module_Summary"), resources.getText("doclet.modules"));
-            TableHeader header = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
+            TableHeader tableHeader = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
             Table table =  new Table(HtmlStyle.overviewSummary)
-                    .setHeader(header)
+                    .setHeader(tableHeader)
                     .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
                     .setDefaultTab(resources.getText("doclet.All_Modules"))
                     .setTabScript(i -> "show(" + i + ");")
@@ -126,7 +110,7 @@
                 }
             }
 
-            for (ModuleElement mdle : configuration.modules) {
+            for (ModuleElement mdle : modules) {
                 if (!mdle.isUnnamed()) {
                     if (!(configuration.nodeprecated && utils.isDeprecated(mdle))) {
                         Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
@@ -145,67 +129,4 @@
             }
         }
     }
-
-    /**
-     * Adds the overview summary comment for this documentation. Add one line
-     * summary at the top of the page and generate a link to the description,
-     * which is added at the end of this page.
-     *
-     * @param main the documentation tree to which the overview header will be added
-     */
-    @Override
-    protected void addOverviewHeader(Content main) {
-        addConfigurationTitle(main);
-        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.setStyle(HtmlStyle.contentContainer);
-            addOverviewComment(div);
-            main.add(div);
-        }
-    }
-
-    /**
-     * Adds the overview comment as provided in the file specified by the
-     * "-overview" option on the command line.
-     *
-     * @param htmltree the documentation tree to which the overview comment will
-     *                 be added
-     */
-    protected void addOverviewComment(Content htmltree) {
-        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
-            addInlineComment(configuration.overviewElement, htmltree);
-        }
-    }
-
-    /**
-     * Adds the top text (from the -top option), the upper
-     * navigation bar, and then the title (from the"-title"
-     * option), at the top of page.
-     *
-     * @param header the documentation tree to which the navigation bar header will be added
-     */
-    @Override
-    protected void addNavigationBarHeader(Content header) {
-        addTop(header);
-        navBar.setUserHeader(getUserHeaderFooter(true));
-        header.add(navBar.getContent(true));
-    }
-
-    /**
-     * Adds the lower navigation bar and the bottom text
-     * (from the -bottom option) at the bottom of page.
-     *
-     * @param footer the documentation tree to which the navigation bar footer will be added
-     */
-    @Override
-    protected void addNavigationBarFooter(Content footer) {
-        navBar.setUserFooter(getUserHeaderFooter(false));
-        footer.add(navBar.getContent(false));
-        addBottom(footer);
-    }
-
-    @Override
-    protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
-            String tableSummary, Content main, ModuleElement mdle) {
-    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -52,7 +52,12 @@
  * @author Atul M Dambalkar
  * @author Bhavesh Patel (Modified)
  */
-public class PackageIndexWriter extends AbstractPackageIndexWriter {
+public class PackageIndexWriter extends AbstractOverviewIndexWriter {
+
+    /**
+     * A Set of Packages to be documented.
+     */
+    protected SortedSet<PackageElement> packages;
 
     /**
      * Construct the PackageIndexWriter. Also constructs the grouping
@@ -65,6 +70,7 @@
      */
     public PackageIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
+        packages = configuration.packages;
     }
 
     /**
@@ -76,26 +82,16 @@
     public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
         DocPath filename = DocPaths.INDEX;
         PackageIndexWriter packgen = new PackageIndexWriter(configuration, filename);
-        packgen.buildPackageIndexFile("doclet.Window_Overview_Summary", "package index");
+        packgen.buildOverviewIndexFile("doclet.Window_Overview_Summary", "package index");
     }
 
     /**
-     * Depending upon the grouping information and their titles, add
-     * separate table indices for each package group.
+     * Adds the packages list to the documentation tree.
      *
-     * @param header the documentation tree to which the navigational links will be added
      * @param main the documentation tree to which the packages list will be added
      */
     @Override
-    protected void addIndex(Content header, Content main) {
-        addIndexContents(header, main);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void addPackagesList(Content main) {
+    protected void addIndex(Content main) {
         Map<String, SortedSet<PackageElement>> groupPackageMap
                 = configuration.group.groupPackages(packages);
 
@@ -134,62 +130,4 @@
             }
         }
     }
-
-    /**
-     * Adds the overview summary comment for this documentation. Add one line
-     * summary at the top of the page and generate a link to the description,
-     * which is added at the end of this page.
-     *
-     * @param main the documentation tree to which the overview header will be added
-     */
-    @Override
-    protected void addOverviewHeader(Content main) {
-        addConfigurationTitle(main);
-        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.setStyle(HtmlStyle.contentContainer);
-            addOverviewComment(div);
-            main.add(div);
-        }
-    }
-
-    /**
-     * Adds the overview comment as provided in the file specified by the
-     * "-overview" option on the command line.
-     *
-     * @param htmltree the documentation tree to which the overview comment will
-     *                 be added
-     */
-    protected void addOverviewComment(Content htmltree) {
-        if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
-            addInlineComment(configuration.overviewElement, htmltree);
-        }
-    }
-
-    /**
-     * Adds the top text (from the -top option), the upper
-     * navigation bar, and then the title (from the"-title"
-     * option), at the top of page.
-     *
-     * @param header the documentation tree to which the navigation bar header will be added
-     */
-    @Override
-    protected void addNavigationBarHeader(Content header) {
-        addTop(header);
-        navBar.setUserHeader(getUserHeaderFooter(true));
-        header.add(navBar.getContent(true));
-    }
-
-    /**
-     * Adds the lower navigation bar and the bottom text
-     * (from the -bottom option) at the bottom of page.
-     *
-     * @param footer the documentation tree to which the navigation bar footer will be added
-     */
-    @Override
-    protected void addNavigationBarFooter(Content footer) {
-        navBar.setUserFooter(getUserHeaderFooter(false));
-        footer.add(navBar.getContent(false));
-        addBottom(footer);
-    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Fri Apr 19 08:00:42 2019 -0400
@@ -98,7 +98,6 @@
 doclet.From=From
 doclet.Uses_Summary=Uses
 doclet.Provides_Summary=Provides
-doclet.Module_Summary=Module Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
 doclet.Enum_Summary=Enum Summary
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Fri Apr 19 08:00:42 2019 -0400
@@ -374,7 +374,7 @@
 
         // locale, doclet and maybe taglet, needs to be determined first
         try {
-            docletClass = preprocess(fileManager, options);
+            doclet = preprocess(fileManager, options);
         } catch (ToolException te) {
             if (!te.result.isOK()) {
                 if (te.message != null) {
@@ -393,24 +393,6 @@
             dumpStack(t == null ? oe : t);
             return oe.result;
         }
-        if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
-            // no need to dispatch to old, safe to init now
-            initMessager();
-            messager.setLocale(locale);
-            try {
-                Object o = docletClass.getConstructor().newInstance();
-                doclet = (Doclet) o;
-            } catch (ReflectiveOperationException exc) {
-                if (apiMode) {
-                    throw new ClientCodeException(exc);
-                }
-                error("main.could_not_instantiate_class", docletClass.getName());
-                return ERROR;
-            }
-        } else {
-            error("main.not_a_doclet", docletClass.getName());
-            return ERROR;
-        }
 
         Result result = OK;
         try {
@@ -649,7 +631,7 @@
         return idx;
     }
 
-    private Class<?> preprocess(JavaFileManager jfm,
+    private Doclet preprocess(JavaFileManager jfm,
             List<String> argv) throws ToolException, OptionException {
         // doclet specifying arguments
         String userDocletPath = null;
@@ -706,71 +688,77 @@
             }
         }
 
-        // Step 2: a doclet is provided, nothing more to do.
-        if (docletClass != null) {
-            return docletClass;
-        }
 
         // Step 3: doclet name specified ? if so find a ClassLoader,
         // and load it.
-        if (userDocletName != null) {
-            ClassLoader cl = classLoader;
-            if (cl == null) {
-                if (!fileManager.hasLocation(DOCLET_PATH)) {
-                    List<File> paths = new ArrayList<>();
-                    if (userDocletPath != null) {
-                        for (String pathname : userDocletPath.split(File.pathSeparator)) {
-                            paths.add(new File(pathname));
+        if(docletClass == null) {
+            if (userDocletName != null) {
+                ClassLoader cl = classLoader;
+                if (cl == null) {
+                    if (!fileManager.hasLocation(DOCLET_PATH)) {
+                        List<File> paths = new ArrayList<>();
+                        if (userDocletPath != null) {
+                            for (String pathname : userDocletPath.split(File.pathSeparator)) {
+                                paths.add(new File(pathname));
+                            }
+                        }
+                        try {
+                            ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
+                        } catch (IOException ioe) {
+                            if (apiMode) {
+                                throw new IllegalArgumentException("Could not set location for " +
+                                        userDocletPath, ioe);
+                            }
+                            String text = messager.getText("main.doclet_could_not_set_location",
+                                    userDocletPath);
+                            throw new ToolException(CMDERR, text, ioe);
                         }
                     }
-                    try {
-                        ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
-                    } catch (IOException ioe) {
+                    cl = fileManager.getClassLoader(DOCLET_PATH);
+                    if (cl == null) {
+                        // despite doclet specified on cmdline no classloader found!
                         if (apiMode) {
-                            throw new IllegalArgumentException("Could not set location for " +
-                                    userDocletPath, ioe);
+                            throw new IllegalArgumentException("Could not obtain classloader to load "
+
+                                    + userDocletPath);
                         }
-                        String text = messager.getText("main.doclet_could_not_set_location",
-                                userDocletPath);
-                        throw new ToolException(CMDERR, text, ioe);
+                        String text = messager.getText("main.doclet_no_classloader_found",
+                                userDocletName);
+                        throw new ToolException(CMDERR, text);
                     }
                 }
-                cl = fileManager.getClassLoader(DOCLET_PATH);
-                if (cl == null) {
-                    // despite doclet specified on cmdline no classloader found!
-                    if (apiMode) {
-                        throw new IllegalArgumentException("Could not obtain classloader to load "
-                                + userDocletPath);
-                    }
-                    String text = messager.getText("main.doclet_no_classloader_found",
-                            userDocletName);
-                    throw new ToolException(CMDERR, text);
-                }
-            }
-            try {
-                return cl.loadClass(userDocletName);
-            } catch (ClassNotFoundException cnfe) {
-                if (apiMode) {
-                    throw new IllegalArgumentException("Cannot find doclet class " + userDocletName,
-                            cnfe);
-                }
-                String text = messager.getText("main.doclet_class_not_found", userDocletName);
-                throw new ToolException(CMDERR, text, cnfe);
+                docletClass = loadDocletClass(userDocletName, cl);
+            } else if (docletName != null){
+                docletClass = loadDocletClass(docletName, getClass().getClassLoader());
+            } else {
+                docletClass = StdDoclet;
             }
         }
 
-        // Step 4: we have a doclet, try loading it
-        if (docletName != null) {
-            return loadDocletClass(docletName);
+        if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
+            // no need to dispatch to old, safe to init now
+            initMessager();
+            messager.setLocale(locale);
+            try {
+                Object o = docletClass.getConstructor().newInstance();
+                doclet = (Doclet) o;
+            } catch (ReflectiveOperationException exc) {
+                if (apiMode) {
+                    throw new ClientCodeException(exc);
+                }
+                String text = messager.getText("main.could_not_instantiate_class", docletClass.getName());
+                throw new ToolException(ERROR, text);
+            }
+        } else {
+            String text = messager.getText("main.not_a_doclet", docletClass.getName());
+            throw new ToolException(ERROR, text);
         }
-
-        // finally
-        return StdDoclet;
+        return doclet;
     }
 
-    private Class<?> loadDocletClass(String docletName) throws ToolException {
+    private Class<?> loadDocletClass(String docletName, ClassLoader classLoader) throws ToolException {
         try {
-            return Class.forName(docletName, true, getClass().getClassLoader());
+            return classLoader == null ? Class.forName(docletName) : classLoader.loadClass(docletName);
         } catch (ClassNotFoundException cnfe) {
             if (apiMode) {
                 throw new IllegalArgumentException("Cannot find doclet class " + docletName);
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package sun.tools.jcmd;
 
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
@@ -121,15 +122,16 @@
             if (line.trim().equals("stop")) {
                 break;
             }
-            try (InputStream in = hvm.executeJCmd(line);) {
+            try (InputStream in = hvm.executeJCmd(line);
+                 InputStreamReader isr = new InputStreamReader(in, "UTF-8")) {
                 // read to EOF and just print output
-                byte b[] = new byte[256];
+                char c[] = new char[256];
                 int n;
                 boolean messagePrinted = false;
                 do {
-                    n = in.read(b);
+                    n = isr.read(c);
                     if (n > 0) {
-                        String s = new String(b, 0, n, "UTF-8");
+                        String s = new String(c, 0, n);
                         System.out.print(s);
                         messagePrinted = true;
                     }
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NameCodec.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NameCodec.java	Fri Apr 19 08:00:42 2019 -0400
@@ -39,11 +39,11 @@
  * to nashorn module.
  * </p>
  *
- * <h3>Comment from BytecodeName class reproduced here:</h3>
+ * <h2>Comment from BytecodeName class reproduced here:</h2>
  *
  * Includes universal mangling rules for the JVM.
  *
- * <h3>Avoiding Dangerous Characters </h3>
+ * <h2>Avoiding Dangerous Characters </h2>
  *
  * <p>
  * The JVM defines a very small set of characters which are illegal
@@ -74,7 +74,7 @@
  * but traditional in the proposed role.
  *
  * </p>
- * <h3> Replacement Characters </h3>
+ * <h2> Replacement Characters </h2>
  *
  *
  * <p>
@@ -159,7 +159,7 @@
  * to check for dangerous characters.
  *
  * </p>
- * <h3> Nice Properties </h3>
+ * <h2> Nice Properties </h2>
  *
  * <p>
  * If a bytecode name does not contain any escape sequence,
@@ -222,7 +222,7 @@
  * </ul>
  *
  *
- * <h3> Suggestions for Human Readable Presentations </h3>
+ * <h2> Suggestions for Human Readable Presentations </h2>
  *
  *
  * <p>
--- a/src/jdk.scripting.nashorn/share/classes/module-info.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.scripting.nashorn/share/classes/module-info.java	Fri Apr 19 08:00:42 2019 -0400
@@ -30,7 +30,7 @@
  * Nashorn is a runtime environment for programs written in ECMAScript 5.1.
  * </p>
  *
- * <h1>Usage</h1>
+ * <h2>Usage</h2>
  *
  * The recommended way to use Nashorn is through the
  * <a href="http://jcp.org/en/jsr/detail?id=223" target="_top">JSR-223
@@ -45,7 +45,7 @@
  *
  * and then use it just as you would any other JSR-223 script engine. See
  * {@link jdk.nashorn.api.scripting} package for details.
- * <h1>Compatibility</h1>
+ * <h2>Compatibility</h2>
  * Nashorn is 100% compliant with the
  * <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"
  * target="_top">ECMA-262 Standard, Edition 5.1</a>.
@@ -55,7 +55,7 @@
  * specification (often referred to as "invokedynamic"), as well as
  * the already mentioned JSR-223.
  *
- * <h1>Interoperability with the Java platform</h1>
+ * <h2>Interoperability with the Java platform</h2>
  *
  * In addition to being a 100% ECMAScript 5.1 runtime, Nashorn provides features
  * for interoperability of the ECMAScript programs with the Java platform.
@@ -68,7 +68,7 @@
  * their properties. In most cases, though, you can't add arbitrary properties
  * to them, nor can you remove existing properties.
  *
- * <h2>Java collection handling</h2>
+ * <h3>Java collection handling</h3>
  *
  * Native Java arrays and {@link java.util.List}s support indexed access to
  * their elements through the property accessors, and {@link java.util.Map}s
@@ -79,7 +79,7 @@
  * operator gives precedence to map elements. Native Java arrays expose
  * the {@code length} property.
  *
- * <h2>ECMAScript primitive types</h2>
+ * <h3>ECMAScript primitive types</h3>
  *
  * ECMAScript primitive types for number, string, and boolean are represented
  * with {@link java.lang.Number}, {@link java.lang.CharSequence}, and
@@ -89,7 +89,7 @@
  * cause other subclasses of {@code Number} and internal implementations of
  * {@code CharSequence} to be used.
  *
- * <h2>Type conversions</h2>
+ * <h3>Type conversions</h3>
  *
  * When a method on a Java object is invoked, the arguments are converted to
  * the formal parameter types of the Java method using all allowed ECMAScript
@@ -106,7 +106,7 @@
  * {@code java.lang.Double}), then Nashorn will of course ensure
  * the required type is passed.
  *
- * <h2>SAM types</h2>
+ * <h3>SAM types</h3>
  *
  * As a special extension when invoking Java methods, ECMAScript function
  * objects can be passed in place of an argument whose Java type is so-called
@@ -122,14 +122,14 @@
  * the same name</em>. This is done to be consistent with the fact that
  * ECMAScript does not have the concept of overloaded methods.
  *
- * <h2>The {@code Java} object</h2>
+ * <h3>The {@code Java} object</h3>
  *
  * Nashorn exposes a non-standard global object named {@code Java} that is
  * the primary API entry point into Java platform-specific functionality.
  * You can use it to create instances of Java classes, convert from Java arrays
  * to native arrays and back, and so on.
  *
- * <h2>Other non-standard built-in objects</h2>
+ * <h3>Other non-standard built-in objects</h3>
  *
  * In addition to {@code Java}, Nashorn also exposes some other
  * non-standard built-in objects:
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Fri Apr 19 08:00:42 2019 -0400
@@ -218,6 +218,9 @@
 
 compiler/jsr292/InvokerSignatureMismatch.java           8221577   generic-all
 
+compiler/arguments/TestScavengeRootsInCode.java         8207267   generic-all
+compiler/loopopts/TestOverunrolling.java                8207267   generic-all
+
 # Graal unit tests
 org.graalvm.compiler.core.test.CheckGraalInvariants                              8205081
 org.graalvm.compiler.core.test.OptionsVerifierTest                               8205081
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/containers/docker/JfrNetwork.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.file.Paths;
+import java.util.List;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordingFile;
+import jdk.test.lib.process.OutputAnalyzer;
+
+
+// This class is intended to run inside a container
+public class JfrNetwork {
+    // use a unique hostname for container
+    public static final String HOST_NAME = "container-unique-8221711";
+    public static final String JFR_REPORTED_CONTAINER_HOSTNAME_TAG = "jfr_reported_container_hostname=";
+
+    public static void main(String[] args) throws Exception {
+        String event = args[0];
+        try (ServerSocket ss = new ServerSocket()) {
+            testNetworkInfo(ss, event);
+        }
+    }
+
+    private static void assertTrue(boolean expr, String msg) {
+        if (!expr) {
+            throw new RuntimeException(msg);
+        }
+    }
+
+    private static void testNetworkInfo(ServerSocket ss, String event) throws Exception {
+        ServerSocketListener server = new ServerSocketListener(ss);
+        server.start();
+        SocketWriter writer = new SocketWriter(ss.getLocalSocketAddress());
+
+        // setup and start the recording
+        String recordingPath = event + ".jfr";
+        log("========= Recording event: " + event);
+        Recording r = new Recording();
+        r.enable(event);
+        r.setDestination(Paths.get("/", "tmp", recordingPath));
+        r.start();
+
+        // start the socker writer thread, write some data into the socket
+        writer.start();
+
+        // wait for writer thread to terminate, then for server thread, then stop recording
+        writer.joinAndThrow();
+        server.joinAndThrow();
+        r.stop();
+
+        // analyze the recording
+        List<RecordedEvent> events = RecordingFile.readAllEvents(r.getDestination());
+        events.forEach(e -> log ("event = " + e));
+        assertTrue(!events.isEmpty(), "No recorded network events");
+        RecordedEvent e = events.get(0);
+        log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host"));
+        verifyIpAddress(e.getString("address"));
+    }
+
+    private static void verifyIpAddress(String eventIp) throws Exception {
+        ProcessBuilder pb = new ProcessBuilder("hostname", "--ip-address");
+        OutputAnalyzer out = new OutputAnalyzer(pb.start());
+        out.shouldHaveExitValue(0);
+        log("hostname --ip-address returned: " + out.getOutput());
+        out.shouldContain(eventIp);
+    }
+
+    private static void log(String msg) {
+        System.out.println(msg);
+    }
+
+
+    private static class ServerSocketListener extends Thread {
+        Exception exception;
+        ServerSocket ss;
+
+        ServerSocketListener(ServerSocket socket) throws Exception {
+            ss = socket;
+            ss.setReuseAddress(true);
+            ss.bind(null);
+            log("ServerSocker Local Address: " + ss.getLocalSocketAddress());
+        }
+
+        public void joinAndThrow() throws Exception {
+            join();
+            if (exception != null) {
+                throw exception;
+            }
+        }
+
+        public void run() {
+            try {
+                try (Socket s = ss.accept(); InputStream is = s.getInputStream()) {
+                    System.out.println("ServerSocketListener: accepted socket connection: s = " + s);
+                    is.read();
+                    is.read();
+                    is.read();
+                }
+            } catch (Exception e) {
+                exception = e;
+            }
+        }
+    }
+
+
+    private static class SocketWriter extends Thread {
+        Exception exception;
+        private SocketAddress ssAddr;
+
+        public SocketWriter(SocketAddress sa) {
+            this.ssAddr = sa;
+            System.out.println("SocketWriter(): sa = " + sa);
+        }
+
+        public void joinAndThrow() throws Exception {
+            join();
+            if (exception != null) {
+                throw exception;
+            }
+        }
+
+        public void run() {
+            try (Socket s = new Socket()) {
+                s.connect(ssAddr);
+                try (OutputStream os = s.getOutputStream()) {
+                    os.write('A');
+                    os.write('B');
+                    os.write('C');
+                }
+            } catch (Exception e) {
+                exception = e;
+            }
+        }
+    }
+
+}
--- a/test/hotspot/jtreg/containers/docker/JfrReporter.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/containers/docker/JfrReporter.java	Fri Apr 19 08:00:42 2019 -0400
@@ -22,53 +22,30 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+import java.nio.file.Path;
 import java.nio.file.Paths;
 import jdk.jfr.Recording;
+import jdk.jfr.ValueDescriptor;
 import jdk.jfr.consumer.RecordedEvent;
 import jdk.jfr.consumer.RecordingFile;
 
-
 // This class is intended to run inside a container
 public class JfrReporter {
-    public static final String TEST_REPORTED_CORES="TEST_REPORTED_CORES";
-    public static final String TEST_REPORTED_MEMORY="TEST_REPORTED_MEMORY";
-    public static final String TEST_REPORTED_PID="TEST_REPORTED_PID";
-    public static final String TESTCASE_CPU="cpu";
-    public static final String TESTCASE_MEMORY="memory";
-    public static final String TESTCASE_PROCESS="process";
-
     public static void main(String[] args) throws Exception {
-        String testCase = args[0];
-        System.out.println("Testcase: " + testCase);
-        switch (testCase) {
-        case TESTCASE_CPU:
-            RecordedEvent event = testEvent("jdk.CPUInformation", "cpu.jfr");
-            System.out.println(TEST_REPORTED_CORES + "=" + event.getInt("cores"));
-            break;
-        case TESTCASE_MEMORY:
-            event = testEvent("jdk.PhysicalMemory", "memory.jfr");
-            System.out.println(TEST_REPORTED_MEMORY + "=" + event.getLong("totalSize"));
-            break;
-        case TESTCASE_PROCESS:
-            event = testEvent("jdk.SystemProcess", "process.jfr");
-            System.out.println(TEST_REPORTED_PID + "=" + event.getString("pid"));
-            break;
-        default:
-            throw new IllegalArgumentException("Invalid test case");
+        String eventName = args[0];
+        try(Recording r = new Recording()) {
+            r.enable(eventName);
+            r.start();
+            r.stop();
+            Path p = Paths.get("/", "tmp", eventName + ".jfr");
+            r.dump(p);
+            for (RecordedEvent e : RecordingFile.readAllEvents(p)) {
+                System.out.println("===== EventType: " + e.getEventType().getName());
+                for (ValueDescriptor v : e.getEventType().getFields()) {
+                    System.out.println(v.getName() + " = " + e.getValue(v.getName()));
+                }
+            }
         }
     }
-
-    private static RecordedEvent testEvent(String event, String recordingPath) throws Exception {
-        System.out.println("========= Testing event: " + event);
-        Recording r = new Recording();
-        r.enable(event);
-        r.setDestination(Paths.get("tmp", recordingPath));
-        r.start();
-        r.stop();
-
-        RecordedEvent recordedEvent = RecordingFile.readAllEvents(r.getDestination()).get(0);
-        System.out.println("RecordedEvent: " + recordedEvent);
-        return recordedEvent;
-    }
 }
+  
\ No newline at end of file
--- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java	Fri Apr 19 08:00:42 2019 -0400
@@ -39,6 +39,8 @@
 import jdk.test.lib.containers.docker.Common;
 import jdk.test.lib.containers.docker.DockerRunOptions;
 import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.Utils;
 
 
@@ -68,6 +70,7 @@
 
             testProcessInfo();
 
+            testEnvironmentVariables();
         } finally {
             DockerTestUtils.removeDockerImage(imageName);
         }
@@ -79,14 +82,12 @@
         DockerTestUtils.dockerRunJava(
                                       commonDockerOpts()
                                       .addDockerOpts("--cpus=" + valueToSet)
-                                      .addClassOptions(JfrReporter.TESTCASE_CPU))
-            .shouldHaveExitValue(0)
-            .shouldContain(JfrReporter.TEST_REPORTED_CORES);
-
+                                      .addClassOptions("jdk.CPUInformation"))
+            .shouldHaveExitValue(0);
         // The following assertion is currently disabled due to JFR reporting incorrect values.
         // JFR reports values for the host system as opposed to values for the container.
         // @ignore 8219999
-        // .shouldContain(JfrReporter.TEST_REPORTED_CORES + "=" + expectedValue);
+        // .shouldContain("cores = " + expectedValue");
     }
 
 
@@ -95,9 +96,9 @@
         DockerTestUtils.dockerRunJava(
                                       commonDockerOpts()
                                       .addDockerOpts("--memory=" + valueToSet)
-                                      .addClassOptions(JfrReporter.TESTCASE_MEMORY))
+                                      .addClassOptions("jdk.PhysicalMemory"))
             .shouldHaveExitValue(0)
-            .shouldContain(JfrReporter.TEST_REPORTED_MEMORY + "=" + expectedValue);
+            .shouldContain("totalSize = " + expectedValue);
     }
 
 
@@ -105,10 +106,9 @@
         Common.logNewTestCase("ProcessInfo");
         DockerTestUtils.dockerRunJava(
                                       commonDockerOpts()
-                                      .addClassOptions(JfrReporter.TESTCASE_PROCESS))
+                                      .addClassOptions("jdk.SystemProcess"))
             .shouldHaveExitValue(0)
-            .shouldContain(JfrReporter.TEST_REPORTED_PID + "=1");
-
+            .shouldContain("pid = 1");
     }
 
 
@@ -117,4 +117,28 @@
             .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
             .addJavaOpts("-cp", "/test-classes/");
     }
+
+
+    // JTReg always defines the environment variable JAVA_MAIN_CLASS_<SOME_NUMBER>.
+    // This variable fits well for use in this test, since it is rather unique.
+    private static String getTestEnvironmentVariable() throws Exception {
+        for (String key : System.getenv().keySet()) {
+            if (key.startsWith("JAVA_MAIN_CLASS")) {
+                return key;
+            }
+        }
+        throw new RuntimeException("JAVA_MAIN_CLASS_* is not defined");
+    }
+
+
+    private static void testEnvironmentVariables() throws Exception {
+        Common.logNewTestCase("EnvironmentVariables");
+
+        DockerTestUtils.dockerRunJava(
+                                      commonDockerOpts()
+                                      .addClassOptions("jdk.InitialEnvironmentVariable"))
+            .shouldHaveExitValue(0)
+            .shouldContain("key = JAVA_HOME")
+            .shouldNotContain(getTestEnvironmentVariable());
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @summary Test JFR network related events inside a container; make sure
+ *          the reported host ip and host name are correctly reported within
+ *          the container.
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build JfrNetwork
+ * @run driver TestJFRNetworkEvents
+ */
+import jdk.test.lib.containers.docker.Common;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Utils;
+
+
+public class TestJFRNetworkEvents {
+    private static final String imageName = Common.imageName("jfr-network");
+    private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
+        if (!DockerTestUtils.canTestDocker()) {
+            return;
+        }
+
+        DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+        try {
+            runTest("jdk.SocketWrite");
+        } finally {
+            DockerTestUtils.removeDockerImage(imageName);
+        }
+    }
+
+    private static void runTest(String event) throws Exception {
+        DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "JfrNetwork")
+        .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
+        .addJavaOpts("-cp", "/test-classes/")
+        .addDockerOpts("--hostname", JfrNetwork.HOST_NAME)
+        .addClassOptions(event);
+    DockerTestUtils.dockerRunJava(opts)
+        .shouldHaveExitValue(0)
+        .shouldContain(JfrNetwork.JFR_REPORTED_CONTAINER_HOSTNAME_TAG + JfrNetwork.HOST_NAME);
+    }
+}
--- a/test/hotspot/jtreg/runtime/ErrorHandling/ExplicitArithmeticCheck.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4221448
- * @summary Use explicit check for integer arithmetic exception on win32.
- */
-
-public class ExplicitArithmeticCheck {
-    public static void main(String argv[]) throws Exception {
-        for (int i = 0; i < 64; i++) {
-          boolean result = false;
-          int n;
-          try {
-              n = 0 / 0;
-          } catch (ArithmeticException e) {
-              result = true;
-          }
-          if (result == false) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          result = false;
-          try {
-              n = 0 % 0;
-          } catch (ArithmeticException e) {
-              result = true;
-          }
-          if (result == false) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          try {
-              n = 0x80000000 / -1;
-          } catch (Throwable t) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          if (n != 0x80000000) {
-            throw new Error("Incorrect integer arithmetic ! ");
-          }
-          try {
-              n = 0x80000000 % -1;
-          } catch (Throwable t) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          if (n != 0) {
-            throw new Error("Incorrect integer arithmetic!");
-          }
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java	Fri Apr 19 08:00:42 2019 -0400
@@ -33,10 +33,15 @@
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak
  */
 
+import java.io.*;
+import java.nio.file.*;
 import java.lang.invoke.*;
 import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Utils;
 import sun.hotspot.WhiteBox;
 import sun.hotspot.code.Compiler;
 import sun.hotspot.gc.GC;
@@ -47,6 +52,7 @@
     // The size of the ResolvedMethodTable is 1024. 2000 entries
     // is enough to trigger a grow/cleaning of the table after a GC.
     private static int methodCount = 2000;
+    public static ArrayList<MethodHandle> keepAlive;
 
     static class Leak {
       public void callMe() {
@@ -56,6 +62,8 @@
         Leak leak = new Leak();
         WhiteBox wb = WhiteBox.getWhiteBox();
 
+        keepAlive = new ArrayList<>(methodCount);
+
         ClassWithManyMethodsClassLoader classLoader = new ClassWithManyMethodsClassLoader();
         Class<?> clazz = classLoader.create(className, methodPrefix, methodCount);
 
@@ -74,14 +82,20 @@
           MethodHandle mh1 = lookup.findSpecial(clazz, methodName, mt, clazz);
 
           mh1.invoke(o);
+
+          keepAlive.add(mh1);
         }
 
         long after = wb.resolvedMethodItemsCount();
 
+        System.out.println("wb.resolvedMethodItemsCount() after setup: " + after);
+
         if (after == before) {
           throw new RuntimeException("Too few resolved methods");
         }
 
+        keepAlive = null;
+
         // Wait until ServiceThread cleans ResolvedMethod table
         int cnt = 0;
         while (true) {
@@ -99,27 +113,48 @@
       }
     }
 
+    private static Path createGcLogPath(String prefix) throws IOException {
+        Path gcLog = Utils.createTempFile(prefix, "log");
+        Files.delete(gcLog);
+        return gcLog;
+    }
+
+    private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
     public static void test(GC gc, boolean doConcurrent) throws Throwable {
-        System.err.println("test(" + gc + ", " + doConcurrent + ")");
+        Path gcLogPath = createGcLogPath("gc." + gc + "." + doConcurrent);
+        System.err.println("test(" + gc + ", " + doConcurrent + ")" + " " + dateFormat.format(new Date()));
         // Run this Leak class with logging
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-                                      "-Xlog:membername+table=trace",
+                                      "-Xlog:membername+table=trace,gc+verify=debug,gc:" + gcLogPath + ":time,utctime,uptime,pid,level,tags",
                                       "-XX:+UnlockExperimentalVMOptions",
                                       "-XX:+UnlockDiagnosticVMOptions",
                                       "-XX:+WhiteBoxAPI",
                                       "-Xbootclasspath/a:.",
+                                      "-XX:+VerifyBeforeGC",
+                                      "-XX:+VerifyAfterGC",
                                       doConcurrent ? "-XX:+ExplicitGCInvokesConcurrent" : "-XX:-ExplicitGCInvokesConcurrent",
                                       "-XX:+ClassUnloading",
                                       "-XX:+ClassUnloadingWithConcurrentMark",
                                       "-XX:+Use" + gc + "GC",
                                       Leak.class.getName());
+
+        // Check process
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.outputTo(System.out);
+        output.errorTo(System.err);
+        output.shouldHaveExitValue(0);
+
+        // Check gc log file
+        OutputAnalyzer gcLogOutput = new OutputAnalyzer(gcLogPath);
+
         // Hardcoded names for classes generated by GeneratedClassLoader
         String descriptor = className + "." + methodPrefix + "0()V";
-        output.shouldContain("ResolvedMethod entry added for " + descriptor);
-        output.shouldContain("ResolvedMethod entry found for " + descriptor);
-        output.shouldContain("ResolvedMethod entry removed");
-        output.shouldHaveExitValue(0);
+        gcLogOutput.shouldContain("ResolvedMethod entry added for " + descriptor);
+        gcLogOutput.shouldContain("ResolvedMethod entry found for " + descriptor);
+        gcLogOutput.shouldContain("ResolvedMethod entry removed");
+
+        System.err.println("test(" + gc + ", " + doConcurrent + ")" + " done " + dateFormat.format(new Date()));
     }
 
     private static boolean supportsSTW(GC gc) {
--- a/test/hotspot/jtreg/runtime/Thread/MonitorCacheMaybeExpand_DeadLock.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4087516
- * @summary Incorrect locking leads to deadlock in monitorCacheMaybeExpand.
- * @author Anand Palaniswamy
- * @build MonitorCacheMaybeExpand_DeadLock
- * @run main/othervm MonitorCacheMaybeExpand_DeadLock
- */
-
-/**
- * Background on the bug:
- *
- *     The thread local monitor cache had a locking bug (till
- *     1.2beta1) where two threads trying to expand the monitor cache
- *     at the same time would cause deadlock. The code paths that the
- *     two threads must be executing for this to happen is described
- *     in the bug report.
- *
- * Caveat and red-flag:
- *
- *     Since deadlocks are very timing dependent, there is a good
- *     chance this test case will not catch the bug most of the time
- *     -- on your machine and setting, it is _possible_ that the two
- *     threads might not try a monitorCacheExpand at the same
- *     time. But in practice, on Solaris native threads, this program
- *     deadlocks the VM in about 2 seconds pretty consistently,
- *     whether MP or not.
- *
- *     The rationale for running this test despite this rather large
- *     caveat is that at worst, it can do no harm.
- *
- * The idea:
- *
- *     Is to create two monitor hungry threads.
- *
- *     Originally Tom Rodriguez and I suspected that this weird state
- *     of two threads trying to expand monitor cache can happen only
- *     if:
- *
- *         Thread 1: Is in the middle of a monitorCacheMaybeExpand.
- *         Thread 2: Runs GC and tries to freeClasses(). This causes
- *                   sysFree() to be invoked, which in turn needs a
- *                   mutex_lock -- and oops, we end up deadlocking
- *                   with 1 on green_threads.
- *
- *     Which is why this test tries to cause class GC at regular
- *     intervals.
- *
- *     Turns out that the GC is not required. Two instances of the
- *     monitor hungry threads deadlock the VM pretty quick. :-) Infact
- *     the static initializer in the forName'd classes running
- *     alongside one of the hungry threads is sufficient to
- *     deadlock. Still keep the GC stuff just-in-case (and also
- *     because I wrote it :-).
- *
- */
-public class MonitorCacheMaybeExpand_DeadLock {
-
-    /**
-     * A monitor-hungry thread.
-     */
-    static class LotsaMonitors extends Thread {
-
-        /** How many recursions? Could cause Java stack overflow. */
-        static final int MAX_DEPTH = 800;
-
-        /** What is our depth? */
-        int depth = 0;
-
-        /** Thread ID */
-        int tid;
-
-        /** So output will have thread number. */
-        public LotsaMonitors(int tid, int depth) {
-            super("LotsaMonitors #" + new Integer(tid).toString());
-            this.tid = tid;
-            this.depth = depth;
-        }
-
-        /** Start a recursion that grabs monitors. */
-        public void run() {
-            System.out.println(">>>Starting " + this.toString() + " ...");
-            Thread.currentThread().yield();
-            this.recurse();
-            System.out.println("<<<Finished " + this.toString());
-        }
-
-        /** Every call to this method grabs an extra monitor. */
-        synchronized void recurse() {
-            if (this.depth > 0) {
-                new LotsaMonitors(tid, depth-1).recurse();
-            }
-        }
-    }
-
-    /**
-     * The test.
-     */
-    public static void main(String[] args) {
-        /* Start the two of these crazy threads. */
-        new LotsaMonitors(1, LotsaMonitors.MAX_DEPTH).start();
-        new LotsaMonitors(2, LotsaMonitors.MAX_DEPTH).start();
-
-        /* And sit there and GC for good measure. */
-        for (int i = 0; i < MAX_GC_ITERATIONS; i++) {
-            new LotsaMonitors(i+3, LotsaMonitors.MAX_DEPTH).start();
-            System.out.println(">>>Loading 10 classes and gc'ing ...");
-            Class[] classes = new Class[10];
-            fillClasses(classes);
-            classes = null;
-            System.gc();
-            Thread.currentThread().yield();
-            System.out.println("<<<Finished loading 10 classes and gc'ing");
-        }
-    }
-
-    /** How many times to GC? */
-    static final int MAX_GC_ITERATIONS = 10;
-
-    /** Load some classes into the array. */
-    static void fillClasses(Class[] classes) {
-        for (int i = 0; i < classes.length; i++) {
-            try {
-                classes[i] = Class.forName(classnames[i]);
-            } catch (ClassNotFoundException cnfe) {
-                cnfe.printStackTrace();
-            }
-        }
-    }
-
-    /** Some random classes to load. */
-    private static String[] classnames = {
-        "java.text.DecimalFormat",
-        "java.text.MessageFormat",
-        "java.util.GregorianCalendar",
-        "java.util.ResourceBundle",
-        "java.text.Collator",
-        "java.util.Date",
-        "java.io.Reader",
-        "java.io.Writer",
-        "java.lang.IllegalAccessException",
-        "java.lang.InstantiationException",
-        "java.lang.ClassNotFoundException",
-        "java.lang.CloneNotSupportedException",
-        "java.lang.InterruptedException",
-        "java.lang.NoSuchFieldException",
-        "java.lang.NoSuchMethodException",
-        "java.lang.RuntimeException",
-        "java.lang.ArithmeticException",
-        "java.lang.ArrayStoreException",
-        "java.lang.ClassCastException",
-        "java.lang.StringIndexOutOfBoundsException",
-        "java.lang.NegativeArraySizeException",
-        "java.lang.IllegalStateException",
-        "java.lang.IllegalArgumentException",
-        "java.lang.NumberFormatException",
-        "java.lang.IllegalThreadStateException",
-        "java.lang.IllegalMonitorStateException",
-        "java.lang.SecurityException",
-        "java.lang.ExceptionInInitializerError"
-    };
-
-}
--- a/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -187,12 +187,18 @@
         checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "513");
 
         /*
+         * Try with 0k which indicates that the default thread stack size from JVM will be used.
+         */
+        checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "0");
+
+        /*
          * Now redo the same tests with the compiler thread stack size:
          */
         checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "16");
         min_stack_allowed = checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "64");
         checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, min_stack_allowed);
         checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "513");
+        checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "0");
 
         /*
          * Now redo the same tests with the VM thread stack size:
@@ -201,5 +207,6 @@
         min_stack_allowed = checkStack("-XX:VMThreadStackSize=", VMThreadStackSizeString, "64");
         checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, min_stack_allowed);
         checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "513");
+        checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "0");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/OldClassTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/OldClassTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -24,7 +24,7 @@
 
 /*
  * @test
- * @summary classes with major version < JDK_1.5 (48) should not be included in CDS
+ * @summary classes with major version < JDK_6 (50) should not be included in CDS
  * @requires vm.cds
  * @library /test/lib
  * @modules java.base/jdk.internal.org.objectweb.asm
@@ -61,9 +61,9 @@
 
     String appClasses[] = TestCommon.list("Hello");
 
-    // CASE 1: pre-JDK 1.5 compiled classes should be excluded from the dump
+    // CASE 1: pre-JDK 6 compiled classes should be excluded from the dump
     OutputAnalyzer output = TestCommon.dump(jar, appClasses);
-    TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
+    TestCommon.checkExecReturn(output, 0, true, "Pre JDK 6 class not supported by CDS");
 
     TestCommon.run(
         "-cp", jar,
@@ -74,7 +74,7 @@
     //         the newer version of this class in a subsequent classpath element.
     String classpath = jar + File.pathSeparator + jarSrcFile.getPath();
     output = TestCommon.dump(classpath, appClasses);
-    TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
+    TestCommon.checkExecReturn(output, 0, true, "Pre JDK 6 class not supported by CDS");
 
     TestCommon.run(
         "-cp", classpath,
@@ -127,8 +127,7 @@
     MethodVisitor mv;
     AnnotationVisitor av0;
 
-//WAS cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
-      cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
+      cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
 
     {
       mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
--- a/test/hotspot/jtreg/runtime/interpreter/WideStrictInline.java	Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4169183
- * @summary Check for correct inlining by the interpreter (widefp and strictfp).
- *          The default is widefp.  A strictfp method was getting inlined
- *          into a widefp method.
- */
-
-import java.io.PrintStream;
-
-public class WideStrictInline {
-    static PrintStream out;
-    static float halfUlp;
-
-    static {
-        halfUlp = 1;
-        for ( int i = 127 - 24; i > 0; i-- )
-            halfUlp *= 2;
-    }
-
-    public static void main(String argv[]) throws Exception {
-        out = System.err;
-        pr(-1,"halfUlp",halfUlp);
-        WideStrictInline obj = new WideStrictInline();
-        for( int i=0; i<48; i++ )
-            obj.instanceMethod( i );
-    }
-
-    private static void pr(int i, String desc, float r) {
-        out.print(" i=("+i+") "+desc+" ; == "+r);
-        out.println(" , 0x"+Integer.toHexString(Float.floatToIntBits(r)));
-    }
-
-    private static strictfp float WideStrictInline(float par) {
-        return par;
-    }
-
-    public static strictfp float strictValue(int i) {
-        float r;
-        switch (i%4) {
-        case 0: r = -Float.MAX_VALUE;  break;
-        case 1: r =  Float.MAX_VALUE;  break;
-        case 2: r =  Float.MIN_VALUE;  break;
-        default : r = 1L << 24;
-        }
-        return r;
-    }
-
-    void instanceMethod (int i) throws Exception {
-        float r;
-        switch (i%4) {
-        case 0:
-            if (!Float.isInfinite( WideStrictInline(strictValue(i)*2) +
-                                   Float.MAX_VALUE ))
-                {
-                    pr(i,
-                       "WideStrictInline(-Float.MAX_VALUE * 2) " +
-                       "!= Float.NEGATIVE_INFINITY"
-                       ,WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE);
-                }
-            r = WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE;
-            if ( !Float.isInfinite( r ) ) {
-                pr(i,"r != Float.NEGATIVE_INFINITY",r);
-                throw new RuntimeException();
-            }
-            break;
-        case 1:
-            if (!Float.isInfinite(WideStrictInline(strictValue(i)+halfUlp) -
-                                  Float.MAX_VALUE )) {
-                pr(i,"WideStrictInline(Float.MAX_VALUE+halfUlp) " +
-                   "!= Float.POSITIVE_INFINITY"
-                   ,WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE);
-            }
-            r = WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE;
-            if ( !Float.isInfinite( r ) ) {
-                pr(i,"r != Float.POSITIVE_INFINITY",r);
-                throw new RuntimeException();
-            }
-            break;
-        case 2:
-            if (WideStrictInline(strictValue(i)/2) != 0) {
-                pr(i,"WideStrictInline(Float.MIN_VALUE/2) != 0",
-                   WideStrictInline(strictValue(i)/2));
-            }
-            r = WideStrictInline(strictValue(i)/2);
-            if ( r != 0 ) {
-                pr(i,"r != 0",r);
-                throw new RuntimeException();
-            }
-            break;
-        default:
-            if (WideStrictInline(strictValue(i)-0.5f) - strictValue(i) != 0) {
-                pr(i,"WideStrictInline(2^24-0.5) != 2^24",
-                   WideStrictInline(strictValue(i)-0.5f));
-            }
-            r = WideStrictInline(strictValue(i)-0.5f);
-            if ( r - strictValue(i) != 0 ) {
-                pr(i,"r != 2^24",r);
-                throw new RuntimeException();
-            }
-        }
-    }
-
-}
--- a/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,19 +22,22 @@
  */
 package parsers;
 
+import java.io.ByteArrayInputStream;
 import java.io.StringReader;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
+import static org.testng.Assert.assertEquals;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
+import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 
 /**
  * @test
- * @bug 8169450
+ * @bug 8169450 8222415
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng/othervm -DrunSecMngr=true parsers.BaseParsingTest
  * @run testng/othervm parsers.BaseParsingTest
@@ -143,7 +146,7 @@
      * @bug 8169450
      * This particular issue does not appear in DOM parsing since the spaces are
      * normalized during version detection. This test case then serves as a guard
-     * against such an issue from occuring in the version detection.
+     * against such an issue from occurring in the version detection.
      *
      * @param xml the test xml
      * @throws Exception if the parser fails to parse the xml
@@ -151,8 +154,24 @@
     @Test(dataProvider = "xmlDeclarations")
     public void testWithDOM(String xml) throws Exception {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setValidating(true);
         DocumentBuilder db = dbf.newDocumentBuilder();
         db.parse(new InputSource(new StringReader(xml)));
     }
+
+    /**
+     * @bug 8222415
+     * Verifies that the parser is configured properly for UTF-16BE or LE.
+     * @throws Exception
+     */
+    @Test
+    public void testEncoding() throws Exception {
+        ByteArrayInputStream bis = new ByteArrayInputStream(
+                "<?xml version=\"1.0\" encoding=\"UTF-16\"?> <a/>".getBytes("UnicodeLittle"));
+        InputSource is = new InputSource(bis);
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder db = dbf.newDocumentBuilder();
+
+        Document doc = db.parse(is);
+        assertEquals("UTF-16LE", doc.getInputEncoding());
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/math/BigDecimal/IntValueExactTests.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8211936
+ * @summary Tests of BigDecimal.intValueExact
+ */
+import java.math.*;
+import java.util.List;
+import java.util.Map;
+import static java.util.Map.entry;
+
+public class IntValueExactTests {
+    public static void main(String... args) {
+        int failures = 0;
+
+        failures += intValueExactSuccessful();
+        failures += intValueExactExceptional();
+
+        if (failures > 0) {
+            throw new RuntimeException("Incurred " + failures +
+                                       " failures while testing intValueExact.");
+        }
+    }
+
+    private static int simpleIntValueExact(BigDecimal bd) {
+        return bd.toBigIntegerExact().intValue();
+    }
+
+    private static int intValueExactSuccessful() {
+        int failures = 0;
+
+        // Strings used to create BigDecimal instances on which invoking
+        // intValueExact() will succeed.
+        Map<BigDecimal, Integer> successCases =
+            Map.ofEntries(entry(new BigDecimal("2147483647"),    Integer.MAX_VALUE), // 2^31 -1
+                          entry(new BigDecimal("2147483647.0"),  Integer.MAX_VALUE),
+                          entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
+
+                          entry(new BigDecimal("-2147483648"),   Integer.MIN_VALUE), // -2^31
+                          entry(new BigDecimal("-2147483648.0"), Integer.MIN_VALUE),
+                          entry(new BigDecimal("-2147483648.00"),Integer.MIN_VALUE),
+
+                          entry(new BigDecimal("1e0"),    1),
+                          entry(new BigDecimal(BigInteger.ONE, -9),   1_000_000_000),
+
+                          entry(new BigDecimal("0e13"),   0), // Fast path zero
+                          entry(new BigDecimal("0e32"),   0),
+                          entry(new BigDecimal("0e512"), 0),
+
+                          entry(new BigDecimal("10.000000000000000000000000000000000"), 10));
+
+        for (var testCase : successCases.entrySet()) {
+            BigDecimal bd = testCase.getKey();
+            int expected = testCase.getValue();
+            try {
+                int intValueExact = bd.intValueExact();
+                if (expected != intValueExact ||
+                    intValueExact != simpleIntValueExact(bd)) {
+                    failures++;
+                    System.err.println("Unexpected intValueExact result " + intValueExact +
+                                       " on " + bd);
+                }
+            } catch (Exception e) {
+                failures++;
+                System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
+            }
+        }
+        return failures;
+    }
+
+    private static int intValueExactExceptional() {
+        int failures = 0;
+        List<BigDecimal> exceptionalCases =
+            List.of(new BigDecimal("2147483648"), // Integer.MAX_VALUE + 1
+                    new BigDecimal("2147483648.0"),
+                    new BigDecimal("2147483648.00"),
+                    new BigDecimal("-2147483649"), // Integer.MIN_VALUE - 1
+                    new BigDecimal("-2147483649.1"),
+                    new BigDecimal("-2147483649.01"),
+
+                    new BigDecimal("9999999999999999999999999999999"),
+                    new BigDecimal("10000000000000000000000000000000"),
+
+                    new BigDecimal("0.99"),
+                    new BigDecimal("0.999999999999999999999"));
+
+        for (BigDecimal bd : exceptionalCases) {
+            try {
+                int intValueExact = bd.intValueExact();
+                failures++;
+                System.err.println("Unexpected non-exceptional intValueExact on " + bd);
+            } catch (ArithmeticException e) {
+                // Success;
+            }
+        }
+        return failures;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/math/BigDecimal/IntegralValueTests.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,241 @@
+/*
+ * 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 8211936
+ * @summary Tests of BigDecimal.intValue() and BigDecimal.longValue()
+ */
+import java.math.BigDecimal;
+import java.util.Map;
+
+public class IntegralValueTests {
+    public static void main(String... args) {
+        int failures =
+            integralValuesTest(INT_VALUES, true) +
+            integralValuesTest(LONG_VALUES, false);
+        if (failures != 0) {
+            throw new RuntimeException
+                ("Incurred " + failures + " failures for {int,long}Value().");
+        }
+    }
+
+    private static final Map<BigDecimal, Number> INT_VALUES =
+        Map.ofEntries(
+
+         // 2**31 - 1
+         Map.entry(new BigDecimal("2147483647"), Integer.MAX_VALUE),
+         Map.entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE),
+         Map.entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
+
+         Map.entry(new BigDecimal("-2147483647"), -Integer.MAX_VALUE),
+         Map.entry(new BigDecimal("-2147483647.0"), -Integer.MAX_VALUE),
+
+         // -2**31
+         Map.entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE),
+         Map.entry(new BigDecimal("-2147483648.1"), Integer.MIN_VALUE),
+         Map.entry(new BigDecimal("-2147483648.01"), Integer.MIN_VALUE),
+
+         // -2**31 + 1 truncation to 2**31 - 1
+         Map.entry(new BigDecimal("-2147483649"), Integer.MAX_VALUE),
+
+         // 2**64 - 1 truncation to 1
+         Map.entry(new BigDecimal("4294967295"), -1),
+
+         // 2**64 truncation to 0
+         Map.entry(new BigDecimal("4294967296"), 0),
+
+         // Fast path truncation to 0
+         Map.entry(new BigDecimal("1e32"), 0),
+
+         // Slow path truncation to -2**31
+         Map.entry(new BigDecimal("1e31"), Integer.MIN_VALUE),
+
+         // Slow path
+         Map.entry(new BigDecimal("1e0"), 1),
+
+         // Fast path round to 0
+         Map.entry(new BigDecimal("9e-1"), 0),
+
+         // Some random values
+         Map.entry(new BigDecimal("900e-1"), 90), // Increasing negative exponents
+         Map.entry(new BigDecimal("900e-2"), 9),
+         Map.entry(new BigDecimal("900e-3"), 0),
+
+         // Fast path round to 0
+         Map.entry(new BigDecimal("123456789e-9"), 0),
+
+         // Slow path round to 1
+         Map.entry(new BigDecimal("123456789e-8"), 1),
+
+         // Increasing positive exponents
+         Map.entry(new BigDecimal("10000001e1"), 100000010),
+         Map.entry(new BigDecimal("10000001e10"), -1315576832),
+         Map.entry(new BigDecimal("10000001e100"), 0),
+         Map.entry(new BigDecimal("10000001e1000"), 0),
+         Map.entry(new BigDecimal("10000001e10000"), 0),
+         Map.entry(new BigDecimal("10000001e100000"), 0),
+         Map.entry(new BigDecimal("10000001e1000000"), 0),
+         Map.entry(new BigDecimal("10000001e10000000"), 0),
+         Map.entry(new BigDecimal("10000001e100000000"), 0),
+         Map.entry(new BigDecimal("10000001e1000000000"), 0),
+
+         // Increasing negative exponents
+         Map.entry(new BigDecimal("10000001e-1"), 1000000),
+         Map.entry(new BigDecimal("10000001e-10"), 0),
+         Map.entry(new BigDecimal("10000001e-100"), 0),
+         Map.entry(new BigDecimal("10000001e-1000"), 0),
+         Map.entry(new BigDecimal("10000001e-10000"), 0),
+         Map.entry(new BigDecimal("10000001e-100000"), 0),
+         Map.entry(new BigDecimal("10000001e-1000000"), 0),
+         Map.entry(new BigDecimal("10000001e-10000000"), 0),
+         Map.entry(new BigDecimal("10000001e-100000000"), 0),
+         Map.entry(new BigDecimal("10000001e-1000000000"), 0),
+
+         // Currency calculation to 4 places
+         Map.entry(new BigDecimal("12345.0001"), 12345),
+         Map.entry(new BigDecimal("12345.9999"), 12345),
+         Map.entry(new BigDecimal("-12345.0001"), -12345),
+         Map.entry(new BigDecimal("-12345.9999"), -12345));
+
+    private static final Map<BigDecimal, Number> LONG_VALUES =
+        Map.ofEntries(
+         // 2**63 - 1
+         Map.entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE),
+         Map.entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE),
+         Map.entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
+
+         // 2**63 truncation to -2**63
+         Map.entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE),
+         Map.entry(new BigDecimal("-9223372036854775808.1"), Long.MIN_VALUE),
+         Map.entry(new BigDecimal("-9223372036854775808.01"), Long.MIN_VALUE),
+
+         // -2**63 + 1 truncation to 2**63 - 1
+         Map.entry(new BigDecimal("-9223372036854775809"), 9223372036854775807L),
+
+         // 2**64 - 1 truncation to -1
+         Map.entry(new BigDecimal("18446744073709551615"), -1L),
+
+         // 2**64 truncation to 0
+         Map.entry(new BigDecimal("18446744073709551616"), 0L),
+
+         // Slow path truncation to -2**63
+         Map.entry(new BigDecimal("1e63"),  -9223372036854775808L),
+         Map.entry(new BigDecimal("-1e63"), -9223372036854775808L),
+         // Fast path with larger magnitude scale
+         Map.entry(new BigDecimal("1e64"), 0L),
+         Map.entry(new BigDecimal("-1e64"), 0L),
+         Map.entry(new BigDecimal("1e65"), 0L),
+         Map.entry(new BigDecimal("-1e65"), 0L),
+
+         // Slow path
+         Map.entry(new BigDecimal("1e0"), 1L),
+
+         // Fast path round to 0
+         Map.entry(new BigDecimal("9e-1"), 0L),
+
+         // Some random values
+         Map.entry(new BigDecimal("900e-1"), 90L), // Increasing negative exponents
+         Map.entry(new BigDecimal("900e-2"), 9L),
+         Map.entry(new BigDecimal("900e-3"), 0L),
+
+         // Fast path round to 0
+         Map.entry(new BigDecimal("123456789e-9"), 0L),
+
+         // Slow path round to 1
+         Map.entry(new BigDecimal("123456789e-8"), 1L),
+
+         // Increasing positive exponents
+         Map.entry(new BigDecimal("10000001e1"), 100000010L),
+         Map.entry(new BigDecimal("10000001e10"), 100000010000000000L),
+         Map.entry(new BigDecimal("10000001e100"), 0L),
+         Map.entry(new BigDecimal("10000001e1000"), 0L),
+         Map.entry(new BigDecimal("10000001e10000"), 0L),
+         Map.entry(new BigDecimal("10000001e100000"), 0L),
+         Map.entry(new BigDecimal("10000001e1000000"), 0L),
+         Map.entry(new BigDecimal("10000001e10000000"), 0L),
+         Map.entry(new BigDecimal("10000001e100000000"), 0L),
+         Map.entry(new BigDecimal("10000001e1000000000"), 0L),
+
+         // Increasing negative exponents
+         Map.entry(new BigDecimal("10000001e-1"), 1000000L),
+         Map.entry(new BigDecimal("10000001e-10"), 0L),
+         Map.entry(new BigDecimal("10000001e-100"), 0L),
+         Map.entry(new BigDecimal("10000001e-1000"), 0L),
+         Map.entry(new BigDecimal("10000001e-10000"), 0L),
+         Map.entry(new BigDecimal("10000001e-100000"), 0L),
+         Map.entry(new BigDecimal("10000001e-1000000"), 0L),
+         Map.entry(new BigDecimal("10000001e-10000000"), 0L),
+         Map.entry(new BigDecimal("10000001e-100000000"), 0L),
+         Map.entry(new BigDecimal("10000001e-1000000000"), 0L),
+
+         // Currency calculation to 4 places
+         Map.entry(new BigDecimal("12345.0001"), 12345L),
+         Map.entry(new BigDecimal("12345.9999"), 12345L),
+         Map.entry(new BigDecimal("-12345.0001"), -12345L),
+         Map.entry(new BigDecimal("-12345.9999"), -12345L));
+
+    private static int integralValuesTest(Map<BigDecimal, Number> v, boolean isInt) {
+        System.err.format("Testing %s%n", isInt ? "Integer" : "Long");
+        int failures = 0;
+        for (var testCase : v.entrySet()) {
+            BigDecimal bd = testCase.getKey();
+            Number expected = testCase.getValue();
+            try {
+                if (isInt) {
+                    int intValue = bd.intValue();
+                    if (intValue != (int)expected) {
+                        failures += reportError(bd, expected, intValue, isInt);
+                    }
+                } else {
+                    long longValue = bd.longValue();
+                    if (longValue != (long)expected) {
+                        failures += reportError(bd, expected, longValue, isInt);
+                    }
+                }
+            } catch (Exception e) {
+                failures++;
+                System.err.format("Unexpected exception %s for %s%n",
+                                  e, bd.toString());
+            }
+        }
+        return failures;
+    }
+
+    private static int reportError(BigDecimal bd, Number expected, long longValue, boolean isInt) {
+        System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n",
+                          bd.toString(), bd.scale(),
+                          (isInt ? (Integer) expected : (Long) expected ),
+                          longValue,
+                          (isInt ? simpleIntValue(bd): simpleLongValue(bd) ));
+        return 1;
+    }
+
+    private static long simpleLongValue(BigDecimal bd) {
+        return bd.toBigInteger().longValue();
+    }
+
+    private static int simpleIntValue(BigDecimal bd) {
+        return bd.toBigInteger().intValue();
+    }
+}
--- a/test/jdk/java/math/BigDecimal/LongValueExactTests.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/math/BigDecimal/LongValueExactTests.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 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
@@ -23,65 +23,98 @@
 
 /**
  * @test
- * @bug 6806261
+ * @bug 6806261 8211936
  * @summary Tests of BigDecimal.longValueExact
  */
 import java.math.*;
+import java.util.List;
+import java.util.Map;
+import static java.util.Map.entry;
 
 public class LongValueExactTests {
+    public static void main(String... args) {
+        int failures = 0;
 
-    private static int longValueExactTests() {
+        failures += longValueExactSuccessful();
+        failures += longValueExactExceptional();
+
+        if (failures > 0) {
+            throw new RuntimeException("Incurred " + failures +
+                                       " failures while testing longValueExact.");
+        }
+    }
+
+    private static long simpleLongValueExact(BigDecimal bd) {
+        return bd.toBigIntegerExact().longValue();
+    }
+
+    private static int longValueExactSuccessful() {
         int failures = 0;
 
-        String[] testStrings = {
-            "9223372036854775807",
-            "9223372036854775807.0",
-            "9223372036854775807.00",
-            "-9223372036854775808",
-            "-9223372036854775808.0",
-            "-9223372036854775808.00",
-        };
+        // Strings used to create BigDecimal instances on which invoking
+        // longValueExact() will succeed.
+        Map<BigDecimal, Long> successCases =
+            Map.ofEntries(entry(new BigDecimal("9223372036854775807"),    Long.MAX_VALUE), // 2^63 -1
+                          entry(new BigDecimal("9223372036854775807.0"),  Long.MAX_VALUE),
+                          entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
+
+                          entry(new BigDecimal("-9223372036854775808"),   Long.MIN_VALUE), // -2^63
+                          entry(new BigDecimal("-9223372036854775808.0"), Long.MIN_VALUE),
+                          entry(new BigDecimal("-9223372036854775808.00"),Long.MIN_VALUE),
+
+                          entry(new BigDecimal("1e0"),    1L),
+                          entry(new BigDecimal(BigInteger.ONE, -18),   1_000_000_000_000_000_000L),
 
-        for (String longValue : testStrings) {
+                          entry(new BigDecimal("0e13"),   0L), // Fast path zero
+                          entry(new BigDecimal("0e64"),   0L),
+                          entry(new BigDecimal("0e1024"), 0L),
+
+                          entry(new BigDecimal("10.000000000000000000000000000000000"), 10L));
+
+        for (var testCase : successCases.entrySet()) {
+            BigDecimal bd = testCase.getKey();
+            long expected = testCase.getValue();
             try {
-                BigDecimal bd = new BigDecimal(longValue);
                 long longValueExact = bd.longValueExact();
+                if (expected != longValueExact ||
+                    longValueExact != simpleLongValueExact(bd)) {
+                    failures++;
+                    System.err.println("Unexpected longValueExact result " + longValueExact +
+                                       " on " + bd);
+                }
             } catch (Exception e) {
                 failures++;
+                System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
             }
         }
+        return failures;
+    }
 
-        // The following Strings are supposed to make longValueExact throw
-        // ArithmeticException.
-        String[] testStrings2 = {
-            "9223372036854775808",
-            "9223372036854775808.0",
-            "9223372036854775808.00",
-            "-9223372036854775809",
-            "-9223372036854775808.1",
-            "-9223372036854775808.01",
-        };
+    private static int longValueExactExceptional() {
+        int failures = 0;
+        List<BigDecimal> exceptionalCases =
+            List.of(new BigDecimal("9223372036854775808"), // Long.MAX_VALUE + 1
+                    new BigDecimal("9223372036854775808.0"),
+                    new BigDecimal("9223372036854775808.00"),
+                    new BigDecimal("-9223372036854775809"), // Long.MIN_VALUE - 1
+                    new BigDecimal("-9223372036854775808.1"),
+                    new BigDecimal("-9223372036854775808.01"),
 
-        for (String bigValue : testStrings2) {
+                    new BigDecimal("9999999999999999999"),
+                    new BigDecimal("10000000000000000000"),
+
+                    new BigDecimal("0.99"),
+                    new BigDecimal("0.999999999999999999999"));
+
+        for (BigDecimal bd : exceptionalCases) {
             try {
-                BigDecimal bd = new BigDecimal(bigValue);
                 long longValueExact = bd.longValueExact();
                 failures++;
+                System.err.println("Unexpected non-exceptional longValueExact on " + bd);
             } catch (ArithmeticException e) {
                 // Success;
             }
         }
         return failures;
     }
-
-    public static void main(String argv[]) {
-        int failures = 0;
-
-        failures += longValueExactTests();
-
-        if (failures > 0) {
-            throw new RuntimeException("Incurred " + failures +
-                                       " failures while testing longValueExact.");
-        }
-    }
 }
--- a/test/jdk/java/net/httpclient/DigestEchoServer.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/DigestEchoServer.java	Fri Apr 19 08:00:42 2019 -0400
@@ -80,6 +80,8 @@
             Boolean.parseBoolean(System.getProperty("test.debug", "false"));
     public static final boolean NO_LINGER =
             Boolean.parseBoolean(System.getProperty("test.nolinger", "false"));
+    public static final boolean TUNNEL_REQUIRES_HOST =
+            Boolean.parseBoolean(System.getProperty("test.requiresHost", "false"));
     public enum HttpAuthType {
         SERVER, PROXY, SERVER307, PROXY305
         /* add PROXY_AND_SERVER and SERVER_PROXY_NONE */
@@ -1522,6 +1524,36 @@
             }
         }
 
+        boolean badRequest(StringBuilder response, String hostport, List<String> hosts) {
+            String message = null;
+            if (hosts.isEmpty()) {
+                message = "No host header provided\r\n";
+            } else if (hosts.size() > 1) {
+                message = "Multiple host headers provided\r\n";
+                for (String h : hosts) {
+                    message = message + "host: " + h + "\r\n";
+                }
+            } else {
+                String h = hosts.get(0);
+                if (!hostport.equalsIgnoreCase(h)
+                        && !hostport.equalsIgnoreCase(h + ":80")
+                        && !hostport.equalsIgnoreCase(h + ":443")) {
+                    message = "Bad host provided: [" + h
+                            + "] doesnot match [" + hostport + "]\r\n";
+                }
+            }
+            if (message != null) {
+                int length = message.getBytes(StandardCharsets.UTF_8).length;
+                response.append("HTTP/1.1 400 BadRequest\r\n")
+                        .append("Content-Length: " + length)
+                        .append("\r\n\r\n")
+                        .append(message);
+                return true;
+            }
+
+            return false;
+        }
+
         boolean authorize(StringBuilder response, String requestLine, String headers) {
             if (authorization != null) {
                 return authorization.authorize(response, requestLine, headers);
@@ -1635,6 +1667,7 @@
                         assert connect.equalsIgnoreCase("connect");
                         String hostport = tokenizer.nextToken();
                         InetSocketAddress targetAddress;
+                        List<String> hosts = new ArrayList<>();
                         try {
                             URI uri = new URI("https", hostport, "/", null, null);
                             int port = uri.getPort();
@@ -1659,9 +1692,30 @@
                             System.out.println(now() + "Tunnel: Reading header: "
                                                + (line = readLine(ccis)));
                             headers.append(line).append("\r\n");
+                            int index = line.indexOf(':');
+                            if (index >= 0) {
+                                String key = line.substring(0, index).trim();
+                                if (key.equalsIgnoreCase("host")) {
+                                    hosts.add(line.substring(index+1).trim());
+                                }
+                            }
+                        }
+                        StringBuilder response = new StringBuilder();
+                        if (TUNNEL_REQUIRES_HOST) {
+                            if (badRequest(response, hostport, hosts)) {
+                                System.out.println(now() + "Tunnel: Sending " + response);
+                                // send the 400 response
+                                pw.print(response.toString());
+                                pw.flush();
+                                toClose.close();
+                                continue;
+                            } else {
+                                assert hosts.size() == 1;
+                                System.out.println(now()
+                                        + "Tunnel: Host header verified " + hosts);
+                            }
                         }
 
-                        StringBuilder response = new StringBuilder();
                         final boolean authorize = authorize(response, requestLine, headers.toString());
                         if (!authorize) {
                             System.out.println(now() + "Tunnel: Sending "
--- a/test/jdk/java/net/httpclient/HttpsTunnelTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/HttpsTunnelTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,8 +47,9 @@
  *          proxy P is downgraded to HTTP/1.1, then a new h2 request
  *          going to a different host through the same proxy will not
  *          be preemptively downgraded. That, is the stack should attempt
- *          a new h2 connection to the new host.
- * @bug 8196967
+ *          a new h2 connection to the new host. It also verifies that
+ *          the stack sends the appropriate "host" header to the proxy.
+ * @bug 8196967 8222527
  * @library /test/lib http2/server
  * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpsTunnelTest
  * @modules java.net.http/jdk.internal.net.http.common
@@ -58,7 +59,14 @@
  *          java.base/sun.net.www.http
  *          java.base/sun.net.www
  *          java.base/sun.net
- * @run main/othervm -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ * @run main/othervm -Dtest.requiresHost=true
+ *                   -Djdk.httpclient.HttpClient.log=headers
+ *                   -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ * @run main/othervm -Dtest.requiresHost=true
+ *                   -Djdk.httpclient.allowRestrictedHeaders=host
+ *                   -Djdk.httpclient.HttpClient.log=headers
+ *                   -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ *
  */
 
 public class HttpsTunnelTest implements HttpServerAdapters {
@@ -116,6 +124,18 @@
         try {
             URI uri1 = new URI("https://" + http1Server.serverAuthority() + "/foo/https1");
             URI uri2 = new URI("https://" + http2Server.serverAuthority() + "/foo/https2");
+
+            boolean provideCustomHost = "host".equalsIgnoreCase(
+                    System.getProperty("jdk.httpclient.allowRestrictedHeaders",""));
+
+            String customHttp1Host = null, customHttp2Host = null;
+            if (provideCustomHost) {
+                customHttp1Host = makeCustomHostString(http1Server, uri1);
+                out.println("HTTP/1.1: <" + uri1 + "> [custom host: " + customHttp1Host + "]");
+                customHttp2Host = makeCustomHostString(http2Server, uri2);
+                out.println("HTTP/2:   <" + uri2 + "> [custom host: " + customHttp2Host + "]");
+            }
+
             ProxySelector ps = ProxySelector.of(proxy.getProxyAddress());
                     //HttpClient.Builder.NO_PROXY;
             HttpsTunnelTest test = new HttpsTunnelTest();
@@ -126,11 +146,12 @@
             assert lines.size() == data.length;
             String body = lines.stream().collect(Collectors.joining("\r\n"));
             HttpRequest.BodyPublisher reqBody = HttpRequest.BodyPublishers.ofString(body);
-            HttpRequest req1 = HttpRequest
+            HttpRequest.Builder req1Builder = HttpRequest
                     .newBuilder(uri1)
                     .version(Version.HTTP_2)
-                    .POST(reqBody)
-                    .build();
+                    .POST(reqBody);
+            if (provideCustomHost) req1Builder.header("host", customHttp1Host);
+            HttpRequest req1 = req1Builder.build();
             out.println("\nPosting to HTTP/1.1 server at: " + req1);
             HttpResponse<Stream<String>> response = client.send(req1, BodyHandlers.ofLines());
             out.println("Checking response...");
@@ -145,12 +166,14 @@
             if (!lines.equals(respLines)) {
                 throw new RuntimeException("Unexpected response 1: " + respLines);
             }
+
             HttpRequest.BodyPublisher reqBody2 = HttpRequest.BodyPublishers.ofString(body);
-            HttpRequest req2 = HttpRequest
+            HttpRequest.Builder req2Builder = HttpRequest
                     .newBuilder(uri2)
                     .version(Version.HTTP_2)
-                    .POST(reqBody2)
-                    .build();
+                    .POST(reqBody2);
+            if (provideCustomHost) req2Builder.header("host", customHttp2Host);
+            HttpRequest req2 = req2Builder.build();
             out.println("\nPosting to HTTP/2 server at: " + req2);
             response = client.send(req2, BodyHandlers.ofLines());
             out.println("Checking response...");
@@ -176,4 +199,26 @@
         }
     }
 
+    /**
+     * Builds a custom host string that is different to what is in the URI
+     * authority, that is textually different than what the stack would
+     * send. For CONNECT we should ignore any custom host settings.
+     * The tunnelling proxy will fail with badRequest 400 if it receives
+     * the custom host instead of the expected URI authority string.
+     * @param  server The target server.
+     * @param  uri    The URI to the target server
+     * @return a host value for the custom host header.
+     */
+    static final String makeCustomHostString(HttpTestServer server, URI uri) {
+        String customHttpHost;
+        if (server.serverAuthority().contains("localhost")) {
+            customHttpHost = InetAddress.getLoopbackAddress().getHostAddress();
+        } else {
+            customHttpHost = InetAddress.getLoopbackAddress().getHostName();
+        }
+        if (customHttpHost.contains(":")) customHttpHost = "[" + customHttpHost + "]";
+        if (uri.getPort() != -1) customHttpHost = customHttpHost + ":" + uri.getPort();
+        return customHttpHost;
+    }
+
 }
--- a/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8087112
+ * @bug 8087112 8222527
  * @summary this test verifies that a client may provides authorization
  *          headers directly when connecting with a server over SSL, and
  *          it verifies that the client honor the jdk.http.auth.*.disabledSchemes
@@ -45,10 +45,12 @@
  * @run main/othervm/timeout=300
  *          -Djdk.http.auth.proxying.disabledSchemes=Basic
  *          -Djdk.http.auth.tunneling.disabledSchemes=Basic
+ *          -Dtest.requiresHost=true
  *          ProxyAuthDisabledSchemesSSL SSL PROXY
  * @run main/othervm/timeout=300
  *          -Djdk.http.auth.proxying.disabledSchemes=Digest
  *          -Djdk.http.auth.tunneling.disabledSchemes=Digest
+ *          -Dtest.requiresHost=true
  *          ProxyAuthDisabledSchemesSSL SSL PROXY
  */
 
--- a/test/jdk/java/nio/channels/Channels/Basic.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/nio/channels/Channels/Basic.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4417152 4481572 6248930 6725399 6884800
+ * @bug 4417152 4481572 6248930 6725399 6884800 8220477
  * @summary Test Channels basic functionality
  */
 
@@ -31,7 +31,6 @@
 import java.nio.charset.*;
 import java.nio.channels.*;
 
-
 public class Basic {
 
     static String message;
@@ -204,6 +203,8 @@
             writeOut(blah, ITERATIONS);
             testNewReader(blah);
 
+            testNewWriterClose();
+            testNewReaderClose();
         } finally {
             blah.delete();
         }
@@ -399,6 +400,98 @@
         r.close();
         fis.close();
     }
+
+    private static void testNewWriterClose() throws Exception {
+        Writer writer = null;
+        try {
+            WritableByteChannel channel = new WritableByteChannel() {
+                @Override
+                public int write(ByteBuffer src) throws IOException {
+                    return 0;
+                }
+
+                @Override
+                public boolean isOpen() {
+                    return true;
+                }
+
+                @Override
+                public void close() throws IOException {
+                    throw new IOException();
+                }
+            };
+            writer = Channels.newWriter(channel,
+                StandardCharsets.UTF_8.newEncoder(), -1);
+            writer.close();
+        } catch (IOException ioe) {
+            Exception theException = null;
+            try {
+                writer.write(1);
+                writer.flush();
+            } catch (Exception e) {
+                theException = e;
+            } finally {
+                if (theException == null) {
+                    throw new RuntimeException("IOException not thrown");
+                } else if (!(theException instanceof IOException)) {
+                    throw new RuntimeException("Exception not an IOException: "
+                        + theException);
+                } else {
+                    String message = theException.getMessage();
+                    if (!message.equals("Stream closed")) {
+                        throw new RuntimeException("Unexpected message "
+                            + message);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void testNewReaderClose() throws Exception {
+        Reader reader = null;
+        try {
+            ReadableByteChannel channel = new ReadableByteChannel() {
+                @Override
+                public int read(ByteBuffer dst) throws IOException {
+                    dst.put((byte)7);
+                    return 1;
+                }
+
+                @Override
+                public boolean isOpen() {
+                    return true;
+                }
+
+                @Override
+                public void close() throws IOException {
+                    throw new IOException();
+                }
+            };
+            reader = Channels.newReader(channel,
+                StandardCharsets.UTF_8.newDecoder(), -1);
+            reader.close();
+        } catch (IOException ioe) {
+            Exception theException = null;
+            try {
+                reader.read();
+            } catch (Exception e) {
+                theException = e;
+            } finally {
+                if (theException == null) {
+                    throw new RuntimeException("IOException not thrown");
+                } else if (!(theException instanceof IOException)) {
+                    throw new RuntimeException("Exception not an IOException: "
+                        + theException);
+                } else {
+                    String message = theException.getMessage();
+                    if (!message.equals("Stream closed")) {
+                        throw new RuntimeException("Unexpected message "
+                            + message);
+                    }
+                }
+            }
+        }
+    }
 }
 
 class ExtendedFileInputStream extends java.io.FileInputStream {
--- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java	Fri Apr 19 08:00:42 2019 -0400
@@ -61,6 +61,14 @@
             return;
         }
 
+        // Verify that 'nc' accepts '-U' for Unix domain sockets.
+        // Skip the test if it is not.
+        Process procHelp = Runtime.getRuntime().exec(CMD_BASE + " -h");
+        if (procHelp.waitFor() != 0) {
+            System.err.println("Netcat does not accept required options; skipping test.");
+            return;
+        }
+
         // Create a new sub-directory of the nominal test directory in which
         // 'nc' will create the socket file.
         String testSubDir = System.getProperty("test.dir", ".")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/rmi/registry/nonLocalRegistry/NonLocalSkeletonTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+import sun.rmi.server.UnicastRef;
+import sun.rmi.transport.LiveRef;
+import sun.rmi.transport.tcp.TCPEndpoint;
+
+import java.lang.reflect.InvocationHandler;
+
+import java.lang.reflect.Proxy;
+import java.net.InetAddress;
+import java.rmi.AccessException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+
+
+/* @test
+ * @bug 8218453
+ * @library ../../testlibrary
+ * @modules java.rmi/sun.rmi.registry:+open java.rmi/sun.rmi.server:+open
+ *      java.rmi/sun.rmi.transport:+open java.rmi/sun.rmi.transport.tcp:+open
+ * @summary Verify that Registry rejects non-local access for bind, unbind, rebind.
+ *    The test is manual because the (non-local) host running rmiregistry must be supplied as a property.
+ * @run main/othervm -Dregistry.host=localhost NonLocalSkeletonTest
+ */
+
+/*
+ * @test
+ * @library ../../testlibrary
+ * @modules java.rmi/sun.rmi.registry:+open java.rmi/sun.rmi.server:+open
+ *      java.rmi/sun.rmi.transport:+open java.rmi/sun.rmi.transport.tcp:+open
+ * @summary Verify that Registry rejects non-local access for bind, unbind, rebind.
+ *    The test is manual because the (non-local) host running rmiregistry must be supplied as a property.
+ * @run main/othervm/manual -Dregistry.host=rmi-registry-host NonLocalSkeletonTest
+ */
+
+/**
+ * Verify that access checks for Registry.bind(), .rebind(), and .unbind()
+ * are prevented on remote access to the registry.
+ *
+ * This test is a manual test and uses a standard rmiregistry running
+ * on a *different* host.
+ * The test verifies that the access check is performed *before* the object to be
+ * bound or rebound is deserialized.
+ *
+ * Login or ssh to the different host and invoke {@code $JDK_HOME/bin/rmiregistry}.
+ * It will not show any output.
+ *
+ * On the first host modify the @run command above to replace "rmi-registry-host"
+ * with the hostname or IP address of the different host and run the test with jtreg.
+ */
+public class NonLocalSkeletonTest {
+
+    public static void main(String[] args) throws Exception {
+        String host = System.getProperty("registry.host");
+        if (host == null || host.isEmpty()) {
+            throw new RuntimeException("supply a remote host with -Dregistry.host=hostname");
+        }
+
+        // Check if running the test on a local system; it only applies to remote
+        String myHostName = InetAddress.getLocalHost().getHostName();
+        Set<InetAddress> myAddrs = Set.of(InetAddress.getAllByName(myHostName));
+        Set<InetAddress> hostAddrs = Set.of(InetAddress.getAllByName(host));
+        boolean isLocal = (hostAddrs.stream().anyMatch(i -> myAddrs.contains(i))
+                || hostAddrs.stream().anyMatch(h -> h.isLoopbackAddress()));
+
+        int port;
+        if (isLocal) {
+            // Create a local Registry to use for the test
+            port = TestLibrary.getUnusedRandomPort();
+            Registry registry = LocateRegistry.createRegistry(port);
+            System.out.printf("local registry port: %s%n", registry);
+        } else {
+            // Use regular rmi registry for non-local test
+            port = Registry.REGISTRY_PORT;
+        }
+
+        try {
+
+            Registry r = nonStaticRegistryProxy(host, port);
+
+            System.out.printf("RegistryRef: %s%n", r);
+
+            r.rebind("anyRef", r);
+            if (!isLocal) {
+                throw new RuntimeException("non-local bind should have failed to host: " + host);
+            } else {
+                System.out.printf("local rebind succeeded%n");
+            }
+        } catch (RemoteException rex) {
+            if (!isLocal) {
+                assertIsAccessException(rex);
+            } else {
+                throw rex;
+            }
+        }
+    }
+
+    /* Returns a non-static proxy for the registry.
+     * Follows the form of sun.rmi.server.Util.createProxy.
+     * @param implClass the RegistryImpl
+     * @param clientRef the registry reference
+     **/
+    static Registry nonStaticRegistryProxy(String host, int port) {
+        final ClassLoader loader = Registry.class.getClassLoader();
+        final Class<?>[] interfaces = new Class<?>[]{Registry.class};
+
+        LiveRef liveRef = new LiveRef(new ObjID(ObjID.REGISTRY_ID),
+                new TCPEndpoint(host, port, null, null),
+                false);
+
+        final InvocationHandler handler = new RemoteObjectInvocationHandler(new UnicastRef(liveRef));
+
+        PrivilegedAction<Registry> action = () -> (Registry) Proxy.newProxyInstance(loader,
+                interfaces, handler);
+        return AccessController.doPrivileged(action);
+    }
+
+    /**
+     * Check the exception chain for the expected AccessException and message.
+     * @param ex the exception from the remote invocation.
+     */
+    private static void assertIsAccessException(Throwable ex) {
+        Throwable t = ex;
+        while (!(t instanceof AccessException) && t.getCause() != null) {
+            t = t.getCause();
+        }
+        if (t instanceof AccessException) {
+            String msg = t.getMessage();
+            int asIndex = msg.indexOf("Registry");
+            int rrIndex = msg.indexOf("Registry.Registry");     // Obsolete error text
+            int disallowIndex = msg.indexOf("disallowed");
+            int nonLocalHostIndex = msg.indexOf("non-local host");
+            if (asIndex < 0 ||
+                    rrIndex != -1 ||
+                    disallowIndex < 0 ||
+                    nonLocalHostIndex < 0 ) {
+                throw new RuntimeException("exception message is malformed", t);
+            }
+            System.out.printf("Found expected AccessException: %s%n%n", t);
+        } else {
+            throw new RuntimeException("AccessException did not occur when expected", ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/SSLSocket/InputStreamClosure.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+//
+// Please run in othervm mode.  SunJSSE does not support dynamic system
+// properties, no way to re-use system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8216326
+ * @modules jdk.crypto.ec
+ * @library /javax/net/ssl/templates
+ * @summary SSLSocket stream close() does not close the associated socket
+ * @run main/othervm InputStreamClosure
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.net.ssl.SSLSocket;
+
+public class InputStreamClosure extends SSLSocketTemplate {
+
+    // Run the test case.
+    public static void main(String[] args) throws Exception {
+        (new InputStreamClosure()).run();
+    }
+
+    @Override
+    protected void runServerApplication(SSLSocket socket) throws Exception {
+        // here comes the test logic
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+    }
+
+    /*
+     * Define the client side application of the test for the specified socket.
+     * This method is used if the returned value of
+     * isCustomizedClientConnection() is false.
+     *
+     * @param socket may be null is no client socket is generated.
+     *
+     * @see #isCustomizedClientConnection()
+     */
+    protected void runClientApplication(SSLSocket socket) throws Exception {
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslIS.close();
+        if (!socket.isClosed()) {
+            throw new Exception("Closing the SSLSocket InputStream does " +
+                    "not close the associated socket");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/SSLSocket/OutputStreamClosure.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+//
+// Please run in othervm mode.  SunJSSE does not support dynamic system
+// properties, no way to re-use system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8216326
+ * @modules jdk.crypto.ec
+ * @library /javax/net/ssl/templates
+ * @summary SSLSocket stream close() does not close the associated socket
+ * @run main/othervm OutputStreamClosure
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.net.ssl.SSLSocket;
+
+public class OutputStreamClosure extends SSLSocketTemplate {
+
+    // Run the test case.
+    public static void main(String[] args) throws Exception {
+        (new OutputStreamClosure()).run();
+    }
+
+    @Override
+    protected void runServerApplication(SSLSocket socket) throws Exception {
+        // here comes the test logic
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write(85);
+        sslOS.flush();
+    }
+
+    /*
+     * Define the client side application of the test for the specified socket.
+     * This method is used if the returned value of
+     * isCustomizedClientConnection() is false.
+     *
+     * @param socket may be null is no client socket is generated.
+     *
+     * @see #isCustomizedClientConnection()
+     */
+    protected void runClientApplication(SSLSocket socket) throws Exception {
+        InputStream sslIS = socket.getInputStream();
+        OutputStream sslOS = socket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslOS.close();
+        if (!socket.isClosed()) {
+            throw new Exception("Closing the SSLSocket OutputStream does " +
+                    "not close the associated socket");
+        }
+    }
+}
--- a/test/jdk/tools/launcher/Settings.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/tools/launcher/Settings.java	Fri Apr 19 08:00:42 2019 -0400
@@ -68,6 +68,7 @@
     private static final String PROP_SETTINGS = "Property settings:";
     private static final String LOCALE_SETTINGS = "Locale settings:";
     private static final String SYSTEM_SETTINGS = "Operating System Metrics:";
+    private static final String STACKSIZE_SETTINGS = "Stack Size:";
 
     static void containsAllOptions(TestResult tr) {
         checkContains(tr, VM_SETTINGS);
@@ -82,10 +83,22 @@
         int stackSize = 256; // in kb
         if (getArch().equals("ppc64") || getArch().equals("ppc64le")) {
             stackSize = 800;
+        } else if (getArch().equals("aarch64")) {
+            /*
+             * The max value of minimum stack size allowed for aarch64 can be estimated as
+             * such: suppose the vm page size is 64KB and the test runs with a debug build,
+             * the initial _java_thread_min_stack_allowed defined in os_linux_aarch64.cpp is
+             * 72K, stack guard zones could take 192KB, and the shadow zone needs 128KB,
+             * after aligning up all parts to the page size, the final size would be 448KB.
+             * See details in JDK-8163363
+             */
+            stackSize = 448;
         }
         TestResult tr;
         tr = doExec(javaCmd, "-Xms64m", "-Xmx512m",
                 "-Xss" + stackSize + "k", "-XshowSettings", "-jar", testJar.getAbsolutePath());
+        // Check the stack size logs printed by -XshowSettings to verify -Xss meaningfully.
+        checkContains(tr, STACKSIZE_SETTINGS);
         containsAllOptions(tr);
         if (!tr.isOK()) {
             System.out.println(tr);
@@ -93,6 +106,7 @@
         }
         tr = doExec(javaCmd, "-Xms65536k", "-Xmx712m",
                 "-Xss" + (stackSize * 1024), "-XshowSettings", "-jar", testJar.getAbsolutePath());
+        checkContains(tr, STACKSIZE_SETTINGS);
         containsAllOptions(tr);
         if (!tr.isOK()) {
             System.out.println(tr);
--- a/test/jdk/tools/launcher/TooSmallStackSize.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/tools/launcher/TooSmallStackSize.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6762191
+ * @bug 6762191 8222334
  * @summary Setting stack size to 16K causes segmentation fault
  * @compile TooSmallStackSize.java
  * @run main TooSmallStackSize
@@ -171,5 +171,11 @@
          * asserts added for 8176768 are not triggered.
          */
         checkMinStackAllowed("513k");
+
+        /*
+         * Try with 0k which indicates that the default thread stack size either from JVM or system
+         * will be used, this should always succeed.
+         */
+        checkMinStackAllowed("0k");
     }
 }
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -59,7 +59,7 @@
                 .classes(classPath.toString())
                 .run()
                 .getOutput(Task.OutputKind.DIRECT);
-        if (!javapOut.contains("0: #21(): CLASS_EXTENDS, type_index=65535"))
+        if (!javapOut.contains("0: #22(): CLASS_EXTENDS, type_index=65535"))
             throw new AssertionError("Expected output missing: " + javapOut);
     }
 }
\ No newline at end of file
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -74,14 +74,14 @@
     // Expected output can't be directly encoded into NestedLambdasCastedTest !!!
     static class OutputExpectedOnceHolder {
         public String[] outputs = {
-            "0: #61(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
-            "1: #61(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
+            "0: #120(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
+            "1: #120(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
         };
     }
 
     static class OutputExpectedTwiceHolder {
         public String[] outputs = {
-            "0: #61(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
+            "0: #120(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
         };
     }
 
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -53,10 +53,10 @@
                       "private static strictfp void lambda$main$2();",
                       "private static strictfp void lambda$main$1();",
                       "private static strictfp void lambda$main$0();",
-                      "0: #62(#63=s#64): CAST, offset=5, type_index=0",
-                      "0: #62(#63=s#69): CAST, offset=5, type_index=0",
-                      "0: #62(#63=s#72): CAST, offset=5, type_index=0",
-                      "0: #62(#63=s#75): CAST, offset=5, type_index=0"
+                      "0: #111(#112=s#113): CAST, offset=5, type_index=0",
+                      "0: #111(#112=s#119): CAST, offset=5, type_index=0",
+                      "0: #111(#112=s#122): CAST, offset=5, type_index=0",
+                      "0: #111(#112=s#125): CAST, offset=5, type_index=0"
         };
     }
 
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Fri Apr 19 08:00:42 2019 -0400
@@ -46,6 +46,7 @@
 compiler.misc.bad.class.signature                       # bad class file
 compiler.misc.bad.const.pool.tag                        # bad class file
 compiler.misc.bad.const.pool.tag.at                     # bad class file
+compiler.misc.bad.const.pool.index                      # bad class file
 compiler.misc.bad.constant.range                        # bad class file
 compiler.misc.bad.constant.value                        # bad class file
 compiler.misc.bad.enclosing.class                       # bad class file
--- a/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java	Fri Apr 19 08:00:42 2019 -0400
@@ -61,6 +61,7 @@
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 import com.sun.tools.javac.tree.JCTree.JCIdent;
@@ -190,7 +191,7 @@
             Symbol oldSym = ident.sym;
             if (!oldSym.isConstructor()) {
                 ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
-                        oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]);
+                        oldSym.owner, bsm.asHandle(), oldSym.type, new LoadableConstant[0]);
             }
             return null;
         }
--- a/test/langtools/tools/javac/lambda/TestInvokeDynamic.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/lambda/TestInvokeDynamic.java	Fri Apr 19 08:00:42 2019 -0400
@@ -60,26 +60,23 @@
 import com.sun.tools.classfile.LineNumberTable_attribute;
 import com.sun.tools.classfile.Method;
 
-import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.jvm.Pool;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 import com.sun.tools.javac.tree.JCTree.JCIdent;
-import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Names;
 
 import combo.ComboParameter;
-import combo.ComboTask;
 import combo.ComboTestHelper;
 import combo.ComboInstance;
 import combo.ComboTask.Result;
 
-import static com.sun.tools.javac.jvm.ClassFile.*;
-
 public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
 
     enum StaticArgumentKind implements ComboParameter {
@@ -168,21 +165,24 @@
 
         abstract boolean check(CPInfo cpInfo) throws Exception;
 
-        Object getValue(Symtab syms, Names names, Types types) {
+        LoadableConstant getValue(Symtab syms) {
             switch (this) {
                 case STRING:
+                    return LoadableConstant.String((String)value);
                 case INTEGER:
+                    return LoadableConstant.Int((Integer)value);
                 case LONG:
+                    return LoadableConstant.Long((Long)value);
                 case FLOAT:
+                    return LoadableConstant.Float((Float)value);
                 case DOUBLE:
-                    return value;
+                    return LoadableConstant.Double((Double)value);
                 case CLASS:
-                    return syms.stringType.tsym;
+                    return (ClassType)syms.stringType;
                 case METHOD_HANDLE:
-                    return new Pool.MethodHandle(REF_invokeVirtual,
-                            syms.arrayCloneMethod, types);
+                    return syms.arrayCloneMethod.asHandle();
                 case METHOD_TYPE:
-                    return syms.arrayCloneMethod.type;
+                    return ((MethodType)syms.arrayCloneMethod.type);
                 default:
                     throw new AssertionError();
             }
@@ -394,7 +394,7 @@
 
     class Indifier extends TreeScanner<Void, Void> implements TaskListener {
 
-        MethodSymbol bsm;
+        MethodHandleSymbol bsm;
         Symtab syms;
         Names names;
         Types types;
@@ -424,12 +424,12 @@
             JCIdent ident = (JCIdent)apply.meth;
             Symbol oldSym = ident.sym;
             if (!oldSym.isConstructor()) {
-                Object[] staticArgs = new Object[arity.arity];
+                LoadableConstant[] staticArgs = new LoadableConstant[arity.arity];
                 for (int i = 0; i < arity.arity ; i++) {
-                    staticArgs[i] = saks[i].getValue(syms, names, types);
+                    staticArgs[i] = saks[i].getValue(syms);
                 }
                 ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
-                        oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
+                        oldSym.owner, bsm, oldSym.type, staticArgs);
             }
             return null;
         }
@@ -438,7 +438,7 @@
         public Void visitMethod(MethodTree node, Void p) {
             super.visitMethod(node, p);
             if (node.getName().toString().equals("bsm")) {
-                bsm = ((JCMethodDecl)node).sym;
+                bsm = ((JCMethodDecl)node).sym.asHandle();
             }
             return null;
         }
--- a/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out	Fri Apr 19 08:00:42 2019 -0400
@@ -1,2 +1,2 @@
-- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: mod/module-info, <error>))
+- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.const.pool.index: module-info.class, 15, 10))
 1 error
--- a/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java	Fri Apr 19 08:00:42 2019 -0400
@@ -90,8 +90,8 @@
                         "NestHost: class CheckNestmateAttrs",
                         "0: aload_0",
                         "1: getfield      #1                  // Field this$1:LCheckNestmateAttrs$Inner;",
-                        "4: getfield      #3                  // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
-                        "7: invokevirtual #4                  // Method CheckNestmateAttrs.test:()V",
+                        "4: getfield      #13                 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
+                        "7: invokevirtual #19                 // Method CheckNestmateAttrs.test:()V",
                         "10: return"
         });
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/environment/TestPreviewEnabled.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8222378
+ * @summary Test that ProcessingEnvironment.isPreviewEnabled works properly
+ * @library /tools/javac/lib
+ * @modules java.compiler
+ * @build   JavacTestingAbstractProcessor
+ * @compile TestPreviewEnabled.java
+ * @compile -processor TestPreviewEnabled -proc:only -source ${jdk.version} -AExpectedPreview=false                  TestSourceVersion.java
+ * @compile -processor TestPreviewEnabled -proc:only -source ${jdk.version} -AExpectedPreview=true  --enable-preview TestSourceVersion.java
+ */
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import javax.annotation.processing.*;
+import javax.lang.model.util.*;
+
+/**
+ * This processor checks that ProcessingEnvironment.isPreviewEnabled
+ * is consistent with the compiler options.
+ */
+@SupportedOptions("ExpectedPreview")
+public class TestPreviewEnabled extends JavacTestingAbstractProcessor {
+    public boolean process(Set<? extends TypeElement> annotations,
+                           RoundEnvironment roundEnvironment) {
+        if (!roundEnvironment.processingOver()) {
+            boolean expectedPreview =
+                Boolean.valueOf(processingEnv.getOptions().get("ExpectedPreview"));
+            boolean actualPreview =  processingEnv.isPreviewEnabled();
+            System.out.println("Expected PreviewEnabled: " + expectedPreview +
+                               "\n  actual PreviewEnabled: "  + actualPreview);
+            if (expectedPreview != actualPreview)
+                throw new RuntimeException();
+
+            if (expectedPreview) {
+                // Create a ProcessingEnvironment that uses the
+                // default implemention of isPreviewEnabled.
+                ProcessingEnvironment testEnv = new ProcessingEnvironment() {
+                        @Override public Elements getElementUtils() {return null;}
+                        @Override public Filer getFiler() {return null;}
+                        @Override public Locale getLocale() {return null;}
+                        @Override public Messager getMessager() {return null;}
+                        @Override public Map<String,String> getOptions() {return null;}
+                        @Override public SourceVersion getSourceVersion() {return null;}
+                        @Override public Types getTypeUtils() {return null;}
+                    };
+                if (testEnv.isPreviewEnabled()) {
+                    throw new RuntimeException("Bad true return value from default " +
+                                               "ProcessingEnvironment.isPreviewEnabled.");
+                }
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.java	Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8222430
+ * @summary Test various predicates of ElementKind.
+ */
+
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.lang.model.element.ElementKind;
+
+/**
+ * Test the isClass, isField, and isInterface predicates of ElementKind.
+ */
+public class TestElementKindPredicates {
+    public static void main(String... args) {
+        Set<ElementKind> ALL_KINDS = Set.of(ElementKind.values());
+
+        // isClass: Returns true if this is a kind of class: either CLASS or ENUM.
+        test(ALL_KINDS,
+             (ElementKind k) -> Set.of(ElementKind.CLASS,
+                                       ElementKind.ENUM).contains(k),
+             (ElementKind k) -> k.isClass(), "isClass");
+
+        // isField: Returns true if this is a kind of field: either FIELD or ENUM_CONSTANT.
+        test(ALL_KINDS,
+             (ElementKind k) -> Set.of(ElementKind.FIELD,
+                                       ElementKind.ENUM_CONSTANT).contains(k),
+             (ElementKind k) -> k.isField(), "isField");
+
+        // isInterface: Returns true if this is a kind of interface: either INTERFACE or ANNOTATION_TYPE.
+        test(ALL_KINDS,
+             (ElementKind k) -> Set.of(ElementKind.INTERFACE,
+                                       ElementKind.ANNOTATION_TYPE).contains(k),
+             (ElementKind k) -> k.isInterface(), "isInterface");
+    }
+
+    private static void test(Set<ElementKind> kinds,
+                             Predicate<ElementKind> expectedPred,
+                             Predicate<ElementKind> actualPred,
+                             String errorMessage) {
+        for(ElementKind kind : kinds) {
+            boolean expected = expectedPred.test(kind);
+            boolean actual = actualPred.test(kind);
+
+            if (expected != actual) {
+                throw new RuntimeException("Error testing ElementKind." + errorMessage + "(" +  kind +
+                                           "):\texpected " + expected + "\tgot " + actual);
+            }
+        }
+    }
+}
--- a/test/langtools/tools/javap/AnnoTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/AnnoTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -49,50 +49,50 @@
 
         expect(out,
                 "RuntimeVisibleAnnotations:\n" +
-                "  0: #18(#19=B#20)\n" +
+                "  0: #21(#22=B#23)\n" +
                 "    AnnoTest$ByteAnno(\n" +
                 "      value=(byte) 42\n" +
                 "    )\n" +
-                "  1: #23(#19=S#24)\n" +
+                "  1: #24(#22=S#25)\n" +
                 "    AnnoTest$ShortAnno(\n" +
                 "      value=(short) 3\n" +
                 "    )");
         expect(out,
                 "RuntimeInvisibleAnnotations:\n" +
-                "  0: #28(#19=[J#29,J#31,J#33,J#35,J#37])\n" +
+                "  0: #27(#22=[J#28,J#30,J#32,J#34,J#36])\n" +
                 "    AnnoTest$ArrayAnno(\n" +
                 "      value=[1l,2l,3l,4l,5l]\n" +
                 "    )\n" +
-                "  1: #41(#19=Z#42)\n" +
+                "  1: #38(#22=Z#39)\n" +
                 "    AnnoTest$BooleanAnno(\n" +
                 "      value=false\n" +
                 "    )\n" +
-                "  2: #45(#46=c#47)\n" +
+                "  2: #40(#41=c#42)\n" +
                 "    AnnoTest$ClassAnno(\n" +
                 "      type=class Ljava/lang/Object;\n" +
                 "    )\n" +
-                "  3: #50(#51=e#52.#53)\n" +
+                "  3: #43(#44=e#45.#46)\n" +
                 "    AnnoTest$EnumAnno(\n" +
                 "      kind=Ljavax/lang/model/element/ElementKind;.PACKAGE\n" +
                 "    )\n" +
-                "  4: #56(#19=I#57)\n" +
+                "  4: #47(#22=I#48)\n" +
                 "    AnnoTest$IntAnno(\n" +
                 "      value=2\n" +
                 "    )\n" +
-                "  5: #60()\n" +
+                "  5: #49()\n" +
                 "    AnnoTest$IntDefaultAnno\n" +
-                "  6: #63(#64=s#65)\n" +
+                "  6: #50(#51=s#52)\n" +
                 "    AnnoTest$NameAnno(\n" +
                 "      name=\"NAME\"\n" +
                 "    )\n" +
-                "  7: #68(#69=D#70,#72=F#73)\n" +
+                "  7: #53(#54=D#55,#57=F#58)\n" +
                 "    AnnoTest$MultiAnno(\n" +
                 "      d=3.14159d\n" +
                 "      f=2.71828f\n" +
                 "    )\n" +
-                "  8: #76()\n" +
+                "  8: #59()\n" +
                 "    AnnoTest$SimpleAnno\n" +
-                "  9: #79(#19=@#56(#19=I#80))\n" +
+                "  9: #60(#22=@#47(#22=I#61))\n" +
                 "    AnnoTest$AnnoAnno(\n" +
                 "      value=@AnnoTest$IntAnno(\n" +
                 "        value=5\n" +
@@ -100,7 +100,7 @@
                 "    )");
         expect(out,
                 "RuntimeInvisibleTypeAnnotations:\n" +
-                "  0: #84(): CLASS_EXTENDS, type_index=0\n" +
+                "  0: #63(): CLASS_EXTENDS, type_index=0\n" +
                 "    AnnoTest$TypeAnno");
 
         if (errors > 0)
--- a/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -51,7 +51,7 @@
 
     private static final String ExpectedSubstring =
             "    AnnotationDefault:\n" +
-            "      default_value: I#7\n";
+            "      default_value: I#9\n";
 
     public static void main(String[] args) throws Exception {
         ToolBox tb = new ToolBox();
--- a/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java	Fri Apr 19 08:00:42 2019 -0400
@@ -62,11 +62,11 @@
             "    RuntimeVisibleParameterAnnotations:\n" +
             "      parameter 0:\n" +
             "      parameter 1:\n" +
-            "        0: #16()\n" +
+            "        0: #14()\n" +
             "          Sample$VisAnno\n" +
             "    RuntimeInvisibleParameterAnnotations:\n" +
             "      parameter 0:\n" +
-            "        0: #18()\n" +
+            "        0: #16()\n" +
             "          Sample$InvisAnno\n" +
             "      parameter 1:";
 
--- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
 
 import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -59,6 +61,15 @@
     /**
      * Create an OutputAnalyzer, a utility class for verifying output
      *
+     * @param file File to analyze
+     */
+    public OutputAnalyzer(Path file) throws IOException {
+        this(Files.readString(file));
+    }
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output
+     *
      * @param stdout stdout buffer to analyze
      * @param stderr stderr buffer to analyze
      */
--- a/test/micro/org/openjdk/bench/java/lang/StringConcat.java	Fri Apr 19 07:55:28 2019 -0400
+++ b/test/micro/org/openjdk/bench/java/lang/StringConcat.java	Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,6 +63,11 @@
     }
 
     @Benchmark
+    public String concatMethodConstString() {
+        return "string".concat(stringValue);
+    }
+
+    @Benchmark
     public String concatConstIntConstInt() {
         return "string" + intValue + "string" + intValue;
     }