Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index ccaf36f..2d52060 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -964,4 +964,7 @@
 f0f617923cebf0b6dfc1c4cd61467fea847b028d jdk8u222-b06
 f321c0bb9fb3124dc35c98d5114c1a8cf4b3d498 jdk8u222-b07
 945f4ae40e436792154bfa77336e1d466606ae00 jdk8u222-b08
+8f29b4acc5d2ee4131b1f13d8c3e57be3dcc63a9 jdk8u232-b00
 81dd104fa95943fe02bc013d36155b5f4d54210d jdk8u222-b09
+eeeabadc6bf04d70c2fb8e0492abbf30143d26f0 jdk8u222-b10
+eeeabadc6bf04d70c2fb8e0492abbf30143d26f0 jdk8u222-ga
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index 90d9412..09b79bb 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -388,16 +388,8 @@
     CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
     CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
   elif test "x$TOOLCHAIN_TYPE" = xgcc; then
-    case $OPENJDK_TARGET_CPU_ARCH in
-    x86 )
-      LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
-      LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
-      ;;
-    x86_64 )
-      LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
-      LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
-      ;;
-    esac
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
     if test "x$OPENJDK_TARGET_OS" != xmacosx; then
       LDFLAGS_JDK="$LDFLAGS_JDK -Wl,-z,relro"
       LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS -Wl,-z,relro"
@@ -456,7 +448,7 @@
   if test "x$TOOLCHAIN_TYPE" = xgcc; then
     # these options are used for both C and C++ compiles
     CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \
-        -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
+        -pipe -fstack-protector -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
     case $OPENJDK_TARGET_CPU_ARCH in
       arm )
         # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing
@@ -465,10 +457,6 @@
       ppc )
         # on ppc we don't prevent gcc to omit frame pointer nor strict-aliasing
         ;;
-      x86 )
-        CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer -fstack-protector"
-        CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing -fstack-protector"
-        ;;
       * )
         CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer"
         CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index c8d6ee0..3f69c91 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -4376,7 +4376,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1556533111
+DATE_WHEN_GENERATED=1560366811
 
 ###############################################################################
 #
@@ -41432,16 +41432,8 @@
     CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
     CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
   elif test "x$TOOLCHAIN_TYPE" = xgcc; then
-    case $OPENJDK_TARGET_CPU_ARCH in
-    x86 )
-      LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
-      LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
-      ;;
-    x86_64 )
-      LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
-      LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
-      ;;
-    esac
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
     if test "x$OPENJDK_TARGET_OS" != xmacosx; then
       LDFLAGS_JDK="$LDFLAGS_JDK -Wl,-z,relro"
       LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS -Wl,-z,relro"
@@ -41552,7 +41544,7 @@
   if test "x$TOOLCHAIN_TYPE" = xgcc; then
     # these options are used for both C and C++ compiles
     CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \
-        -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
+        -pipe -fstack-protector -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
     case $OPENJDK_TARGET_CPU_ARCH in
       arm )
         # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing
@@ -41561,10 +41553,6 @@
       ppc )
         # on ppc we don't prevent gcc to omit frame pointer nor strict-aliasing
         ;;
-      x86 )
-        CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer -fstack-protector"
-        CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing -fstack-protector"
-        ;;
       * )
         CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer"
         CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
diff --git a/corba/.hgtags b/corba/.hgtags
index 7a4531b..a4955f6 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -1037,4 +1037,7 @@
 74bdd387f873523cae121fa48056fb662e289679 jdk8u222-b06
 3abf299d26c40608af206c3b43c35b7ab2aade07 jdk8u222-b07
 d8e58175603e92f46baa775c878cf346181cafed jdk8u222-b08
+5837b825d94bd4fbc1bff28099810e8bcb1e848a jdk8u232-b00
 60d5ceb1043500475c41501de673b9582ef4d97b jdk8u222-b09
+d44170c2cecec81b5f328d40529cb78bfd0bbb1c jdk8u222-b10
+d44170c2cecec81b5f328d40529cb78bfd0bbb1c jdk8u222-ga
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index d3b1151..8b57637 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -1270,4 +1270,7 @@
 17778f8991c83d794897f05210dce2d2a7b4eb2d jdk8u222-b06
 75f4e02f1113bc353fc60df7330dd5456efc49a3 jdk8u222-b07
 36a743eee6721b423b7c21a3ba28ac8d906a5386 jdk8u222-b08
+1ec20e8a3d8a7a29e9113b14567abec9f0240e9d jdk8u232-b00
 55f693ba975d445d83a59cc32367ec4c2452b0c5 jdk8u222-b09
+adfdce09acc32a691145a67792d47ab637159776 jdk8u222-b10
+adfdce09acc32a691145a67792d47ab637159776 jdk8u222-ga
diff --git a/hotspot/agent/src/os/linux/ps_core.c b/hotspot/agent/src/os/linux/ps_core.c
index 541c857..c62e58d 100644
--- a/hotspot/agent/src/os/linux/ps_core.c
+++ b/hotspot/agent/src/os/linux/ps_core.c
@@ -865,8 +865,51 @@
 #define LD_BASE_OFFSET        offsetof(struct r_debug,  r_ldbase)
 #define LINK_MAP_ADDR_OFFSET  offsetof(struct link_map, l_addr)
 #define LINK_MAP_NAME_OFFSET  offsetof(struct link_map, l_name)
+#define LINK_MAP_LD_OFFSET    offsetof(struct link_map, l_ld)
 #define LINK_MAP_NEXT_OFFSET  offsetof(struct link_map, l_next)
 
+// Calculate the load address of shared library
+// on prelink-enabled environment.
+//
+// In case of GDB, it would be calculated by offset of link_map.l_ld
+// and the address of .dynamic section.
+// See GDB implementation: lm_addr_check @ solib-svr4.c
+static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* elf_ehdr, uintptr_t link_map_addr) {
+  ELF_PHDR *phbuf;
+  uintptr_t lib_ld;
+  uintptr_t lib_dyn_addr = 0L;
+  uintptr_t load_addr;
+  int i;
+
+  phbuf = read_program_header_table(lib_fd, elf_ehdr);
+  if (phbuf == NULL) {
+    print_debug("can't read program header of shared object\n");
+    return 0L;
+  }
+
+  // Get the address of .dynamic section from shared library.
+  for (i = 0; i < elf_ehdr->e_phnum; i++) {
+    if (phbuf[i].p_type == PT_DYNAMIC) {
+      lib_dyn_addr = phbuf[i].p_vaddr;
+      break;
+    }
+  }
+
+  free(phbuf);
+
+  if (ps_pdread(ph, (psaddr_t)link_map_addr + LINK_MAP_LD_OFFSET,
+               &lib_ld, sizeof(uintptr_t)) != PS_OK) {
+    print_debug("can't read address of dynamic section in shared object\n");
+    return 0L;
+  }
+
+  // Return the load address which is calculated by the address of .dynamic
+  // and link_map.l_ld .
+  load_addr = lib_ld - lib_dyn_addr;
+  print_debug("lib_ld = 0x%lx, lib_dyn_addr = 0x%lx -> lib_base_diff = 0x%lx\n", lib_ld, lib_dyn_addr, load_addr);
+  return load_addr;
+}
+
 // read shared library info from runtime linker's data structures.
 // This work is done by librtlb_db in Solaris
 static bool read_shared_lib_info(struct ps_prochandle* ph) {
@@ -968,6 +1011,14 @@
             // continue with other libraries...
          } else {
             if (read_elf_header(lib_fd, &elf_ehdr)) {
+               if (lib_base_diff == 0x0L) {
+                 lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr);
+                 if (lib_base_diff == 0x0L) {
+                   close(lib_fd);
+                   return false;
+                 }
+               }
+
                lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
                print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
                            lib_name, lib_base, lib_base_diff);
diff --git a/hotspot/make/aix/makefiles/jsig.make b/hotspot/make/aix/makefiles/jsig.make
index f8bf938..ae453f2 100644
--- a/hotspot/make/aix/makefiles/jsig.make
+++ b/hotspot/make/aix/makefiles/jsig.make
@@ -54,10 +54,15 @@
   JSIG_DEBUG_CFLAGS = -g
 endif
 
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+  JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
 $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CXX) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
-                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl
+                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) -o $@ $< -ldl
 
 #ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 #	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
diff --git a/hotspot/make/bsd/makefiles/jsig.make b/hotspot/make/bsd/makefiles/jsig.make
index 29779b0..b5860bf 100644
--- a/hotspot/make/bsd/makefiles/jsig.make
+++ b/hotspot/make/bsd/makefiles/jsig.make
@@ -59,10 +59,15 @@
   JSIG_DEBUG_CFLAGS = -g
 endif
 
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+  JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
 $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
-                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) $(EXTRA_CFLAGS) -o $@ $<
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifeq ($(OS_VENDOR), Darwin)
 	$(DSYMUTIL) $@
diff --git a/hotspot/make/linux/makefiles/jsig.make b/hotspot/make/linux/makefiles/jsig.make
index 9bf3b73..6290db5 100644
--- a/hotspot/make/linux/makefiles/jsig.make
+++ b/hotspot/make/linux/makefiles/jsig.make
@@ -51,10 +51,15 @@
   JSIG_DEBUG_CFLAGS = -g
 endif
 
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+  JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
 $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
-                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $< -ldl
+                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) $(EXTRA_CFLAGS) -o $@ $< -ldl
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifneq ($(STRIP_POLICY),no_strip)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
diff --git a/hotspot/make/solaris/makefiles/jsig.make b/hotspot/make/solaris/makefiles/jsig.make
index bbc0982..74b0721 100644
--- a/hotspot/make/solaris/makefiles/jsig.make
+++ b/hotspot/make/solaris/makefiles/jsig.make
@@ -47,10 +47,15 @@
 LFLAGS_JSIG += -mt -xnolib
 endif
 
+# Optimize jsig lib unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+  JSIG_OPT_FLAGS = -xO4 -g
+endif
+
 $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
 	@echo Making signal interposition lib...
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
-                         $(LFLAGS_JSIG) -o $@ $(JSIGSRCDIR)/jsig.c -ldl
+                         $(LFLAGS_JSIG) $(JSIG_OPT_FLAGS) -o $@ $(JSIGSRCDIR)/jsig.c -ldl
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
 	$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
 	$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@
diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
index b14f2b6..16884ca 100644
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp
@@ -2000,7 +2000,8 @@
   inline void vsbox(       VectorRegister d, VectorRegister a);
 
   // SHA (introduced with Power 8)
-  // Not yet implemented.
+  inline void vshasigmad(VectorRegister d, VectorRegister a, bool st, int six);
+  inline void vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six);
 
   // Vector Binary Polynomial Multiplication (introduced with Power 8)
   inline void vpmsumb(  VectorRegister d, VectorRegister a, VectorRegister b);
@@ -2096,6 +2097,10 @@
   inline void lvsl(  VectorRegister d, Register s2);
   inline void lvsr(  VectorRegister d, Register s2);
 
+  // Endianess specific concatenation of 2 loaded vectors.
+  inline void load_perm(VectorRegister perm, Register addr);
+  inline void vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm);
+
   // RegisterOrConstant versions.
   // These emitters choose between the versions using two registers and
   // those with register and immediate, depending on the content of roc.
diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp
index 1d2c05e..badeecf 100644
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp
@@ -789,7 +789,8 @@
 inline void Assembler::vsbox(       VectorRegister d, VectorRegister a)                   { emit_int32( VSBOX_OPCODE        | vrt(d) | vra(a)         ); }
 
 // SHA (introduced with Power 8)
-// Not yet implemented.
+inline void Assembler::vshasigmad(VectorRegister d, VectorRegister a, bool st, int six) { emit_int32( VSHASIGMAD_OPCODE | vrt(d) | vra(a) | vst(st) | vsix(six)); }
+inline void Assembler::vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six) { emit_int32( VSHASIGMAW_OPCODE | vrt(d) | vra(a) | vst(st) | vsix(six)); }
 
 // Vector Binary Polynomial Multiplication (introduced with Power 8)
 inline void Assembler::vpmsumb(  VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMB_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -887,6 +888,22 @@
 inline void Assembler::lvsl(  VectorRegister d, Register s2) { emit_int32( LVSL_OPCODE   | vrt(d) | rb(s2)); }
 inline void Assembler::lvsr(  VectorRegister d, Register s2) { emit_int32( LVSR_OPCODE   | vrt(d) | rb(s2)); }
 
+inline void Assembler::load_perm(VectorRegister perm, Register addr) {
+#if defined(VM_LITTLE_ENDIAN)
+  lvsr(perm, addr);
+#else
+  lvsl(perm, addr);
+#endif
+}
+
+inline void Assembler::vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm) {
+#if defined(VM_LITTLE_ENDIAN)
+  vperm(first_dest, second, first_dest, perm);
+#else
+  vperm(first_dest, first_dest, second, perm);
+#endif
+}
+
 inline void Assembler::load_const(Register d, void* x, Register tmp) {
    load_const(d, (long)x, tmp);
 }
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
index 3c6cea5..afcec9a 100644
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
@@ -667,6 +667,40 @@
 
   void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp);
 
+  // SHA-2 auxiliary functions and public interfaces
+ private:
+  void sha256_deque(const VectorRegister src,
+      const VectorRegister dst1, const VectorRegister dst2, const VectorRegister dst3);
+  void sha256_load_h_vec(const VectorRegister a, const VectorRegister e, const Register hptr);
+  void sha256_round(const VectorRegister* hs, const int total_hs, int& h_cnt, const VectorRegister kpw);
+  void sha256_load_w_plus_k_vec(const Register buf_in, const VectorRegister* ws,
+      const int total_ws, const Register k, const VectorRegister* kpws,
+      const int total_kpws);
+  void sha256_calc_4w(const VectorRegister w0, const VectorRegister w1,
+      const VectorRegister w2, const VectorRegister w3, const VectorRegister kpw0,
+      const VectorRegister kpw1, const VectorRegister kpw2, const VectorRegister kpw3,
+      const Register j, const Register k);
+  void sha256_update_sha_state(const VectorRegister a, const VectorRegister b,
+      const VectorRegister c, const VectorRegister d, const VectorRegister e,
+      const VectorRegister f, const VectorRegister g, const VectorRegister h,
+      const Register hptr);
+
+  void sha512_load_w_vec(const Register buf_in, const VectorRegister* ws, const int total_ws);
+  void sha512_update_sha_state(const Register state, const VectorRegister* hs, const int total_hs);
+  void sha512_round(const VectorRegister* hs, const int total_hs, int& h_cnt, const VectorRegister kpw);
+  void sha512_load_h_vec(const Register state, const VectorRegister* hs, const int total_hs);
+  void sha512_calc_2w(const VectorRegister w0, const VectorRegister w1,
+      const VectorRegister w2, const VectorRegister w3,
+      const VectorRegister w4, const VectorRegister w5,
+      const VectorRegister w6, const VectorRegister w7,
+      const VectorRegister kpw0, const VectorRegister kpw1, const Register j,
+      const VectorRegister vRb, const Register k);
+
+ public:
+  void sha256(bool multi_block);
+  void sha512(bool multi_block);
+
+
   //
   // Debugging
   //
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp
new file mode 100644
index 0000000..7a82ed3
--- /dev/null
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp
@@ -0,0 +1,1136 @@
+// Copyright (c) 2017 Instituto de Pesquisas Eldorado. All rights reserved.
+// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+//
+// This code is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 2 only, as
+// published by the Free Software Foundation.
+//
+// This code is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// version 2 for more details (a copy is included in the LICENSE file that
+// accompanied this code).
+//
+// You should have received a copy of the GNU General Public License version
+// 2 along with this work; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+// or visit www.oracle.com if you need additional information or have any
+// questions.
+
+// Implemented according to "Descriptions of SHA-256, SHA-384, and SHA-512"
+// (http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf).
+
+#include "asm/macroAssembler.inline.hpp"
+#include "runtime/stubRoutines.hpp"
+
+/**********************************************************************
+ * SHA 256
+ *********************************************************************/
+
+void MacroAssembler::sha256_deque(const VectorRegister src,
+                                  const VectorRegister dst1,
+                                  const VectorRegister dst2,
+                                  const VectorRegister dst3) {
+  vsldoi (dst1, src, src, 12);
+  vsldoi (dst2, src, src, 8);
+  vsldoi (dst3, src, src, 4);
+}
+
+void MacroAssembler::sha256_round(const VectorRegister* hs,
+                                  const int total_hs,
+                                  int& h_cnt,
+                                  const VectorRegister kpw) {
+  // convenience registers: cycle from 0-7 downwards
+  const VectorRegister a = hs[(total_hs + 0 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister b = hs[(total_hs + 1 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister c = hs[(total_hs + 2 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister d = hs[(total_hs + 3 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister e = hs[(total_hs + 4 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister f = hs[(total_hs + 5 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister g = hs[(total_hs + 6 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister h = hs[(total_hs + 7 - (h_cnt % total_hs)) % total_hs];
+  // temporaries
+  VectorRegister ch  = VR0;
+  VectorRegister maj = VR1;
+  VectorRegister bsa = VR2;
+  VectorRegister bse = VR3;
+  VectorRegister vt0 = VR4;
+  VectorRegister vt1 = VR5;
+  VectorRegister vt2 = VR6;
+  VectorRegister vt3 = VR7;
+
+  vsel       (ch,  g,   f, e);
+  vxor       (maj, a,   b);
+  vshasigmaw (bse, e,   1, 0xf);
+  vadduwm    (vt2, ch,  kpw);
+  vadduwm    (vt1, h,   bse);
+  vsel       (maj, b,   c, maj);
+  vadduwm    (vt3, vt1, vt2);
+  vshasigmaw (bsa, a,   1, 0);
+  vadduwm    (vt0, bsa, maj);
+
+  vadduwm    (d,   d,   vt3);
+  vadduwm    (h,   vt3, vt0);
+
+  // advance vector pointer to the next iteration
+  h_cnt++;
+}
+
+void MacroAssembler::sha256_load_h_vec(const VectorRegister a,
+                                       const VectorRegister e,
+                                       const Register hptr) {
+  // temporaries
+  Register tmp = R8;
+  VectorRegister vt0 = VR0;
+  VectorRegister vRb = VR6;
+  // labels
+  Label sha256_aligned;
+
+  andi_  (tmp,  hptr, 0xf);
+  lvx    (a,    hptr);
+  addi   (tmp,  hptr, 16);
+  lvx    (e,    tmp);
+  beq    (CCR0, sha256_aligned);
+
+  // handle unaligned accesses
+  load_perm(vRb, hptr);
+  addi   (tmp, hptr, 32);
+  vec_perm(a,   e,    vRb);
+
+  lvx    (vt0,  tmp);
+  vec_perm(e,   vt0,  vRb);
+
+  // aligned accesses
+  bind(sha256_aligned);
+}
+
+void MacroAssembler::sha256_load_w_plus_k_vec(const Register buf_in,
+                                              const VectorRegister* ws,
+                                              const int total_ws,
+                                              const Register k,
+                                              const VectorRegister* kpws,
+                                              const int total_kpws) {
+  Label w_aligned, after_w_load;
+
+  Register tmp       = R8;
+  VectorRegister vt0 = VR0;
+  VectorRegister vt1 = VR1;
+  VectorRegister vRb = VR6;
+
+  andi_ (tmp, buf_in, 0xF);
+  beq   (CCR0, w_aligned); // address ends with 0x0, not 0x8
+
+  // deal with unaligned addresses
+  lvx    (ws[0], buf_in);
+  load_perm(vRb, buf_in);
+
+  for (int n = 1; n < total_ws; n++) {
+    VectorRegister w_cur = ws[n];
+    VectorRegister w_prev = ws[n-1];
+
+    addi (tmp, buf_in, n * 16);
+    lvx  (w_cur, tmp);
+    vec_perm(w_prev, w_cur, vRb);
+  }
+  addi   (tmp, buf_in, total_ws * 16);
+  lvx    (vt0, tmp);
+  vec_perm(ws[total_ws-1], vt0, vRb);
+  b      (after_w_load);
+
+  bind(w_aligned);
+
+  // deal with aligned addresses
+  lvx(ws[0], buf_in);
+  for (int n = 1; n < total_ws; n++) {
+    VectorRegister w = ws[n];
+    addi (tmp, buf_in, n * 16);
+    lvx  (w, tmp);
+  }
+
+  bind(after_w_load);
+
+#if defined(VM_LITTLE_ENDIAN)
+  // Byte swapping within int values
+  li       (tmp, 8);
+  lvsl     (vt0, tmp);
+  vspltisb (vt1, 0xb);
+  vxor     (vt1, vt0, vt1);
+  for (int n = 0; n < total_ws; n++) {
+    VectorRegister w = ws[n];
+    vec_perm(w, w, vt1);
+  }
+#endif
+
+  // Loading k, which is always aligned to 16-bytes
+  lvx    (kpws[0], k);
+  for (int n = 1; n < total_kpws; n++) {
+    VectorRegister kpw = kpws[n];
+    addi (tmp, k, 16 * n);
+    lvx  (kpw, tmp);
+  }
+
+  // Add w to K
+  assert(total_ws == total_kpws, "Redesign the loop below");
+  for (int n = 0; n < total_kpws; n++) {
+    VectorRegister kpw = kpws[n];
+    VectorRegister w   = ws[n];
+
+    vadduwm  (kpw, kpw, w);
+  }
+}
+
+void MacroAssembler::sha256_calc_4w(const VectorRegister w0,
+                                    const VectorRegister w1,
+                                    const VectorRegister w2,
+                                    const VectorRegister w3,
+                                    const VectorRegister kpw0,
+                                    const VectorRegister kpw1,
+                                    const VectorRegister kpw2,
+                                    const VectorRegister kpw3,
+                                    const Register j,
+                                    const Register k) {
+  // Temporaries
+  const VectorRegister  vt0  = VR0;
+  const VectorRegister  vt1  = VR1;
+  const VectorSRegister vsrt1 = vt1->to_vsr();
+  const VectorRegister  vt2  = VR2;
+  const VectorRegister  vt3  = VR3;
+  const VectorSRegister vst3 = vt3->to_vsr();
+  const VectorRegister  vt4  = VR4;
+
+  // load to k[j]
+  lvx        (vt0, j,   k);
+
+  // advance j
+  addi       (j,   j,   16); // 16 bytes were read
+
+#if defined(VM_LITTLE_ENDIAN)
+  // b = w[j-15], w[j-14], w[j-13], w[j-12]
+  vsldoi     (vt1, w1,  w0, 12);
+
+  // c = w[j-7], w[j-6], w[j-5], w[j-4]
+  vsldoi     (vt2, w3,  w2, 12);
+
+#else
+  // b = w[j-15], w[j-14], w[j-13], w[j-12]
+  vsldoi     (vt1, w0,  w1, 4);
+
+  // c = w[j-7], w[j-6], w[j-5], w[j-4]
+  vsldoi     (vt2, w2,  w3, 4);
+#endif
+
+  // d = w[j-2], w[j-1], w[j-4], w[j-3]
+  vsldoi     (vt3, w3,  w3, 8);
+
+  // b = s0(w[j-15]) , s0(w[j-14]) , s0(w[j-13]) , s0(w[j-12])
+  vshasigmaw (vt1, vt1, 0,  0);
+
+  // d = s1(w[j-2]) , s1(w[j-1]) , s1(w[j-4]) , s1(w[j-3])
+  vshasigmaw (vt3, vt3, 0,  0xf);
+
+  // c = s0(w[j-15]) + w[j-7],
+  //     s0(w[j-14]) + w[j-6],
+  //     s0(w[j-13]) + w[j-5],
+  //     s0(w[j-12]) + w[j-4]
+  vadduwm    (vt2, vt1, vt2);
+
+  // c = s0(w[j-15]) + w[j-7] + w[j-16],
+  //     s0(w[j-14]) + w[j-6] + w[j-15],
+  //     s0(w[j-13]) + w[j-5] + w[j-14],
+  //     s0(w[j-12]) + w[j-4] + w[j-13]
+  vadduwm    (vt2, vt2, w0);
+
+  // e = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+  //     s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+  //     s0(w[j-13]) + w[j-5] + w[j-14] + s1(w[j-4]), // UNDEFINED
+  //     s0(w[j-12]) + w[j-4] + w[j-13] + s1(w[j-3])  // UNDEFINED
+  vadduwm    (vt4, vt2, vt3);
+
+  // At this point, e[0] and e[1] are the correct values to be stored at w[j]
+  // and w[j+1].
+  // e[2] and e[3] are not considered.
+  // b = s1(w[j]) , s1(s(w[j+1]) , UNDEFINED , UNDEFINED
+  vshasigmaw (vt1, vt4, 0,  0xf);
+
+  // v5 = s1(w[j-2]) , s1(w[j-1]) , s1(w[j]) , s1(w[j+1])
+#if defined(VM_LITTLE_ENDIAN)
+  xxmrgld    (vst3, vsrt1, vst3);
+#else
+  xxmrghd    (vst3, vst3, vsrt1);
+#endif
+
+  // c = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+  //     s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+  //     s0(w[j-13]) + w[j-5] + w[j-14] + s1(w[j]),   // w[j+2]
+  //     s0(w[j-12]) + w[j-4] + w[j-13] + s1(w[j+1])  // w[j+4]
+  vadduwm    (vt2, vt2, vt3);
+
+  // Updating w0 to w3 to hold the new previous 16 values from w.
+  vmr        (w0,  w1);
+  vmr        (w1,  w2);
+  vmr        (w2,  w3);
+  vmr        (w3,  vt2);
+
+  // store k + w to v9 (4 values at once)
+#if defined(VM_LITTLE_ENDIAN)
+  vadduwm    (kpw0, vt2, vt0);
+
+  vsldoi     (kpw1, kpw0, kpw0, 12);
+  vsldoi     (kpw2, kpw0, kpw0, 8);
+  vsldoi     (kpw3, kpw0, kpw0, 4);
+#else
+  vadduwm    (kpw3, vt2, vt0);
+
+  vsldoi     (kpw2, kpw3, kpw3, 12);
+  vsldoi     (kpw1, kpw3, kpw3, 8);
+  vsldoi     (kpw0, kpw3, kpw3, 4);
+#endif
+}
+
+void MacroAssembler::sha256_update_sha_state(const VectorRegister a,
+                                             const VectorRegister b_,
+                                             const VectorRegister c,
+                                             const VectorRegister d,
+                                             const VectorRegister e,
+                                             const VectorRegister f,
+                                             const VectorRegister g,
+                                             const VectorRegister h,
+                                             const Register hptr) {
+  // temporaries
+  VectorRegister vt0  = VR0;
+  VectorRegister vt1  = VR1;
+  VectorRegister vt2  = VR2;
+  VectorRegister vt3  = VR3;
+  VectorRegister vt4  = VR4;
+  VectorRegister vt5  = VR5;
+  VectorRegister vaux = VR6;
+  VectorRegister vRb  = VR6;
+  Register tmp        = R8;
+  Register of16       = R8;
+  Register of32       = R9;
+  Label state_load_aligned;
+
+  // Load hptr
+  andi_   (tmp, hptr, 0xf);
+  li      (of16, 16);
+  lvx     (vt0, hptr);
+  lvx     (vt5, of16, hptr);
+  beq     (CCR0, state_load_aligned);
+
+  // handle unaligned accesses
+  li      (of32, 32);
+  load_perm(vRb, hptr);
+
+  vec_perm(vt0, vt5,  vRb);        // vt0 = hptr[0]..hptr[3]
+
+  lvx     (vt1, hptr, of32);
+  vec_perm(vt5, vt1,  vRb);        // vt5 = hptr[4]..hptr[7]
+
+  // aligned accesses
+  bind(state_load_aligned);
+
+#if defined(VM_LITTLE_ENDIAN)
+  vmrglw  (vt1, b_, a);            // vt1 = {a, b, ?, ?}
+  vmrglw  (vt2, d, c);             // vt2 = {c, d, ?, ?}
+  vmrglw  (vt3, f, e);             // vt3 = {e, f, ?, ?}
+  vmrglw  (vt4, h, g);             // vt4 = {g, h, ?, ?}
+  xxmrgld (vt1->to_vsr(), vt2->to_vsr(), vt1->to_vsr()); // vt1 = {a, b, c, d}
+  xxmrgld (vt3->to_vsr(), vt4->to_vsr(), vt3->to_vsr()); // vt3 = {e, f, g, h}
+  vadduwm (a,   vt0, vt1);         // a = {a+hptr[0], b+hptr[1], c+hptr[2], d+hptr[3]}
+  vadduwm (e,   vt5, vt3);         // e = {e+hptr[4], f+hptr[5], g+hptr[6], h+hptr[7]}
+
+  // Save hptr back, works for any alignment
+  xxswapd (vt0->to_vsr(), a->to_vsr());
+  stxvd2x (vt0->to_vsr(), hptr);
+  xxswapd (vt5->to_vsr(), e->to_vsr());
+  stxvd2x (vt5->to_vsr(), of16, hptr);
+#else
+  vmrglw  (vt1, a, b_);            // vt1 = {a, b, ?, ?}
+  vmrglw  (vt2, c, d);             // vt2 = {c, d, ?, ?}
+  vmrglw  (vt3, e, f);             // vt3 = {e, f, ?, ?}
+  vmrglw  (vt4, g, h);             // vt4 = {g, h, ?, ?}
+  xxmrgld (vt1->to_vsr(), vt1->to_vsr(), vt2->to_vsr()); // vt1 = {a, b, c, d}
+  xxmrgld (vt3->to_vsr(), vt3->to_vsr(), vt4->to_vsr()); // vt3 = {e, f, g, h}
+  vadduwm (d,   vt0, vt1);         // d = {a+hptr[0], b+hptr[1], c+hptr[2], d+hptr[3]}
+  vadduwm (h,   vt5, vt3);         // h = {e+hptr[4], f+hptr[5], g+hptr[6], h+hptr[7]}
+
+  // Save hptr back, works for any alignment
+  stxvd2x (d->to_vsr(), hptr);
+  stxvd2x (h->to_vsr(), of16, hptr);
+#endif
+}
+
+static const uint32_t sha256_round_table[64] __attribute((aligned(16))) = {
+  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
+};
+static const uint32_t *sha256_round_consts = sha256_round_table;
+
+//   R3_ARG1   - byte[]  Input string with padding but in Big Endian
+//   R4_ARG2   - int[]   SHA.state (at first, the root of primes)
+//   R5_ARG3   - int     offset
+//   R6_ARG4   - int     limit
+//
+//   Internal Register usage:
+//   R7        - k
+//   R8        - tmp | j | of16
+//   R9        - of32
+//   VR0-VR8   - ch, maj, bsa, bse, vt0-vt3 | vt0-vt5, vaux/vRb
+//   VR9-VR16  - a-h
+//   VR17-VR20 - w0-w3
+//   VR21-VR23 - vRb | vaux0-vaux2
+//   VR24-VR27 - kpw0-kpw3
+void MacroAssembler::sha256(bool multi_block) {
+  static const ssize_t buf_size = 64;
+  static const uint8_t w_size = sizeof(sha256_round_table)/sizeof(uint32_t);
+#ifdef AIX
+  // malloc provides 16 byte alignment
+  if (((uintptr_t)sha256_round_consts & 0xF) != 0) {
+    uint32_t *new_round_consts = (uint32_t*)malloc(sizeof(sha256_round_table));
+    guarantee(new_round_consts, "oom");
+    memcpy(new_round_consts, sha256_round_consts, sizeof(sha256_round_table));
+    sha256_round_consts = (const uint32_t*)new_round_consts;
+  }
+#endif
+
+  Register buf_in = R3_ARG1;
+  Register state  = R4_ARG2;
+  Register ofs    = R5_ARG3;
+  Register limit  = R6_ARG4;
+
+  Label sha_loop, core_loop;
+
+  // Save non-volatile vector registers in the red zone
+  static const VectorRegister nv[] = {
+    VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27/*, VR28, VR29, VR30, VR31*/
+  };
+  static const uint8_t nv_size = sizeof(nv) / sizeof (VectorRegister);
+
+  for (int c = 0; c < nv_size; c++) {
+    Register tmp = R8;
+    li  (tmp, (c - (nv_size)) * 16);
+    stvx(nv[c], tmp, R1);
+  }
+
+  // Load hash state to registers
+  VectorRegister a = VR9;
+  VectorRegister b = VR10;
+  VectorRegister c = VR11;
+  VectorRegister d = VR12;
+  VectorRegister e = VR13;
+  VectorRegister f = VR14;
+  VectorRegister g = VR15;
+  VectorRegister h = VR16;
+  static const VectorRegister hs[] = {a, b, c, d, e, f, g, h};
+  static const int total_hs = sizeof(hs)/sizeof(VectorRegister);
+  // counter for cycling through hs vector to avoid register moves between iterations
+  int h_cnt = 0;
+
+  // Load a-h registers from the memory pointed by state
+#if defined(VM_LITTLE_ENDIAN)
+  sha256_load_h_vec(a, e, state);
+#else
+  sha256_load_h_vec(d, h, state);
+#endif
+
+  // keep k loaded also during MultiBlock loops
+  Register k = R7;
+  assert(((uintptr_t)sha256_round_consts & 0xF) == 0, "k alignment");
+  load_const_optimized(k, (address)sha256_round_consts, R0);
+
+  // Avoiding redundant loads
+  if (multi_block) {
+    align(OptoLoopAlignment);
+  }
+  bind(sha_loop);
+#if defined(VM_LITTLE_ENDIAN)
+  sha256_deque(a, b, c, d);
+  sha256_deque(e, f, g, h);
+#else
+  sha256_deque(d, c, b, a);
+  sha256_deque(h, g, f, e);
+#endif
+
+  // Load 16 elements from w out of the loop.
+  // Order of the int values is Endianess specific.
+  VectorRegister w0 = VR17;
+  VectorRegister w1 = VR18;
+  VectorRegister w2 = VR19;
+  VectorRegister w3 = VR20;
+  static const VectorRegister ws[] = {w0, w1, w2, w3};
+  static const int total_ws = sizeof(ws)/sizeof(VectorRegister);
+
+  VectorRegister kpw0 = VR24;
+  VectorRegister kpw1 = VR25;
+  VectorRegister kpw2 = VR26;
+  VectorRegister kpw3 = VR27;
+  static const VectorRegister kpws[] = {kpw0, kpw1, kpw2, kpw3};
+  static const int total_kpws = sizeof(kpws)/sizeof(VectorRegister);
+
+  sha256_load_w_plus_k_vec(buf_in, ws, total_ws, k, kpws, total_kpws);
+
+  // Cycle through the first 16 elements
+  assert(total_ws == total_kpws, "Redesign the loop below");
+  for (int n = 0; n < total_ws; n++) {
+    VectorRegister vaux0 = VR21;
+    VectorRegister vaux1 = VR22;
+    VectorRegister vaux2 = VR23;
+
+    sha256_deque(kpws[n], vaux0, vaux1, vaux2);
+
+#if defined(VM_LITTLE_ENDIAN)
+    sha256_round(hs, total_hs, h_cnt, kpws[n]);
+    sha256_round(hs, total_hs, h_cnt, vaux0);
+    sha256_round(hs, total_hs, h_cnt, vaux1);
+    sha256_round(hs, total_hs, h_cnt, vaux2);
+#else
+    sha256_round(hs, total_hs, h_cnt, vaux2);
+    sha256_round(hs, total_hs, h_cnt, vaux1);
+    sha256_round(hs, total_hs, h_cnt, vaux0);
+    sha256_round(hs, total_hs, h_cnt, kpws[n]);
+#endif
+  }
+
+  Register tmp = R8;
+  // loop the 16th to the 64th iteration by 8 steps
+  li   (tmp, (w_size - 16) / total_hs);
+  mtctr(tmp);
+
+  // j will be aligned to 4 for loading words.
+  // Whenever read, advance the pointer (e.g: when j is used in a function)
+  Register j = R8;
+  li   (j, 16*4);
+
+  align(OptoLoopAlignment);
+  bind(core_loop);
+
+  // due to VectorRegister rotate, always iterate in multiples of total_hs
+  for (int n = 0; n < total_hs/4; n++) {
+    sha256_calc_4w(w0, w1, w2, w3, kpw0, kpw1, kpw2, kpw3, j, k);
+    sha256_round(hs, total_hs, h_cnt, kpw0);
+    sha256_round(hs, total_hs, h_cnt, kpw1);
+    sha256_round(hs, total_hs, h_cnt, kpw2);
+    sha256_round(hs, total_hs, h_cnt, kpw3);
+  }
+
+  bdnz   (core_loop);
+
+  // Update hash state
+  sha256_update_sha_state(a, b, c, d, e, f, g, h, state);
+
+  if (multi_block) {
+    addi(buf_in, buf_in, buf_size);
+    addi(ofs, ofs, buf_size);
+    cmplw(CCR0, ofs, limit);
+    ble(CCR0, sha_loop);
+
+    // return ofs
+    mr(R3_RET, ofs);
+  }
+
+  // Restore non-volatile registers
+  for (int c = 0; c < nv_size; c++) {
+    Register tmp = R8;
+    li  (tmp, (c - (nv_size)) * 16);
+    lvx(nv[c], tmp, R1);
+  }
+}
+
+
+/**********************************************************************
+ * SHA 512
+ *********************************************************************/
+
+void MacroAssembler::sha512_load_w_vec(const Register buf_in,
+                                       const VectorRegister* ws,
+                                       const int total_ws) {
+  Register tmp       = R8;
+  VectorRegister vRb = VR8;
+  VectorRegister aux = VR9;
+  Label is_aligned, after_alignment;
+
+  andi_  (tmp, buf_in, 0xF);
+  beq    (CCR0, is_aligned); // address ends with 0x0, not 0x8
+
+  // deal with unaligned addresses
+  lvx    (ws[0], buf_in);
+  load_perm(vRb, buf_in);
+
+  for (int n = 1; n < total_ws; n++) {
+    VectorRegister w_cur = ws[n];
+    VectorRegister w_prev = ws[n-1];
+    addi (tmp, buf_in, n * 16);
+    lvx  (w_cur, tmp);
+    vec_perm(w_prev, w_cur, vRb);
+  }
+  addi   (tmp, buf_in, total_ws * 16);
+  lvx    (aux, tmp);
+  vec_perm(ws[total_ws-1], aux, vRb);
+  b      (after_alignment);
+
+  bind(is_aligned);
+  lvx  (ws[0], buf_in);
+  for (int n = 1; n < total_ws; n++) {
+    VectorRegister w = ws[n];
+    addi (tmp, buf_in, n * 16);
+    lvx  (w, tmp);
+  }
+
+  bind(after_alignment);
+}
+
+// Update hash state
+void MacroAssembler::sha512_update_sha_state(const Register state,
+                                             const VectorRegister* hs,
+                                             const int total_hs) {
+
+#if defined(VM_LITTLE_ENDIAN)
+  int start_idx = 0;
+#else
+  int start_idx = 1;
+#endif
+
+  // load initial hash from the memory pointed by state
+  VectorRegister ini_a = VR10;
+  VectorRegister ini_c = VR12;
+  VectorRegister ini_e = VR14;
+  VectorRegister ini_g = VR16;
+  static const VectorRegister inis[] = {ini_a, ini_c, ini_e, ini_g};
+  static const int total_inis = sizeof(inis)/sizeof(VectorRegister);
+
+  Label state_save_aligned, after_state_save_aligned;
+
+  Register addr      = R7;
+  Register tmp       = R8;
+  VectorRegister vRb = VR8;
+  VectorRegister aux = VR9;
+
+  andi_(tmp, state, 0xf);
+  beq(CCR0, state_save_aligned);
+  // deal with unaligned addresses
+
+  {
+    VectorRegister a = hs[0];
+    VectorRegister b_ = hs[1];
+    VectorRegister c = hs[2];
+    VectorRegister d = hs[3];
+    VectorRegister e = hs[4];
+    VectorRegister f = hs[5];
+    VectorRegister g = hs[6];
+    VectorRegister h = hs[7];
+    load_perm(vRb, state);
+    lvx    (ini_a, state);
+    addi   (addr, state, 16);
+
+    lvx    (ini_c, addr);
+    addi   (addr, state, 32);
+    vec_perm(ini_a, ini_c, vRb);
+
+    lvx    (ini_e, addr);
+    addi   (addr, state, 48);
+    vec_perm(ini_c, ini_e, vRb);
+
+    lvx    (ini_g, addr);
+    addi   (addr, state, 64);
+    vec_perm(ini_e, ini_g, vRb);
+
+    lvx    (aux, addr);
+    vec_perm(ini_g, aux, vRb);
+
+#if defined(VM_LITTLE_ENDIAN)
+    xxmrgld(a->to_vsr(), b_->to_vsr(), a->to_vsr());
+    xxmrgld(c->to_vsr(), d->to_vsr(), c->to_vsr());
+    xxmrgld(e->to_vsr(), f->to_vsr(), e->to_vsr());
+    xxmrgld(g->to_vsr(), h->to_vsr(), g->to_vsr());
+#else
+    xxmrgld(b_->to_vsr(), a->to_vsr(), b_->to_vsr());
+    xxmrgld(d->to_vsr(), c->to_vsr(), d->to_vsr());
+    xxmrgld(f->to_vsr(), e->to_vsr(), f->to_vsr());
+    xxmrgld(h->to_vsr(), g->to_vsr(), h->to_vsr());
+#endif
+
+    for (int n = start_idx; n < total_hs; n += 2) {
+      VectorRegister h_cur = hs[n];
+      VectorRegister ini_cur = inis[n/2];
+
+      vaddudm(h_cur, ini_cur, h_cur);
+    }
+
+    for (int n = start_idx; n < total_hs; n += 2) {
+      VectorRegister h_cur = hs[n];
+
+      mfvrd  (tmp, h_cur);
+#if defined(VM_LITTLE_ENDIAN)
+      std    (tmp, 8*n + 8, state);
+#else
+      std    (tmp, 8*n - 8, state);
+#endif
+      vsldoi (aux, h_cur, h_cur, 8);
+      mfvrd  (tmp, aux);
+      std    (tmp, 8*n + 0, state);
+    }
+
+    b      (after_state_save_aligned);
+  }
+
+  bind(state_save_aligned);
+  {
+    for (int n = 0; n < total_hs; n += 2) {
+#if defined(VM_LITTLE_ENDIAN)
+      VectorRegister h_cur = hs[n];
+      VectorRegister h_next = hs[n+1];
+#else
+      VectorRegister h_cur = hs[n+1];
+      VectorRegister h_next = hs[n];
+#endif
+      VectorRegister ini_cur = inis[n/2];
+
+      if (n/2 == 0) {
+        lvx(ini_cur, state);
+      } else {
+        addi(addr, state, (n/2) * 16);
+        lvx(ini_cur, addr);
+      }
+      xxmrgld(h_cur->to_vsr(), h_next->to_vsr(), h_cur->to_vsr());
+    }
+
+    for (int n = start_idx; n < total_hs; n += 2) {
+      VectorRegister h_cur = hs[n];
+      VectorRegister ini_cur = inis[n/2];
+
+      vaddudm(h_cur, ini_cur, h_cur);
+    }
+
+    for (int n = start_idx; n < total_hs; n += 2) {
+      VectorRegister h_cur = hs[n];
+
+      if (n/2 == 0) {
+        stvx(h_cur, state);
+      } else {
+        addi(addr, state, (n/2) * 16);
+        stvx(h_cur, addr);
+      }
+    }
+  }
+
+  bind(after_state_save_aligned);
+}
+
+// Use h_cnt to cycle through hs elements but also increment it at the end
+void MacroAssembler::sha512_round(const VectorRegister* hs,
+                                  const int total_hs, int& h_cnt,
+                                  const VectorRegister kpw) {
+
+  // convenience registers: cycle from 0-7 downwards
+  const VectorRegister a = hs[(total_hs + 0 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister b = hs[(total_hs + 1 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister c = hs[(total_hs + 2 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister d = hs[(total_hs + 3 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister e = hs[(total_hs + 4 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister f = hs[(total_hs + 5 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister g = hs[(total_hs + 6 - (h_cnt % total_hs)) % total_hs];
+  const VectorRegister h = hs[(total_hs + 7 - (h_cnt % total_hs)) % total_hs];
+  // temporaries
+  const VectorRegister Ch   = VR20;
+  const VectorRegister Maj  = VR21;
+  const VectorRegister bsa  = VR22;
+  const VectorRegister bse  = VR23;
+  const VectorRegister tmp1 = VR24;
+  const VectorRegister tmp2 = VR25;
+
+  vsel      (Ch,   g,    f,   e);
+  vxor      (Maj,  a,    b);
+  vshasigmad(bse,  e,    1,   0xf);
+  vaddudm   (tmp2, Ch,   kpw);
+  vaddudm   (tmp1, h,    bse);
+  vsel      (Maj,  b,    c,   Maj);
+  vaddudm   (tmp1, tmp1, tmp2);
+  vshasigmad(bsa,  a,    1,   0);
+  vaddudm   (tmp2, bsa,  Maj);
+  vaddudm   (d,    d,    tmp1);
+  vaddudm   (h,    tmp1, tmp2);
+
+  // advance vector pointer to the next iteration
+  h_cnt++;
+}
+
+void MacroAssembler::sha512_calc_2w(const VectorRegister w0,
+                                    const VectorRegister w1,
+                                    const VectorRegister w2,
+                                    const VectorRegister w3,
+                                    const VectorRegister w4,
+                                    const VectorRegister w5,
+                                    const VectorRegister w6,
+                                    const VectorRegister w7,
+                                    const VectorRegister kpw0,
+                                    const VectorRegister kpw1,
+                                    const Register j,
+                                    const VectorRegister vRb,
+                                    const Register k) {
+  // Temporaries
+  const VectorRegister VR_a = VR20;
+  const VectorRegister VR_b = VR21;
+  const VectorRegister VR_c = VR22;
+  const VectorRegister VR_d = VR23;
+
+  // load to k[j]
+  lvx        (VR_a, j,    k);
+  // advance j
+  addi       (j,    j,    16); // 16 bytes were read
+
+#if defined(VM_LITTLE_ENDIAN)
+  // v6 = w[j-15], w[j-14]
+  vperm      (VR_b, w1,   w0,  vRb);
+  // v12 = w[j-7], w[j-6]
+  vperm      (VR_c, w5,   w4,  vRb);
+#else
+  // v6 = w[j-15], w[j-14]
+  vperm      (VR_b, w0,   w1,  vRb);
+  // v12 = w[j-7], w[j-6]
+  vperm      (VR_c, w4,   w5,  vRb);
+#endif
+
+  // v6 = s0(w[j-15]) , s0(w[j-14])
+  vshasigmad (VR_b, VR_b,    0,   0);
+  // v5 = s1(w[j-2]) , s1(w[j-1])
+  vshasigmad (VR_d, w7,      0,   0xf);
+  // v6 = s0(w[j-15]) + w[j-7] , s0(w[j-14]) + w[j-6]
+  vaddudm    (VR_b, VR_b, VR_c);
+  // v8 = s1(w[j-2]) + w[j-16] , s1(w[j-1]) + w[j-15]
+  vaddudm    (VR_d, VR_d, w0);
+  // v9 = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+  //      s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+  vaddudm    (VR_c, VR_d, VR_b);
+  // Updating w0 to w7 to hold the new previous 16 values from w.
+  vmr        (w0,   w1);
+  vmr        (w1,   w2);
+  vmr        (w2,   w3);
+  vmr        (w3,   w4);
+  vmr        (w4,   w5);
+  vmr        (w5,   w6);
+  vmr        (w6,   w7);
+  vmr        (w7,   VR_c);
+
+#if defined(VM_LITTLE_ENDIAN)
+  // store k + w to kpw0 (2 values at once)
+  vaddudm    (kpw0, VR_c, VR_a);
+  // kpw1 holds (k + w)[1]
+  vsldoi     (kpw1, kpw0, kpw0, 8);
+#else
+  // store k + w to kpw0 (2 values at once)
+  vaddudm    (kpw1, VR_c, VR_a);
+  // kpw1 holds (k + w)[1]
+  vsldoi     (kpw0, kpw1, kpw1, 8);
+#endif
+}
+
+void MacroAssembler::sha512_load_h_vec(const Register state,
+                                       const VectorRegister* hs,
+                                       const int total_hs) {
+#if defined(VM_LITTLE_ENDIAN)
+  VectorRegister a   = hs[0];
+  VectorRegister g   = hs[6];
+  int start_idx = 0;
+#else
+  VectorRegister a   = hs[1];
+  VectorRegister g   = hs[7];
+  int start_idx = 1;
+#endif
+
+  Register addr      = R7;
+  VectorRegister vRb = VR8;
+  Register tmp       = R8;
+  Label state_aligned, after_state_aligned;
+
+  andi_(tmp, state, 0xf);
+  beq(CCR0, state_aligned);
+
+  // deal with unaligned addresses
+  VectorRegister aux = VR9;
+
+  lvx(hs[start_idx], state);
+  load_perm(vRb, state);
+
+  for (int n = start_idx + 2; n < total_hs; n += 2) {
+    VectorRegister h_cur   = hs[n];
+    VectorRegister h_prev2 = hs[n - 2];
+    addi(addr, state, (n/2) * 16);
+    lvx(h_cur, addr);
+    vec_perm(h_prev2, h_cur, vRb);
+  }
+  addi(addr, state, (total_hs/2) * 16);
+  lvx    (aux, addr);
+  vec_perm(hs[total_hs - 2 + start_idx], aux, vRb);
+  b      (after_state_aligned);
+
+  bind(state_aligned);
+
+  // deal with aligned addresses
+  lvx(hs[start_idx], state);
+
+  for (int n = start_idx + 2; n < total_hs; n += 2) {
+    VectorRegister h_cur = hs[n];
+    addi(addr, state, (n/2) * 16);
+    lvx(h_cur, addr);
+  }
+
+  bind(after_state_aligned);
+}
+
+static const uint64_t sha512_round_table[80] __attribute((aligned(16))) = {
+  0x428a2f98d728ae22, 0x7137449123ef65cd,
+  0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+  0x3956c25bf348b538, 0x59f111f1b605d019,
+  0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+  0xd807aa98a3030242, 0x12835b0145706fbe,
+  0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+  0x72be5d74f27b896f, 0x80deb1fe3b1696b1,
+  0x9bdc06a725c71235, 0xc19bf174cf692694,
+  0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+  0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+  0x2de92c6f592b0275, 0x4a7484aa6ea6e483,
+  0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+  0x983e5152ee66dfab, 0xa831c66d2db43210,
+  0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+  0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+  0x06ca6351e003826f, 0x142929670a0e6e70,
+  0x27b70a8546d22ffc, 0x2e1b21385c26c926,
+  0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+  0x650a73548baf63de, 0x766a0abb3c77b2a8,
+  0x81c2c92e47edaee6, 0x92722c851482353b,
+  0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+  0xc24b8b70d0f89791, 0xc76c51a30654be30,
+  0xd192e819d6ef5218, 0xd69906245565a910,
+  0xf40e35855771202a, 0x106aa07032bbd1b8,
+  0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
+  0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+  0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+  0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+  0x748f82ee5defb2fc, 0x78a5636f43172f60,
+  0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+  0x90befffa23631e28, 0xa4506cebde82bde9,
+  0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+  0xca273eceea26619c, 0xd186b8c721c0c207,
+  0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+  0x06f067aa72176fba, 0x0a637dc5a2c898a6,
+  0x113f9804bef90dae, 0x1b710b35131c471b,
+  0x28db77f523047d84, 0x32caab7b40c72493,
+  0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+  0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+  0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+};
+static const uint64_t *sha512_round_consts = sha512_round_table;
+
+//   R3_ARG1   - byte[]  Input string with padding but in Big Endian
+//   R4_ARG2   - int[]   SHA.state (at first, the root of primes)
+//   R5_ARG3   - int     offset
+//   R6_ARG4   - int     limit
+//
+//   Internal Register usage:
+//   R7 R8 R9  - volatile temporaries
+//   VR0-VR7   - a-h
+//   VR8       - vRb
+//   VR9       - aux (highly volatile, use with care)
+//   VR10-VR17 - w0-w7 | ini_a-ini_h
+//   VR18      - vsp16 | kplusw0
+//   VR19      - vsp32 | kplusw1
+//   VR20-VR25 - sha512_calc_2w and sha512_round temporaries
+void MacroAssembler::sha512(bool multi_block) {
+  static const ssize_t buf_size = 128;
+  static const uint8_t w_size = sizeof(sha512_round_table)/sizeof(uint64_t);
+#ifdef AIX
+  // malloc provides 16 byte alignment
+  if (((uintptr_t)sha512_round_consts & 0xF) != 0) {
+    uint64_t *new_round_consts = (uint64_t*)malloc(sizeof(sha512_round_table));
+    guarantee(new_round_consts, "oom");
+    memcpy(new_round_consts, sha512_round_consts, sizeof(sha512_round_table));
+    sha512_round_consts = (const uint64_t*)new_round_consts;
+  }
+#endif
+
+  Register buf_in = R3_ARG1;
+  Register state  = R4_ARG2;
+  Register ofs    = R5_ARG3;
+  Register limit  = R6_ARG4;
+
+  Label sha_loop, core_loop;
+
+  // Save non-volatile vector registers in the red zone
+  static const VectorRegister nv[] = {
+    VR20, VR21, VR22, VR23, VR24, VR25/*, VR26, VR27, VR28, VR29, VR30, VR31*/
+  };
+  static const uint8_t nv_size = sizeof(nv) / sizeof (VectorRegister);
+
+  for (int c = 0; c < nv_size; c++) {
+    Register idx = R7;
+    li  (idx, (c - (nv_size)) * 16);
+    stvx(nv[c], idx, R1);
+  }
+
+  // Load hash state to registers
+  VectorRegister a = VR0;
+  VectorRegister b = VR1;
+  VectorRegister c = VR2;
+  VectorRegister d = VR3;
+  VectorRegister e = VR4;
+  VectorRegister f = VR5;
+  VectorRegister g = VR6;
+  VectorRegister h = VR7;
+  static const VectorRegister hs[] = {a, b, c, d, e, f, g, h};
+  static const int total_hs = sizeof(hs)/sizeof(VectorRegister);
+  // counter for cycling through hs vector to avoid register moves between iterations
+  int h_cnt = 0;
+
+  // Load a-h registers from the memory pointed by state
+  sha512_load_h_vec(state, hs, total_hs);
+
+  Register k = R9;
+  assert(((uintptr_t)sha512_round_consts & 0xF) == 0, "k alignment");
+  load_const_optimized(k, (address)sha512_round_consts, R0);
+
+  if (multi_block) {
+    align(OptoLoopAlignment);
+  }
+  bind(sha_loop);
+
+  for (int n = 0; n < total_hs; n += 2) {
+#if defined(VM_LITTLE_ENDIAN)
+    VectorRegister h_cur = hs[n];
+    VectorRegister h_next = hs[n + 1];
+#else
+    VectorRegister h_cur = hs[n + 1];
+    VectorRegister h_next = hs[n];
+#endif
+    vsldoi (h_next, h_cur, h_cur, 8);
+  }
+
+  // Load 16 elements from w out of the loop.
+  // Order of the long values is Endianess specific.
+  VectorRegister w0 = VR10;
+  VectorRegister w1 = VR11;
+  VectorRegister w2 = VR12;
+  VectorRegister w3 = VR13;
+  VectorRegister w4 = VR14;
+  VectorRegister w5 = VR15;
+  VectorRegister w6 = VR16;
+  VectorRegister w7 = VR17;
+  static const VectorRegister ws[] = {w0, w1, w2, w3, w4, w5, w6, w7};
+  static const int total_ws = sizeof(ws)/sizeof(VectorRegister);
+
+  // Load 16 w into vectors and setup vsl for vperm
+  sha512_load_w_vec(buf_in, ws, total_ws);
+
+#if defined(VM_LITTLE_ENDIAN)
+  VectorRegister vsp16 = VR18;
+  VectorRegister vsp32 = VR19;
+  VectorRegister shiftarg = VR9;
+
+  vspltisw(vsp16,    8);
+  vspltisw(shiftarg, 1);
+  vsl     (vsp16,    vsp16, shiftarg);
+  vsl     (vsp32,    vsp16, shiftarg);
+
+  VectorRegister vsp8 = VR9;
+  vspltish(vsp8,     8);
+
+  // Convert input from Big Endian to Little Endian
+  for (int c = 0; c < total_ws; c++) {
+    VectorRegister w = ws[c];
+    vrlh  (w, w, vsp8);
+  }
+  for (int c = 0; c < total_ws; c++) {
+    VectorRegister w = ws[c];
+    vrlw  (w, w, vsp16);
+  }
+  for (int c = 0; c < total_ws; c++) {
+    VectorRegister w = ws[c];
+    vrld  (w, w, vsp32);
+  }
+#endif
+
+  Register Rb        = R10;
+  VectorRegister vRb = VR8;
+  li      (Rb, 8);
+  load_perm(vRb, Rb);
+
+  VectorRegister kplusw0 = VR18;
+  VectorRegister kplusw1 = VR19;
+
+  Register addr      = R7;
+
+  for (int n = 0; n < total_ws; n++) {
+    VectorRegister w = ws[n];
+
+    if (n == 0) {
+      lvx  (kplusw0, k);
+    } else {
+      addi (addr, k, n * 16);
+      lvx  (kplusw0, addr);
+    }
+#if defined(VM_LITTLE_ENDIAN)
+    vaddudm(kplusw0, kplusw0, w);
+    vsldoi (kplusw1, kplusw0, kplusw0, 8);
+#else
+    vaddudm(kplusw1, kplusw0, w);
+    vsldoi (kplusw0, kplusw1, kplusw1, 8);
+#endif
+
+    sha512_round(hs, total_hs, h_cnt, kplusw0);
+    sha512_round(hs, total_hs, h_cnt, kplusw1);
+  }
+
+  Register tmp       = R8;
+  li    (tmp, (w_size-16)/total_hs);
+  mtctr (tmp);
+  // j will be aligned to 4 for loading words.
+  // Whenever read, advance the pointer (e.g: when j is used in a function)
+  Register j = tmp;
+  li     (j, 8*16);
+
+  align(OptoLoopAlignment);
+  bind(core_loop);
+
+  // due to VectorRegister rotate, always iterate in multiples of total_hs
+  for (int n = 0; n < total_hs/2; n++) {
+    sha512_calc_2w(w0, w1, w2, w3, w4, w5, w6, w7, kplusw0, kplusw1, j, vRb, k);
+    sha512_round(hs, total_hs, h_cnt, kplusw0);
+    sha512_round(hs, total_hs, h_cnt, kplusw1);
+  }
+
+  bdnz   (core_loop);
+
+  sha512_update_sha_state(state, hs, total_hs);
+
+  if (multi_block) {
+    addi(buf_in, buf_in, buf_size);
+    addi(ofs, ofs, buf_size);
+    cmplw(CCR0, ofs, limit);
+    ble(CCR0, sha_loop);
+
+    // return ofs
+    mr(R3_RET, ofs);
+  }
+
+  // Restore non-volatile registers
+  for (int c = 0; c < nv_size; c++) {
+    Register idx = R7;
+    li  (idx, (c - (nv_size)) * 16);
+    lvx(nv[c], idx, R1);
+  }
+}
diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
index 12dd846..12cff00 100644
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
@@ -2652,6 +2652,28 @@
      return start;
   }
 
+  address generate_sha256_implCompress(bool multi_block, const char *name) {
+    assert(UseSHA, "need SHA instructions");
+    StubCodeMark mark(this, "StubRoutines", name);
+    address start = __ function_entry();
+
+    __ sha256 (multi_block);
+
+    __ blr();
+    return start;
+  }
+
+  address generate_sha512_implCompress(bool multi_block, const char *name) {
+    assert(UseSHA, "need SHA instructions");
+    StubCodeMark mark(this, "StubRoutines", name);
+    address start = __ function_entry();
+
+    __ sha512 (multi_block);
+
+    __ blr();
+    return start;
+  }
+
   void generate_arraycopy_stubs() {
     // Note: the disjoint stubs must be generated first, some of
     // the conjoint stubs use them.
@@ -2881,6 +2903,15 @@
       StubRoutines::_montgomerySquare
         = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square);
     }
+
+    if (UseSHA256Intrinsics) {
+      StubRoutines::_sha256_implCompress   = generate_sha256_implCompress(false, "sha256_implCompress");
+      StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true,  "sha256_implCompressMB");
+    }
+    if (UseSHA512Intrinsics) {
+      StubRoutines::_sha512_implCompress   = generate_sha512_implCompress(false, "sha512_implCompress");
+      StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB");
+    }
   }
 
  public:
diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
index 3655c1f..cf9ebc4 100644
--- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
+++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
@@ -34,7 +34,7 @@
 
 enum platform_dependent_constants {
   code_size1 = 20000,          // simply increase if too small (assembler will crash if too small)
-  code_size2 = 20000           // simply increase if too small (assembler will crash if too small)
+  code_size2 = 22000           // simply increase if too small (assembler will crash if too small)
 };
 
 // CRC32 Intrinsics.
diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
index 6761c02..e7fad48 100644
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
@@ -110,7 +110,7 @@
   // Create and print feature-string.
   char buf[(num_features+1) * 16]; // Max 16 chars per feature.
   jio_snprintf(buf, sizeof(buf),
-               "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s",
+               "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                (has_fsqrt()   ? " fsqrt"   : ""),
                (has_isel()    ? " isel"    : ""),
                (has_lxarxeh() ? " lxarxeh" : ""),
@@ -124,7 +124,8 @@
                (has_vcipher() ? " aes"     : ""),
                (has_vpmsumb() ? " vpmsumb" : ""),
                (has_mfdscr()  ? " mfdscr"  : ""),
-               (has_vsx()     ? " vsx"     : "")
+               (has_vsx()     ? " vsx"     : ""),
+               (has_vshasig() ? " sha"     : "")
                // Make sure number of %s matches num_features!
               );
   _features_str = strdup(buf);
@@ -206,17 +207,43 @@
   }
 #endif
 
-  if (UseSHA) {
-    warning("SHA instructions are not available on this CPU");
+  if (has_vshasig()) {
+    if (FLAG_IS_DEFAULT(UseSHA)) {
+      UseSHA = true;
+    }
+  } else if (UseSHA) {
+    if (!FLAG_IS_DEFAULT(UseSHA))
+      warning("SHA instructions are not available on this CPU");
     FLAG_SET_DEFAULT(UseSHA, false);
   }
-  if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
-    warning("SHA intrinsics are not available on this CPU");
+
+  if (UseSHA1Intrinsics) {
+    warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
     FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+  }
+
+  if (UseSHA && has_vshasig()) {
+    if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
+      FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
+    }
+  } else if (UseSHA256Intrinsics) {
+    warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
     FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+  }
+
+  if (UseSHA && has_vshasig()) {
+    if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
+      FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
+    }
+  } else if (UseSHA512Intrinsics) {
+    warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
   }
 
+  if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
+    FLAG_SET_DEFAULT(UseSHA, false);
+  }
+
   if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
     UseMontgomeryMultiplyIntrinsic = true;
   }
@@ -503,6 +530,7 @@
   a->vpmsumb(VR0, VR1, VR2);                   // code[12] -> vpmsumb
   a->mfdscr(R0);                               // code[13] -> mfdscr
   a->lxvd2x(VSR0, R3_ARG1);                    // code[14] -> vsx
+  a->vshasigmaw(VR0, VR1, 1, 0xF);             // code[15] -> vshasig
   a->blr();
 
   // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@@ -551,6 +579,7 @@
   if (code[feature_cntr++]) features |= vpmsumb_m;
   if (code[feature_cntr++]) features |= mfdscr_m;
   if (code[feature_cntr++]) features |= vsx_m;
+  if (code[feature_cntr++]) features |= vshasig_m;
 
   // Print the detection code.
   if (PrintAssembly) {
diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp
index 6245e1c..86243a1 100644
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp
@@ -47,6 +47,7 @@
     vpmsumb,
     mfdscr,
     vsx,
+    vshasig,
     num_features // last entry to count features
   };
   enum Feature_Flag_Set {
@@ -63,6 +64,7 @@
     dcba_m                = (1 << dcba   ),
     lqarx_m               = (1 << lqarx  ),
     vcipher_m             = (1 << vcipher),
+    vshasig_m             = (1 << vshasig),
     vpmsumb_m             = (1 << vpmsumb),
     mfdscr_m              = (1 << mfdscr ),
     vsx_m                 = (1 << vsx    ),
@@ -99,6 +101,7 @@
   static bool has_vpmsumb() { return (_features & vpmsumb_m) != 0; }
   static bool has_mfdscr()  { return (_features & mfdscr_m) != 0; }
   static bool has_vsx()     { return (_features & vsx_m) != 0; }
+  static bool has_vshasig() { return (_features & vshasig_m) != 0; }
 
   static const char* cpu_features() { return _features_str; }
 
diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad
index e20b02d..e36604f 100644
--- a/hotspot/src/cpu/x86/vm/x86_64.ad
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad
@@ -3740,6 +3740,23 @@
   %}
 %}
 
+// Indirect Memory Plus Positive Index Register Plus Offset Operand
+operand indPosIndexOffset(any_RegP reg, immL32 off, rRegI idx)
+%{
+  constraint(ALLOC_IN_RC(ptr_reg));
+  predicate(n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
+  match(AddP (AddP reg (ConvI2L idx)) off);
+
+  op_cost(10);
+  format %{"[$reg + $off + $idx]" %}
+  interface(MEMORY_INTER) %{
+    base($reg);
+    index($idx);
+    scale(0x0);
+    disp($off);
+  %}
+%}
+
 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
 operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale)
 %{
@@ -3891,6 +3908,23 @@
   %}
 %}
 
+// Indirect Memory Times Plus Positive Index Register Plus Offset Operand
+operand indPosIndexOffsetNarrow(rRegN reg, immL32 off, rRegI idx)
+%{
+  constraint(ALLOC_IN_RC(ptr_reg));
+  predicate(Universe::narrow_oop_shift() == 0 && n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
+  match(AddP (AddP (DecodeN reg) (ConvI2L idx)) off);
+
+  op_cost(10);
+  format %{"[$reg + $off + $idx]" %}
+  interface(MEMORY_INTER) %{
+    base($reg);
+    index($idx);
+    scale(0x0);
+    disp($off);
+  %}
+%}
+
 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
 operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 scale)
 %{
@@ -4082,11 +4116,11 @@
 // case of this is memory operands.
 
 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
-               indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset,
+               indIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
                indCompressedOopOffset,
                indirectNarrow, indOffset8Narrow, indOffset32Narrow,
                indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
-               indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow);
+               indIndexScaleOffsetNarrow, indPosIndexOffsetNarrow, indPosIndexScaleOffsetNarrow);
 
 //----------PIPELINE-----------------------------------------------------------
 // Rules which define the behavior of the target architectures pipeline.
@@ -5120,6 +5154,17 @@
   ins_pipe(ialu_reg_reg_fat);
 %}
 
+instruct leaPPosIdxOff(rRegP dst, indPosIndexOffset mem)
+%{
+  match(Set dst mem);
+
+  ins_cost(110);
+  format %{ "leaq    $dst, $mem\t# ptr posidxoff" %}
+  opcode(0x8D);
+  ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
+  ins_pipe(ialu_reg_reg_fat);
+%}
+
 instruct leaPPosIdxScaleOff(rRegP dst, indPosIndexScaleOffset mem)
 %{
   match(Set dst mem);
@@ -5204,6 +5249,18 @@
   ins_pipe(ialu_reg_reg_fat);
 %}
 
+instruct leaPPosIdxOffNarrow(rRegP dst, indPosIndexOffsetNarrow mem)
+%{
+  predicate(Universe::narrow_oop_shift() == 0);
+  match(Set dst mem);
+
+  ins_cost(110);
+  format %{ "leaq    $dst, $mem\t# ptr posidxoffnarrow" %}
+  opcode(0x8D);
+  ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
+  ins_pipe(ialu_reg_reg_fat);
+%}
+
 instruct leaPPosIdxScaleOffNarrow(rRegP dst, indPosIndexScaleOffsetNarrow mem)
 %{
   predicate(Universe::narrow_oop_shift() == 0);
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index b03ce24..717f692 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -4184,8 +4184,7 @@
 
   /* Scan the directory */
   bool result = true;
-  char buf[sizeof(struct dirent) + MAX_PATH];
-  while (result && (ptr = ::readdir(dir)) != NULL) {
+  while (result && (ptr = readdir(dir)) != NULL) {
     if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
       result = false;
     }
diff --git a/hotspot/src/os/aix/vm/os_aix.inline.hpp b/hotspot/src/os/aix/vm/os_aix.inline.hpp
index a97c94c..421ea34 100644
--- a/hotspot/src/os/aix/vm/os_aix.inline.hpp
+++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp
@@ -92,19 +92,6 @@
 
 inline const int os::default_file_open_flags() { return 0;}
 
-inline DIR* os::opendir(const char* dirname)
-{
-  assert(dirname != NULL, "just checking");
-  return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
-  // according to aix sys/limits, NAME_MAX must be retrieved at runtime. */
-  const long my_NAME_MAX = pathconf(path, _PC_NAME_MAX);
-  return my_NAME_MAX + sizeof(dirent) + 1;
-}
-
 inline jlong os::lseek(int fd, jlong offset, int whence) {
   return (jlong) ::lseek64(fd, offset, whence);
 }
@@ -121,28 +108,6 @@
   return ::ftruncate64(fd, length);
 }
 
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
-  dirent* p;
-  int status;
-  assert(dirp != NULL, "just checking");
-
-  // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
-  // version. Here is the doc for this function:
-  // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
-  if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
-    errno = status;
-    return NULL;
-  } else
-    return p;
-}
-
-inline int os::closedir(DIR *dirp) {
-  assert(dirp != NULL, "argument is NULL");
-  return ::closedir(dirp);
-}
-
 // macros for restartable system calls
 
 #define RESTARTABLE(_cmd, _result) do { \
diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
index 96f8451..80ae9e7 100644
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
@@ -612,9 +612,8 @@
   // to determine the user name for the process id.
   //
   struct dirent* dentry;
-  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
   errno = 0;
-  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+  while ((dentry = os::readdir(tmpdirp)) != NULL) {
 
     // check if the directory entry is a hsperfdata file
     if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -648,9 +647,8 @@
     }
 
     struct dirent* udentry;
-    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
-    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+    while ((udentry = os::readdir(subdirp)) != NULL) {
 
       if (filename_to_pid(udentry->d_name) == vmid) {
         struct stat statbuf;
@@ -694,11 +692,9 @@
       }
     }
     os::closedir(subdirp);
-    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
     FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   }
   os::closedir(tmpdirp);
-  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
 
   return(oldest_user);
 }
@@ -774,10 +770,8 @@
   // loop under these conditions is dependent upon the implementation of
   // opendir/readdir.
   struct dirent* entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
   errno = 0;
-  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+  while ((entry = os::readdir(dirp)) != NULL) {
 
     pid_t pid = filename_to_pid(entry->d_name);
 
@@ -816,7 +810,6 @@
   // Close the directory and reset the current working directory.
   close_directory_secure_cwd(dirp, saved_cwd_fd);
 
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
 // Make the user specific temporary directory. Returns true if
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 99a0399..1c0336e 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -3957,8 +3957,7 @@
 
   /* Scan the directory */
   bool result = true;
-  char buf[sizeof(struct dirent) + MAX_PATH];
-  while (result && (ptr = ::readdir(dir)) != NULL) {
+  while (result && (ptr = readdir(dir)) != NULL) {
     if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
       result = false;
     }
diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
index 10b3994..c35abf4 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
@@ -95,17 +95,6 @@
 
 inline const int os::default_file_open_flags() { return 0;}
 
-inline DIR* os::opendir(const char* dirname)
-{
-  assert(dirname != NULL, "just checking");
-  return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
-  return NAME_MAX + sizeof(dirent) + 1;
-}
-
 inline jlong os::lseek(int fd, jlong offset, int whence) {
   return (jlong) ::lseek(fd, offset, whence);
 }
@@ -122,28 +111,6 @@
   return ::ftruncate(fd, length);
 }
 
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
-  dirent* p;
-  int status;
-  assert(dirp != NULL, "just checking");
-
-  // NOTE: Bsd readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
-  // version. Here is the doc for this function:
-  // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
-  if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
-    errno = status;
-    return NULL;
-  } else
-    return p;
-}
-
-inline int os::closedir(DIR *dirp) {
-  assert(dirp != NULL, "argument is NULL");
-  return ::closedir(dirp);
-}
-
 // macros for restartable system calls
 
 #define RESTARTABLE(_cmd, _result) do { \
diff --git a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
index df4fca6..802d090 100644
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -533,9 +533,8 @@
   // to determine the user name for the process id.
   //
   struct dirent* dentry;
-  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
   errno = 0;
-  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+  while ((dentry = os::readdir(tmpdirp)) != NULL) {
 
     // check if the directory entry is a hsperfdata file
     if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -557,9 +556,8 @@
     }
 
     struct dirent* udentry;
-    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
-    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+    while ((udentry = os::readdir(subdirp)) != NULL) {
 
       if (filename_to_pid(udentry->d_name) == vmid) {
         struct stat statbuf;
@@ -603,11 +601,9 @@
       }
     }
     os::closedir(subdirp);
-    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
     FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   }
   os::closedir(tmpdirp);
-  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
 
   return(oldest_user);
 }
@@ -686,10 +682,8 @@
   // opendir/readdir.
   //
   struct dirent* entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
   errno = 0;
-  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+  while ((entry = os::readdir(dirp)) != NULL) {
 
     pid_t pid = filename_to_pid(entry->d_name);
 
@@ -729,7 +723,6 @@
   // close the directory and reset the current working directory
   close_directory_secure_cwd(dirp, saved_cwd_fd);
 
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
 // make the user specific temporary directory. Returns true if
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index a499e49..03cabfe 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -5501,8 +5501,7 @@
 
   /* Scan the directory */
   bool result = true;
-  char buf[sizeof(struct dirent) + MAX_PATH];
-  while (result && (ptr = ::readdir(dir)) != NULL) {
+  while (result && (ptr = readdir(dir)) != NULL) {
     if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
       result = false;
     }
diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp
index 10d56d8..a23bd56 100644
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp
@@ -87,17 +87,6 @@
 
 inline const int os::default_file_open_flags() { return 0;}
 
-inline DIR* os::opendir(const char* dirname)
-{
-  assert(dirname != NULL, "just checking");
-  return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
-  return NAME_MAX + sizeof(dirent) + 1;
-}
-
 inline jlong os::lseek(int fd, jlong offset, int whence) {
   return (jlong) ::lseek64(fd, offset, whence);
 }
@@ -114,28 +103,6 @@
   return ::ftruncate64(fd, length);
 }
 
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
-  dirent* p;
-  int status;
-  assert(dirp != NULL, "just checking");
-
-  // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
-  // version. Here is the doc for this function:
-  // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
-  if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
-    errno = status;
-    return NULL;
-  } else
-    return p;
-}
-
-inline int os::closedir(DIR *dirp) {
-  assert(dirp != NULL, "argument is NULL");
-  return ::closedir(dirp);
-}
-
 // macros for restartable system calls
 
 #define RESTARTABLE(_cmd, _result) do { \
diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
index 4143f65..8293b71 100644
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
@@ -533,9 +533,8 @@
   // to determine the user name for the process id.
   //
   struct dirent* dentry;
-  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
   errno = 0;
-  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+  while ((dentry = os::readdir(tmpdirp)) != NULL) {
 
     // check if the directory entry is a hsperfdata file
     if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -569,9 +568,8 @@
     }
 
     struct dirent* udentry;
-    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
-    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+    while ((udentry = os::readdir(subdirp)) != NULL) {
 
       if (filename_to_pid(udentry->d_name) == vmid) {
         struct stat statbuf;
@@ -615,11 +613,9 @@
       }
     }
     os::closedir(subdirp);
-    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
     FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   }
   os::closedir(tmpdirp);
-  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
 
   return(oldest_user);
 }
@@ -698,10 +694,8 @@
   // opendir/readdir.
   //
   struct dirent* entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
   errno = 0;
-  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+  while ((entry = os::readdir(dirp)) != NULL) {
 
     pid_t pid = filename_to_pid(entry->d_name);
 
@@ -738,8 +732,6 @@
 
   // close the directory and reset the current working directory
   close_directory_secure_cwd(dirp, saved_cwd_fd);
-
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
 // make the user specific temporary directory. Returns true if
diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp
index 534b192..a43a855 100644
--- a/hotspot/src/os/posix/vm/os_posix.cpp
+++ b/hotspot/src/os/posix/vm/os_posix.cpp
@@ -302,6 +302,21 @@
   return ::fdopen(fd, mode);
 }
 
+DIR* os::opendir(const char* dirname) {
+  assert(dirname != NULL, "just checking");
+  return ::opendir(dirname);
+}
+
+struct dirent* os::readdir(DIR* dirp) {
+  assert(dirp != NULL, "just checking");
+  return ::readdir(dirp);
+}
+
+int os::closedir(DIR *dirp) {
+  assert(dirp != NULL, "just checking");
+  return ::closedir(dirp);
+}
+
 // Builds a platform dependent Agent_OnLoad_<lib_name> function name
 // which is used to find statically linked in agents.
 // Parameters:
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index 014a6d3..6956f63 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -5163,9 +5163,7 @@
 
   /* Scan the directory */
   bool result = true;
-  char buf[sizeof(struct dirent) + MAX_PATH];
-  struct dirent *dbuf = (struct dirent *) buf;
-  while (result && (ptr = readdir(dir, dbuf)) != NULL) {
+  while (result && (ptr = readdir(dir)) != NULL) {
     if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
       result = false;
     }
diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
index 921fcf7..8e095ab 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
@@ -71,37 +71,6 @@
 }
 inline void os::dll_unload(void *lib) { ::dlclose(lib); }
 
-inline DIR* os::opendir(const char* dirname) {
-  assert(dirname != NULL, "just checking");
-  return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path) {
-  int size = pathconf(path, _PC_NAME_MAX);
-  return (size < 0 ? MAXPATHLEN : size) + sizeof(dirent) + 1;
-}
-
-inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) {
-  assert(dirp != NULL, "just checking");
-#if defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
-  dirent* p;
-  int status;
-
-  if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
-    errno = status;
-    return NULL;
-  } else
-    return p;
-#else  // defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
-  return ::readdir_r(dirp, dbuf);
-#endif // defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
-}
-
-inline int os::closedir(DIR *dirp) {
-  assert(dirp != NULL, "argument is NULL");
-  return ::closedir(dirp);
-}
-
 //////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
index 7c6f616..8af1b24 100644
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
@@ -524,9 +524,8 @@
   // to determine the user name for the process id.
   //
   struct dirent* dentry;
-  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
   errno = 0;
-  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+  while ((dentry = os::readdir(tmpdirp)) != NULL) {
 
     // check if the directory entry is a hsperfdata file
     if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -560,9 +559,8 @@
     }
 
     struct dirent* udentry;
-    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
-    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+    while ((udentry = os::readdir(subdirp)) != NULL) {
 
       if (filename_to_pid(udentry->d_name) == vmid) {
         struct stat statbuf;
@@ -606,11 +604,9 @@
       }
     }
     os::closedir(subdirp);
-    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
     FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   }
   os::closedir(tmpdirp);
-  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
 
   return(oldest_user);
 }
@@ -737,10 +733,8 @@
   // opendir/readdir.
   //
   struct dirent* entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
   errno = 0;
-  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+  while ((entry = os::readdir(dirp)) != NULL) {
 
     pid_t pid = filename_to_pid(entry->d_name);
 
@@ -780,7 +774,6 @@
   // close the directory and reset the current working directory
   close_directory_secure_cwd(dirp, saved_cwd_fd);
 
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
 // make the user specific temporary directory. Returns true if
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 2aca06d..06eebde 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -1172,14 +1172,12 @@
     return dirp;
 }
 
-/* parameter dbuf unused on Windows */
-
 struct dirent *
-os::readdir(DIR *dirp, dirent *dbuf)
+os::readdir(DIR *dirp)
 {
     assert(dirp != NULL, "just checking");      // hotspot change
     if (dirp->handle == INVALID_HANDLE_VALUE) {
-        return 0;
+        return NULL;
     }
 
     strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);
@@ -1187,7 +1185,7 @@
     if (!FindNextFile(dirp->handle, &dirp->find_data)) {
         if (GetLastError() == ERROR_INVALID_HANDLE) {
             errno = EBADF;
-            return 0;
+            return NULL;
         }
         FindClose(dirp->handle);
         dirp->handle = INVALID_HANDLE_VALUE;
diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp
index 30ce468..5dac11c 100644
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp
@@ -65,14 +65,6 @@
   return true;
 }
 
-inline int os::readdir_buf_size(const char *path)
-{
-  /* As Windows doesn't use the directory entry buffer passed to
-     os::readdir() this can be as short as possible */
-
-  return 1;
-}
-
 // Bang the shadow pages if they need to be touched to be mapped.
 inline void os::bang_stack_shadow_pages() {
   // Write to each page of our new frame to force OS mapping.
diff --git a/hotspot/src/os/windows/vm/perfMemory_windows.cpp b/hotspot/src/os/windows/vm/perfMemory_windows.cpp
index b32fd9a..c4cf8c1 100644
--- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp
+++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp
@@ -316,9 +316,8 @@
   // to determine the user name for the process id.
   //
   struct dirent* dentry;
-  char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
   errno = 0;
-  while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+  while ((dentry = os::readdir(tmpdirp)) != NULL) {
 
     // check if the directory entry is a hsperfdata file
     if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -351,9 +350,8 @@
     }
 
     struct dirent* udentry;
-    char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
     errno = 0;
-    while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+    while ((udentry = os::readdir(subdirp)) != NULL) {
 
       if (filename_to_pid(udentry->d_name) == vmid) {
         struct stat statbuf;
@@ -405,11 +403,9 @@
       }
     }
     os::closedir(subdirp);
-    FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
     FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   }
   os::closedir(tmpdirp);
-  FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
 
   return(latest_user);
 }
@@ -639,9 +635,8 @@
   // opendir/readdir.
   //
   struct dirent* entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
   errno = 0;
-  while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+  while ((entry = os::readdir(dirp)) != NULL) {
 
     int pid = filename_to_pid(entry->d_name);
 
@@ -682,7 +677,6 @@
     errno = 0;
   }
   os::closedir(dirp);
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
 // create a file mapping object with the requested name, and size
diff --git a/hotspot/src/share/vm/c1/c1_Optimizer.cpp b/hotspot/src/share/vm/c1/c1_Optimizer.cpp
index f366462..a2ba0e3 100644
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp
+++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp
@@ -175,6 +175,12 @@
   for_each_phi_fun(t_block, phi, return; );
   for_each_phi_fun(f_block, phi, return; );
 
+  // Only replace safepoint gotos if state_before information is available (if is a safepoint)
+  bool is_safepoint = if_->is_safepoint();
+  if (!is_safepoint && (t_goto->is_safepoint() || f_goto->is_safepoint())) {
+    return;
+  }
+
   // 2) substitute conditional expression
   //    with an IfOp followed by a Goto
   // cut if_ away and get node before
@@ -203,7 +209,7 @@
 
   // append Goto to successor
   ValueStack* state_before = if_->state_before();
-  Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
+  Goto* goto_ = new Goto(sux, state_before, is_safepoint);
 
   // prepare state for Goto
   ValueStack* goto_state = if_state;
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 6aff230..0204188 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -147,7 +147,7 @@
       len = name->utf8_length();                                 \
     }                                                            \
     HOTSPOT_CLASS_INITIALIZATION_##type(                         \
-      data, len, (clss)->class_loader(), thread_type);           \
+      data, len, (void *)(clss)->class_loader(), thread_type); \
   }
 
 #define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
@@ -160,7 +160,7 @@
       len = name->utf8_length();                                 \
     }                                                            \
     HOTSPOT_CLASS_INITIALIZATION_##type(                         \
-      data, len, (clss)->class_loader(), thread_type, wait);     \
+      data, len, (void *)(clss)->class_loader(), thread_type, wait); \
   }
 #endif /* USDT2 */
 
diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp
index 9f612c3..df01892 100644
--- a/hotspot/src/share/vm/oops/klass.hpp
+++ b/hotspot/src/share/vm/oops/klass.hpp
@@ -335,10 +335,11 @@
     _lh_header_size_mask        = right_n_bits(BitsPerByte),  // shifted mask
     _lh_array_tag_bits          = 2,
     _lh_array_tag_shift         = BitsPerInt - _lh_array_tag_bits,
-    _lh_array_tag_type_value    = ~0x00,  // 0xC0000000 >> 30
     _lh_array_tag_obj_value     = ~0x01   // 0x80000000 >> 30
   };
 
+  static const unsigned int _lh_array_tag_type_value = 0Xffffffff; // ~0x00,  // 0xC0000000 >> 30
+
   static int layout_helper_size_in_bytes(jint lh) {
     assert(lh > (jint)_lh_neutral_value, "must be instance");
     return (int) lh & ~_lh_instance_slow_path_bit;
diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp
index 3101455..68f068d 100644
--- a/hotspot/src/share/vm/opto/ifnode.cpp
+++ b/hotspot/src/share/vm/opto/ifnode.cpp
@@ -601,7 +601,7 @@
     if( din4->is_Call() &&      // Handle a slow-path call on either arm
         (din4 = din4->in(0)) )
       din4 = din4->in(0);
-    if( din3 == din4 && din3->is_If() )
+    if (din3 != NULL && din3 == din4 && din3->is_If()) // Regions not degraded to a copy
       return din3;              // Skip around diamonds
   }
 
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 5f2bb30..4bb5ca8 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3803,7 +3803,7 @@
   }
   // Now test the correct condition.
   jint  nval = (obj_array
-                ? ((jint)Klass::_lh_array_tag_type_value
+                ? (jint)(Klass::_lh_array_tag_type_value
                    <<    Klass::_lh_array_tag_shift)
                 : Klass::_lh_neutral_value);
   Node* cmp = _gvn.transform(new(C) CmpINode(layout_val, intcon(nval)));
@@ -6759,10 +6759,18 @@
   if (state == NULL) return false;
 
   // Call the stub.
-  Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
-                                 OptoRuntime::digestBase_implCompressMB_Type(),
-                                 stubAddr, stubName, TypePtr::BOTTOM,
-                                 src_start, state, ofs, limit);
+  Node *call;
+  if (CCallingConventionRequiresIntsAsLongs) {
+    call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                             OptoRuntime::digestBase_implCompressMB_Type(),
+                             stubAddr, stubName, TypePtr::BOTTOM,
+                             src_start, state, ofs XTOP, limit XTOP);
+  } else {
+    call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                             OptoRuntime::digestBase_implCompressMB_Type(),
+                             stubAddr, stubName, TypePtr::BOTTOM,
+                             src_start, state, ofs, limit);
+  }
   // return ofs (int)
   Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms));
   set_result(result);
diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp
index 5d2b469..db7c108 100644
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp
@@ -611,7 +611,11 @@
   const TypeInt* idx_type = TypeInt::INT;
   if ((stride > 0) == (scale > 0) == upper) {
     if (TraceLoopPredicate) {
-      predString->print(limit->is_Con() ? "(%d " : "(limit ", con_limit);
+      if (limit->is_Con()) {
+        predString->print("(%d ", con_limit);
+      } else {
+        predString->print("(limit ");
+      }
       predString->print("- %d) ", stride);
     }
     // Check if (limit - stride) may overflow
@@ -639,7 +643,11 @@
     register_new_node(max_idx_expr, ctrl);
   } else {
     if (TraceLoopPredicate) {
-      predString->print(init->is_Con() ? "%d " : "init ", con_init);
+      if (init->is_Con()) {
+        predString->print("%d ", con_init);
+      } else {
+        predString->print("init ");
+      }
     }
     idx_type = _igvn.type(init)->isa_int();
     max_idx_expr = init;
@@ -675,7 +683,11 @@
 
   if (offset && (!offset->is_Con() || con_offset != 0)){
     if (TraceLoopPredicate) {
-      predString->print(offset->is_Con() ? "+ %d " : "+ offset", con_offset);
+      if (offset->is_Con()) {
+        predString->print("+ %d ", con_offset);
+      } else {
+        predString->print("+ offset");
+      }
     }
     // Check if (max_idx_expr + offset) may overflow
     const TypeInt* offset_type = _igvn.type(offset)->isa_int();
diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp
index 364152c..57d2f57 100644
--- a/hotspot/src/share/vm/opto/runtime.cpp
+++ b/hotspot/src/share/vm/opto/runtime.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -930,12 +930,24 @@
   // create input type (domain)
   int num_args = 4;
   int argcnt = num_args;
+  if(CCallingConventionRequiresIntsAsLongs) {
+    argcnt += 2;
+  }
   const Type** fields = TypeTuple::fields(argcnt);
   int argp = TypeFunc::Parms;
-  fields[argp++] = TypePtr::NOTNULL; // buf
-  fields[argp++] = TypePtr::NOTNULL; // state
-  fields[argp++] = TypeInt::INT;     // ofs
-  fields[argp++] = TypeInt::INT;     // limit
+  if(CCallingConventionRequiresIntsAsLongs) {
+    fields[argp++] = TypePtr::NOTNULL; // buf
+    fields[argp++] = TypePtr::NOTNULL; // state
+    fields[argp++] = TypeLong::LONG;   // ofs
+    fields[argp++] = Type::HALF;
+    fields[argp++] = TypeLong::LONG;   // limit
+    fields[argp++] = Type::HALF;
+  } else {
+    fields[argp++] = TypePtr::NOTNULL; // buf
+    fields[argp++] = TypePtr::NOTNULL; // state
+    fields[argp++] = TypeInt::INT;     // ofs
+    fields[argp++] = TypeInt::INT;     // limit
+  }
   assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
   const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
 
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 43e31d2..2665b6b 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -556,8 +556,7 @@
 
   /* Scan the directory for jars/zips, appending them to path. */
   struct dirent *entry;
-  char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
-  while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+  while ((entry = os::readdir(dir)) != NULL) {
     const char* name = entry->d_name;
     const char* ext = name + strlen(name) - 4;
     bool isJarOrZip = ext > name &&
@@ -571,7 +570,6 @@
       FREE_C_HEAP_ARRAY(char, jarpath, mtInternal);
     }
   }
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   os::closedir(dir);
   return path;
 }
@@ -3485,14 +3483,12 @@
   if (dir == NULL) return false;
 
   struct dirent *entry;
-  char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
   bool hasJarFile = false;
-  while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+  while (!hasJarFile && (entry = os::readdir(dir)) != NULL) {
     const char* name = entry->d_name;
     const char* ext = name + strlen(name) - 4;
     hasJarFile = ext > name && (os::file_name_strcmp(ext, ".jar") == 0);
   }
-  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   os::closedir(dir);
   return hasJarFile ;
 }
@@ -3574,8 +3570,7 @@
   if (dir != NULL) {
     int num_ext_jars = 0;
     struct dirent *entry;
-    char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(extDir), mtInternal);
-    while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+    while ((entry = os::readdir(dir)) != NULL) {
       const char* name = entry->d_name;
       const char* ext = name + strlen(name) - 4;
       if (ext > name && (os::file_name_strcmp(ext, ".jar") == 0)) {
@@ -3594,7 +3589,6 @@
         }
       }
     }
-    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
     os::closedir(dir);
     if (num_ext_jars > 0) {
       nonEmptyDirs += 1;
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 931f4cb..14cd942 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -561,8 +561,7 @@
 
   // Reading directories.
   static DIR*           opendir(const char* dirname);
-  static int            readdir_buf_size(const char *path);
-  static struct dirent* readdir(DIR* dirp, dirent* dbuf);
+  static struct dirent* readdir(DIR* dirp);
   static int            closedir(DIR* dirp);
 
   // Dynamic library extension
diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp
index 92a548b..fce2b27 100644
--- a/hotspot/src/share/vm/services/classLoadingService.cpp
+++ b/hotspot/src/share/vm/services/classLoadingService.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
       len = name->utf8_length();                    \
     }                                               \
     HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \
-      data, len, (clss)->class_loader(), (shared)); \
+      data, len, (void *)(clss)->class_loader(), (shared)); \
   }
 
 #endif /* USDT2 */
diff --git a/hotspot/test/compiler/c1/TestGotoIf.jasm b/hotspot/test/compiler/c1/TestGotoIf.jasm
new file mode 100644
index 0000000..b5dc03a
--- /dev/null
+++ b/hotspot/test/compiler/c1/TestGotoIf.jasm
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+public class compiler/c1/TestGotoIf version 52:0 {
+    public Field f1:"I";
+    public Field f2:"I";
+    public static Field i:"I";
+
+    Method "<init>":"()V" stack 1 locals 1 {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+    public Method test1:"()I" stack 3 locals 1 {
+        aload_0;
+        getfield Field f1:"I";
+        aload_0;
+        getfield Field f2:"I";
+        iconst_1;
+        isub;
+        // Without the fix, if got eliminated by CEE
+        if_icmpgt Null;
+        iconst_1;
+      Return: stack_frame_type stack1;
+      stack_map int;
+        ireturn;
+      Null: stack_frame_type same;
+        iconst_0;
+        goto Return; // Backbranch (t_goto) with safepoint
+    }
+
+    public Method test2:"()I" stack 3 locals 1 {
+        aload_0;
+        getfield Field f1:"I";
+        aload_0;
+        getfield Field f2:"I";
+        iconst_1;
+        isub;
+        goto Skip;
+      Return: stack_frame_type full;
+      stack_map int;
+        ireturn;
+      Skip: stack_frame_type full;
+      stack_map int, int;
+        // Without the fix, if got eliminated by CEE
+        if_icmpgt Null;
+        iconst_1;
+        goto Return; // Backbranch (f_goto) with safepoint
+      Null: stack_frame_type full;
+      stack_map;
+        iconst_0;
+        goto Return; // Backbranch (t_goto) with safepoint
+    }
+
+    public Method test3:"()I" stack 3 locals 1 {
+        aload_0;
+        getfield Field f1:"I";
+        aload_0;
+        getfield Field f2:"I";
+        iconst_1;
+        isub;
+        goto Skip;
+      Return: stack_frame_type full;
+      stack_map int;
+        ireturn;
+      Null: stack_frame_type full;
+      stack_map;
+        iconst_0;
+        goto Return; // Backbranch (t_goto) with safepoint
+      Skip: stack_frame_type full;
+      stack_map int, int;
+        // If will be eliminated by CEE
+        if_icmpgt Null; // Backbranch (if) with safepoint
+        iconst_1;
+        goto Return; // Backbranch (f_goto) with safepoint
+    }
+
+    public Method test4:"()I" stack 3 locals 1 {
+        aload_0;
+        getfield Field f1:"I";
+        aload_0;
+        getfield Field f2:"I";
+        iconst_1;
+        isub;
+        goto Skip;
+      Null: stack_frame_type full;
+      stack_map;
+        iconst_0;
+      Return: stack_frame_type full;
+      stack_map int;
+        ireturn; 
+      Skip: stack_frame_type full;
+      stack_map int, int;
+        // If will be eliminated by CEE
+        if_icmpgt Null; // Backbranch (if) with safepoint
+        iconst_1;
+        goto Return; // Backbranch (f_goto) with safepoint
+    }
+
+    public Method test5:"()I" stack 3 locals 2 {
+        aload_0;
+        getfield Field f1:"I";
+        aload_0;
+        getfield Field f2:"I";
+        iconst_1;
+        isub;
+        goto Skip;
+      Null: stack_frame_type full;
+      stack_map;
+        iconst_0;
+        goto Return;
+      Skip: stack_frame_type full;
+      stack_map int, int;
+        // If will be eliminated by CEE
+        if_icmpgt Null; // Backbranch (if) with safepoint
+        iconst_1;
+      Return: stack_frame_type full;
+      stack_map int;
+        ireturn; 
+    }
+
+    public Method test6:"()I" stack 4 locals 1 {
+        getstatic Field i:"I";
+      Loop: stack_frame_type full;
+      stack_map int;
+        // Decrement i and exit loop if < 0
+        iconst_0;
+        getstatic Field i:"I";
+        iconst_1;
+        isub;
+        dup;
+        putstatic Field i:"I";
+        if_icmpgt Exit;
+
+        iconst_1;
+        // Without the fix, if got eliminated by CEE
+        if_icmpgt Null;
+        iconst_1;
+        goto Loop; // Backbranch (f_goto) with safepoint
+      Null: stack_frame_type same;
+        iconst_0;
+        goto Loop; // Backbranch (t_goto) with safepoint
+
+      Exit: stack_frame_type full;
+      stack_map int;
+        iconst_0;
+        ireturn; 
+    }
+}
diff --git a/hotspot/test/compiler/c1/TestGotoIfMain.java b/hotspot/test/compiler/c1/TestGotoIfMain.java
new file mode 100644
index 0000000..ac8b1b8
--- /dev/null
+++ b/hotspot/test/compiler/c1/TestGotoIfMain.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8218721
+ * @compile TestGotoIf.jasm
+ * @run main/othervm -XX:TieredStopAtLevel=1 -Xcomp
+ *                   -XX:CompileCommand=compileonly,compiler.c1.TestGotoIf::test*
+ *                   compiler.c1.TestGotoIfMain
+ */
+
+package compiler.c1;
+
+public class TestGotoIfMain {
+    public static void main(String[] args) {
+        TestGotoIf test = new TestGotoIf();
+        test.i = 5;
+        test.test1();
+        test.test2();
+        test.test3();
+        test.test4();
+        test.test5();
+        test.test6();
+    }
+}
diff --git a/hotspot/test/compiler/c2/TestIfWithDeadRegion.java b/hotspot/test/compiler/c2/TestIfWithDeadRegion.java
new file mode 100644
index 0000000..1117908
--- /dev/null
+++ b/hotspot/test/compiler/c2/TestIfWithDeadRegion.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8219807
+ * @summary Test IfNode::up_one_dom() with dead regions.
+ * @compile -XDstringConcat=inline TestIfWithDeadRegion.java
+ * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestIfWithDeadRegion::test
+ *                   compiler.c2.TestIfWithDeadRegion
+ */
+
+package compiler.c2;
+
+import java.util.function.Supplier;
+
+public class TestIfWithDeadRegion {
+
+    static String msg;
+
+    static String getString(String s, int i) {
+        String current = s + String.valueOf(i);
+        System.nanoTime();
+        return current;
+    }
+
+    static void test(Supplier<String> supplier) {
+        msg = supplier.get();
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 20_000; ++i) {
+            test(() -> getString("Test1", 42));
+            test(() -> getString("Test2", 42));
+        }
+    }
+}
diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
index c5d21ed..3285071 100644
--- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
@@ -36,7 +36,8 @@
     public GenericTestCaseForOtherCPU(String optionName) {
         // Execute the test case on any CPU except SPARC and X86
         super(optionName, new NotPredicate(new OrPredicate(Platform::isSparc,
-                new OrPredicate(Platform::isX64, Platform::isX86))));
+                new OrPredicate(Platform::isPPC,
+                new OrPredicate(Platform::isX64, Platform::isX86)))));
     }
 
     @Override
diff --git a/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
index 51ab609..bac4665 100644
--- a/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
+++ b/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
@@ -63,12 +63,20 @@
                     null);
 
     public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE
-            = new CPUSpecificPredicate("sparc.*", new String[] { "sha256" },
-                    null);
+            = new OrPredicate(new CPUSpecificPredicate("sparc.*",   new String[] { "sha256" },
+                                                       null),
+              new OrPredicate(new CPUSpecificPredicate("ppc64.*",   new String[] { "sha"    },
+                                                       null),
+                              new CPUSpecificPredicate("ppc64le.*", new String[] { "sha"    },
+                                                       null)));
 
     public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE
-            = new CPUSpecificPredicate("sparc.*", new String[] { "sha512" },
-                    null);
+            = new OrPredicate(new CPUSpecificPredicate("sparc.*",   new String[] { "sha512" },
+                                                       null),
+              new OrPredicate(new CPUSpecificPredicate("ppc64.*",   new String[] { "sha"    },
+                                                       null),
+                              new CPUSpecificPredicate("ppc64le.*", new String[] { "sha"    },
+                                                       null)));
 
     public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE
             = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index b7771da..857a785 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -1001,4 +1001,7 @@
 e18fe3687a512b39b08d7d8e288b06cfd7e18840 jdk8u222-b06
 08cd0a82185d3aaa614d628977e1809d6b4879cf jdk8u222-b07
 2b416473fe205b3abea19b8de53d948fbe4f67f1 jdk8u222-b08
+de624afa6e750486bc1ea3e59bf9fb7de24b1379 jdk8u232-b00
 60d685ed9d5bb2eb4847d6e6e4237565fe40089b jdk8u222-b09
+268ffbdb01e136ccd78a5f3f8c8aa2d58e71fcb5 jdk8u222-b10
+268ffbdb01e136ccd78a5f3f8c8aa2d58e71fcb5 jdk8u222-ga
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 6bbc13d..2a4f316 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -995,4 +995,7 @@
 dfe2ef52003ccd228f05d3d8e18f26eafda88ae1 jdk8u222-b06
 2fa997404a5c0ef884a6eb86ca3df2fbc3346fc0 jdk8u222-b07
 3a9307bd93d3ed04e7ddf94e46ae6fd349cd8060 jdk8u222-b08
+bd5323b37905fc22dc5cddd32384ad9e46feca6e jdk8u232-b00
 22b905fce1aa80ee5f4dd615f49a8562260c1dbf jdk8u222-b09
+3a4dd1917fc5a3b415b7cdaf1a0394e31b072be5 jdk8u222-b10
+3a4dd1917fc5a3b415b7cdaf1a0394e31b072be5 jdk8u222-ga
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 424b1e2..b68c2dd 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -996,4 +996,7 @@
 63b345c88831be5a690b857adfa84bd20ad376e1 jdk8u222-b06
 c7a97c9b7e5932d651eda37c8a907311818491d7 jdk8u222-b07
 0bb89d93d4d7da64d408a9888df21085e7bfb291 jdk8u222-b08
+887c8314411dd461ec4b1e14cd6368ed3d9a7a3b jdk8u232-b00
 0da125166b2bd35aac0d6222ba44535730e2713f jdk8u222-b09
+2a9bea6e5e03a53469abdcd2da268a312cc7b5b8 jdk8u222-b10
+2a9bea6e5e03a53469abdcd2da268a312cc7b5b8 jdk8u222-ga
diff --git a/jdk/make/Images.gmk b/jdk/make/Images.gmk
index 06077dc..3354d80 100644
--- a/jdk/make/Images.gmk
+++ b/jdk/make/Images.gmk
@@ -125,7 +125,9 @@
       wsimport$(EXE_SUFFIX) \
       schemagen$(EXE_SUFFIX) \
       jsadebugd$(EXE_SUFFIX) \
-      jhat$(EXE_SUFFIX)
+      jhat$(EXE_SUFFIX) \
+      clhsdb$(EXE_SUFFIX) \
+      hsdb$(EXE_SUFFIX)
 endif
 
 WINDOWS_JDK_BIN_FILES = \
diff --git a/jdk/make/mapfiles/launchers/mapfile-x86 b/jdk/make/mapfiles/launchers/mapfile-x86
index dcda7f9..5951e8e 100644
--- a/jdk/make/mapfiles/launchers/mapfile-x86
+++ b/jdk/make/mapfiles/launchers/mapfile-x86
@@ -42,6 +42,11 @@
 		__fsr;
 		__fsr_init_value;
 		__longdouble_used;
+                # Needs to be global rather than local. Note that _IO_stdin_used
+                # is exported by crt1.o. If it were using 'local' scope instead,
+                # glibc would use a legacy implementation of libio, which isn't
+                # what we want
+                _IO_stdin_used;
 
 	local:
 		*;
diff --git a/jdk/make/mapfiles/libj2pkcs11/mapfile-vers b/jdk/make/mapfiles/libj2pkcs11/mapfile-vers
index 6ca76c0..8f01cde 100644
--- a/jdk/make/mapfiles/libj2pkcs11/mapfile-vers
+++ b/jdk/make/mapfiles/libj2pkcs11/mapfile-vers
@@ -32,6 +32,8 @@
 		Java_sun_security_pkcs11_wrapper_PKCS11_finalizeLibrary;
 		Java_sun_security_pkcs11_wrapper_PKCS11_connect;
 		Java_sun_security_pkcs11_wrapper_PKCS11_disconnect;
+		Java_sun_security_pkcs11_wrapper_PKCS11_getNativeKeyInfo;
+		Java_sun_security_pkcs11_wrapper_PKCS11_createNativeKey;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1Initialize;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1Finalize;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetInfo;
diff --git a/jdk/src/share/classes/java/io/ObjectStreamClass.java b/jdk/src/share/classes/java/io/ObjectStreamClass.java
index bcbbea2..a2181c6 100644
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java
@@ -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
@@ -2371,7 +2371,7 @@
      */
     private static class FieldReflectorKey extends WeakReference<Class<?>> {
 
-        private final String sigs;
+        private final String[] sigs;
         private final int hash;
         private final boolean nullClass;
 
@@ -2380,13 +2380,13 @@
         {
             super(cl, queue);
             nullClass = (cl == null);
-            StringBuilder sbuf = new StringBuilder();
-            for (int i = 0; i < fields.length; i++) {
+            sigs = new String[2 * fields.length];
+            for (int i = 0, j = 0; i < fields.length; i++) {
                 ObjectStreamField f = fields[i];
-                sbuf.append(f.getName()).append(f.getSignature());
+                sigs[j++] = f.getName();
+                sigs[j++] = f.getSignature();
             }
-            sigs = sbuf.toString();
-            hash = System.identityHashCode(cl) + sigs.hashCode();
+            hash = System.identityHashCode(cl) + Arrays.hashCode(sigs);
         }
 
         public int hashCode() {
@@ -2404,7 +2404,7 @@
                 return (nullClass ? other.nullClass
                                   : ((referent = get()) != null) &&
                                     (referent == other.get())) &&
-                    sigs.equals(other.sigs);
+                        Arrays.equals(sigs, other.sigs);
             } else {
                 return false;
             }
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
index 842af56..2e98092 100644
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
@@ -255,9 +255,6 @@
         new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
                              null, this, null);
 
-    // The initiating protection domains for all classes loaded by this loader
-    private final Set<ProtectionDomain> domains;
-
     // Invoked by the VM to record every loaded class with this loader.
     void addClass(Class<?> c) {
         classes.addElement(c);
@@ -281,14 +278,11 @@
         if (ParallelLoaders.isRegistered(this.getClass())) {
             parallelLockMap = new ConcurrentHashMap<>();
             package2certs = new ConcurrentHashMap<>();
-            domains =
-                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
             assertionLock = new Object();
         } else {
             // no finer-grained lock; lock on the classloader instance
             parallelLockMap = null;
             package2certs = new Hashtable<>();
-            domains = new HashSet<>();
             assertionLock = this;
         }
     }
@@ -505,7 +499,6 @@
                 }, new AccessControlContext(new ProtectionDomain[] {pd}));
             }
         }
-        domains.add(pd);
     }
 
     /**
diff --git a/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java
index 955daab..d645bb4 100644
--- a/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java
+++ b/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java
@@ -421,6 +421,20 @@
     static final int ASYNC  =  1;
     static final int NESTED = -1;
 
+    /**
+     * Spins before blocking in waitingGet.
+     * There is no need to spin on uniprocessors.
+     *
+     * Call to Runtime.availableProcessors is expensive, cache the value here.
+     * This unfortunately relies on the number of available CPUs during first
+     * initialization. This affects the case when MP system would report only
+     * one CPU available at startup, initialize SPINS to 0, and then make more
+     * CPUs online. This would incur some performance penalty due to less spins
+     * than would otherwise happen.
+     */
+    private static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
+                                      1 << 8 : 0);
+
     /* ------------- Base Completion classes and operations -------------- */
 
     @SuppressWarnings("serial")
@@ -1709,8 +1723,7 @@
         Object r;
         while ((r = result) == null) {
             if (spins < 0)
-                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
-                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
+                spins = SPINS;
             else if (spins > 0) {
                 if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                     --spins;
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
index 3d3f5a1..bf72636 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -344,7 +344,7 @@
     private void implInit(int opmode, Key key, byte[] iv,
             SecureRandom random)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
-        cancelOperation();
+        reset(true);
         if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
             throw new InvalidKeyException("Key size is invalid");
         }
@@ -400,58 +400,83 @@
         }
     }
 
-    private void cancelOperation() {
-        if (initialized == false) {
+    // reset the states to the pre-initialized values
+    // need to be called after doFinal or prior to re-init
+    private void reset(boolean doCancel) {
+        if (!initialized) {
             return;
         }
         initialized = false;
-        if ((session == null) || (token.explicitCancel == false)) {
-            return;
-        }
-        // cancel operation by finishing it
-        int bufLen = doFinalLength(0);
-        byte[] buffer = new byte[bufLen];
         try {
-            if (encrypt) {
-                token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
-            } else {
-                token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+            if (session == null) {
+                return;
             }
-        } catch (PKCS11Exception e) {
-            throw new ProviderException("Cancel failed", e);
+            if (doCancel && token.explicitCancel) {
+                cancelOperation();
+            }
         } finally {
-            reset();
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
+            bytesBuffered = 0;
+            padBufferLen = 0;
+        }
+    }
+
+    private void cancelOperation() {
+        token.ensureValid();
+        if (session.hasObjects() == false) {
+            session = token.killSession(session);
+            return;
+        } else {
+            try {
+                // cancel operation by finishing it
+                int bufLen = doFinalLength(0);
+                byte[] buffer = new byte[bufLen];
+                if (encrypt) {
+                    token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+                } else {
+                    token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+                }
+            } catch (PKCS11Exception e) {
+                throw new ProviderException("Cancel failed", e);
+            }
         }
     }
 
     private void ensureInitialized() throws PKCS11Exception {
-        if (initialized == false) {
+        if (!initialized) {
             initialize();
         }
     }
 
     private void initialize() throws PKCS11Exception {
-        if (session == null) {
-            session = token.getOpSession();
+        if (p11Key == null) {
+            throw new ProviderException(
+                    "Operation cannot be performed without"
+                    + " calling engineInit first");
         }
-        CK_MECHANISM mechParams = (blockMode == MODE_CTR?
-            new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
-            new CK_MECHANISM(mechanism, iv));
-
+        token.ensureValid();
+        long p11KeyID = p11Key.getKeyID();
         try {
-            if (encrypt) {
-                token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
-            } else {
-                token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID);
+            if (session == null) {
+                session = token.getOpSession();
             }
-        } catch (PKCS11Exception ex) {
-            // release session when initialization failed
+            CK_MECHANISM mechParams = (blockMode == MODE_CTR?
+                    new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
+                    new CK_MECHANISM(mechanism, iv));
+            if (encrypt) {
+                token.p11.C_EncryptInit(session.id(), mechParams, p11KeyID);
+            } else {
+                token.p11.C_DecryptInit(session.id(), mechParams, p11KeyID);
+            }
+        } catch (PKCS11Exception e) {
+            p11Key.releaseKeyID();
             session = token.releaseSession(session);
-            throw ex;
+            throw e;
         }
+        initialized = true;
         bytesBuffered = 0;
         padBufferLen = 0;
-        initialized = true;
     }
 
     // if update(inLen) is called, how big does the output buffer have to be?
@@ -482,16 +507,6 @@
         return result;
     }
 
-    // reset the states to the pre-initialized values
-    private void reset() {
-        initialized = false;
-        bytesBuffered = 0;
-        padBufferLen = 0;
-        if (session != null) {
-            session = token.releaseSession(session);
-        }
-    }
-
     // see JCE spec
     protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
         try {
@@ -610,7 +625,7 @@
                 throw (ShortBufferException)
                         (new ShortBufferException().initCause(e));
             }
-            reset();
+            reset(false);
             throw new ProviderException("update() failed", e);
         }
     }
@@ -728,7 +743,7 @@
                 throw (ShortBufferException)
                         (new ShortBufferException().initCause(e));
             }
-            reset();
+            reset(false);
             throw new ProviderException("update() failed", e);
         }
     }
@@ -740,6 +755,7 @@
         if (outLen < requiredOutLen) {
             throw new ShortBufferException();
         }
+        boolean doCancel = true;
         try {
             ensureInitialized();
             int k = 0;
@@ -753,7 +769,12 @@
                 }
                 k += token.p11.C_EncryptFinal(session.id(),
                         0, out, (outOfs + k), (outLen - k));
+                doCancel = false;
             } else {
+                // Special handling to match SunJCE provider behavior
+                if (bytesBuffered == 0 && padBufferLen == 0) {
+                    return 0;
+                }
                 if (paddingObj != null) {
                     if (padBufferLen != 0) {
                         k = token.p11.C_DecryptUpdate(session.id(), 0,
@@ -762,20 +783,24 @@
                     }
                     k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
                             padBuffer.length - k);
+                    doCancel = false;
+
                     int actualPadLen = paddingObj.unpad(padBuffer, k);
                     k -= actualPadLen;
                     System.arraycopy(padBuffer, 0, out, outOfs, k);
                 } else {
                     k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
                             outLen);
+                    doCancel = false;
                 }
             }
             return k;
         } catch (PKCS11Exception e) {
+            doCancel = false;
             handleException(e);
             throw new ProviderException("doFinal() failed", e);
         } finally {
-            reset();
+            reset(doCancel);
         }
     }
 
@@ -788,6 +813,7 @@
             throw new ShortBufferException();
         }
 
+        boolean doCancel = true;
         try {
             ensureInitialized();
 
@@ -818,7 +844,13 @@
                 }
                 k += token.p11.C_EncryptFinal(session.id(),
                         outAddr, outArray, (outOfs + k), (outLen - k));
+                doCancel = false;
             } else {
+                // Special handling to match SunJCE provider behavior
+                if (bytesBuffered == 0 && padBufferLen == 0) {
+                    return 0;
+                }
+
                 if (paddingObj != null) {
                     if (padBufferLen != 0) {
                         k = token.p11.C_DecryptUpdate(session.id(),
@@ -828,6 +860,8 @@
                     }
                     k += token.p11.C_DecryptFinal(session.id(),
                             0, padBuffer, k, padBuffer.length - k);
+                    doCancel = false;
+
                     int actualPadLen = paddingObj.unpad(padBuffer, k);
                     k -= actualPadLen;
                     outArray = padBuffer;
@@ -835,6 +869,7 @@
                 } else {
                     k = token.p11.C_DecryptFinal(session.id(),
                             outAddr, outArray, outOfs, outLen);
+                    doCancel = false;
                 }
             }
             if ((!encrypt && paddingObj != null) ||
@@ -846,10 +881,11 @@
             }
             return k;
         } catch (PKCS11Exception e) {
+            doCancel = false;
             handleException(e);
             throw new ProviderException("doFinal() failed", e);
         } finally {
-            reset();
+            reset(doCancel);
         }
     }
 
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
index 7bc5f14..3815694 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -221,7 +221,12 @@
                 new CK_ATTRIBUTE(CKA_PRIME),
                 new CK_ATTRIBUTE(CKA_BASE),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
             KeySpec spec = new DHPublicKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger(),
@@ -243,7 +248,12 @@
                 new CK_ATTRIBUTE(CKA_PRIME),
                 new CK_ATTRIBUTE(CKA_BASE),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
             KeySpec spec = new DHPrivateKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger(),
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
index d9550cb..9263fc8 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -218,7 +218,12 @@
                 new CK_ATTRIBUTE(CKA_SUBPRIME),
                 new CK_ATTRIBUTE(CKA_BASE),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
             KeySpec spec = new DSAPublicKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger(),
@@ -242,7 +247,12 @@
                 new CK_ATTRIBUTE(CKA_SUBPRIME),
                 new CK_ATTRIBUTE(CKA_BASE),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
             KeySpec spec = new DSAPrivateKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger(),
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java b/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java
index 2dc66d2..3e8bd10 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,8 @@
         token.ensureValid();
 
         if (session != null) {
-            if (state == S_INIT && token.explicitCancel == true) {
+            if (state == S_INIT && token.explicitCancel == true
+                    && session.hasObjects() == false) {
                 session = token.killSession(session);
             } else {
                 session = token.releaseSession(session);
@@ -250,6 +251,7 @@
         }
 
         fetchSession();
+        long p11KeyID = p11Key.getKeyID();
         try {
             if (state == S_BUFFERED) {
                 token.p11.C_DigestInit(session.id(), mechanism);
@@ -260,10 +262,12 @@
                 token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
                 bufOfs = 0;
             }
-            token.p11.C_DigestKey(session.id(), p11Key.keyID);
+            token.p11.C_DigestKey(session.id(), p11KeyID);
         } catch (PKCS11Exception e) {
             engineReset();
             throw new ProviderException("update(SecretKey) failed", e);
+        } finally {
+            p11Key.releaseKeyID();
         }
     }
 
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java b/jdk/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
index ac2b7e3..52b56ef 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,6 +120,7 @@
             throw new IllegalStateException("Not initialized correctly");
         }
         Session session = null;
+        long privKeyID = privateKey.getKeyID();
         try {
             session = token.getOpSession();
             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -131,8 +132,8 @@
             attributes = token.getAttributes
                 (O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
             long keyID = token.p11.C_DeriveKey(session.id(),
-                new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
-                attributes);
+                    new CK_MECHANISM(mechanism, ckParams), privKeyID,
+                    attributes);
             attributes = new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE)
             };
@@ -143,6 +144,7 @@
         } catch (PKCS11Exception e) {
             throw new ProviderException("Could not derive key", e);
         } finally {
+            privateKey.releaseKeyID();
             publicValue = null;
             token.releaseSession(session);
         }
@@ -182,6 +184,7 @@
         }
         long keyType = CKK_GENERIC_SECRET;
         Session session = null;
+        long privKeyID = privateKey.getKeyID();
         try {
             session = token.getObjSession();
             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -193,8 +196,8 @@
             attributes = token.getAttributes
                 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
             long keyID = token.p11.C_DeriveKey(session.id(),
-                new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
-                attributes);
+                    new CK_MECHANISM(mechanism, ckParams), privKeyID,
+                    attributes);
             CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE_LEN),
             };
@@ -206,6 +209,7 @@
         } catch (PKCS11Exception e) {
             throw new InvalidKeyException("Could not derive key", e);
         } finally {
+            privateKey.releaseKeyID();
             publicValue = null;
             token.releaseSession(session);
         }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
index 494ab00..ed1b84e 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -290,13 +290,16 @@
                 new CK_ATTRIBUTE(CKA_EC_POINT),
                 new CK_ATTRIBUTE(CKA_EC_PARAMS),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
             try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
                 ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
                 ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
                 return keySpec.cast(new ECPublicKeySpec(point, params));
             } catch (IOException e) {
                 throw new InvalidKeySpecException("Could not parse key", e);
+            } finally {
+                key.releaseKeyID();
             }
         } else { // X.509 handled in superclass
             throw new InvalidKeySpecException("Only ECPublicKeySpec and "
@@ -312,13 +315,16 @@
                 new CK_ATTRIBUTE(CKA_VALUE),
                 new CK_ATTRIBUTE(CKA_EC_PARAMS),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
             try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
                 ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
                 return keySpec.cast(
                     new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
             } catch (IOException e) {
                 throw new InvalidKeySpecException("Could not parse key", e);
+            } finally {
+                key.releaseKeyID();
             }
         } else { // PKCS#8 handled in superclass
             throw new InvalidKeySpecException("Only ECPrivateKeySpec "
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
index c56483a..feee544 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.lang.ref.*;
 import java.math.BigInteger;
 import java.util.*;
-
 import java.security.*;
 import java.security.interfaces.*;
 import java.security.spec.*;
@@ -43,11 +42,15 @@
 import sun.security.internal.interfaces.TlsMasterSecret;
 
 import sun.security.pkcs11.wrapper.*;
+
+import static sun.security.pkcs11.TemplateManager.O_GENERATE;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
 import sun.security.util.DerValue;
 import sun.security.util.Length;
 
+import sun.security.jca.JCAUtil;
+
 /**
  * Key implementation classes.
  *
@@ -79,23 +82,38 @@
     // algorithm name, returned by getAlgorithm(), etc.
     final String algorithm;
 
-    // key id
-    final long keyID;
-
     // effective key length of the key, e.g. 56 for a DES key
     final int keyLength;
 
     // flags indicating whether the key is a token object, sensitive, extractable
     final boolean tokenObject, sensitive, extractable;
 
-    // phantom reference notification clean up for session keys
-    private final SessionKeyRef sessionKeyRef;
+    private final NativeKeyHolder keyIDHolder;
+
+    private static final boolean DISABLE_NATIVE_KEYS_EXTRACTION;
+
+    /**
+     * {@systemProperty sun.security.pkcs11.disableKeyExtraction} property
+     * indicating whether or not cryptographic keys within tokens are
+     * extracted to a Java byte array for memory management purposes.
+     *
+     * Key extraction affects NSS PKCS11 library only.
+     *
+     */
+    static {
+        PrivilegedAction<String> getKeyExtractionProp =
+                () -> System.getProperty(
+                        "sun.security.pkcs11.disableKeyExtraction", "false");
+        String disableKeyExtraction =
+                AccessController.doPrivileged(getKeyExtractionProp);
+        DISABLE_NATIVE_KEYS_EXTRACTION =
+                "true".equalsIgnoreCase(disableKeyExtraction);
+    }
 
     P11Key(String type, Session session, long keyID, String algorithm,
             int keyLength, CK_ATTRIBUTE[] attributes) {
         this.type = type;
         this.token = session.token;
-        this.keyID = keyID;
         this.algorithm = algorithm;
         this.keyLength = keyLength;
         boolean tokenObject = false;
@@ -115,11 +133,21 @@
         this.tokenObject = tokenObject;
         this.sensitive = sensitive;
         this.extractable = extractable;
-        if (tokenObject == false) {
-            sessionKeyRef = new SessionKeyRef(this, keyID, session);
-        } else {
-            sessionKeyRef = null;
-        }
+        char[] tokenLabel = this.token.tokenInfo.label;
+        boolean isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
+                && tokenLabel[2] == 'S');
+        boolean extractKeyInfo = (!DISABLE_NATIVE_KEYS_EXTRACTION && isNSS &&
+                extractable && !tokenObject);
+        this.keyIDHolder = new NativeKeyHolder(this, keyID, session, extractKeyInfo,
+            tokenObject);
+    }
+
+    public long getKeyID() {
+        return keyIDHolder.getKeyID();
+    }
+
+    public void releaseKeyID() {
+        keyIDHolder.releaseKeyID();
     }
 
     // see JCA spec
@@ -204,8 +232,7 @@
         token.ensureValid();
         String s1 = token.provider.getName() + " " + algorithm + " " + type
                 + " key, " + keyLength + " bits";
-        s1 += " (id " + keyID + ", "
-                + (tokenObject ? "token" : "session") + " object";
+        s1 += (tokenObject ? "token" : "session") + " object";
         if (isPublic()) {
             s1 += ")";
         } else {
@@ -237,12 +264,15 @@
 
     void fetchAttributes(CK_ATTRIBUTE[] attributes) {
         Session tempSession = null;
+        long keyID = this.getKeyID();
         try {
             tempSession = token.getOpSession();
-            token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
+            token.p11.C_GetAttributeValue(tempSession.id(), keyID,
+                        attributes);
         } catch (PKCS11Exception e) {
             throw new ProviderException(e);
         } finally {
+            this.releaseKeyID();
             token.releaseSession(tempSession);
         }
     }
@@ -289,7 +319,8 @@
             new CK_ATTRIBUTE(CKA_SENSITIVE),
             new CK_ATTRIBUTE(CKA_EXTRACTABLE),
         });
-        return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
+        return new P11SecretKey(session, keyID, algorithm, keyLength,
+                attributes);
     }
 
     static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
@@ -299,8 +330,9 @@
             new CK_ATTRIBUTE(CKA_SENSITIVE),
             new CK_ATTRIBUTE(CKA_EXTRACTABLE),
         });
-        return new P11TlsMasterSecretKey
-                (session, keyID, algorithm, keyLength, attributes, major, minor);
+        return new P11TlsMasterSecretKey(
+                session, keyID, algorithm, keyLength, attributes, major,
+                minor);
     }
 
     // we assume that all components of public keys are always accessible
@@ -308,17 +340,17 @@
             int keyLength, CK_ATTRIBUTE[] attributes) {
         switch (algorithm) {
             case "RSA":
-                return new P11RSAPublicKey
-                    (session, keyID, algorithm, keyLength, attributes);
+                return new P11RSAPublicKey(session, keyID, algorithm,
+                        keyLength, attributes);
             case "DSA":
-                return new P11DSAPublicKey
-                    (session, keyID, algorithm, keyLength, attributes);
+                return new P11DSAPublicKey(session, keyID, algorithm,
+                        keyLength, attributes);
             case "DH":
-                return new P11DHPublicKey
-                    (session, keyID, algorithm, keyLength, attributes);
+                return new P11DHPublicKey(session, keyID, algorithm,
+                        keyLength, attributes);
             case "EC":
-                return new P11ECPublicKey
-                    (session, keyID, algorithm, keyLength, attributes);
+                return new P11ECPublicKey(session, keyID, algorithm,
+                        keyLength, attributes);
             default:
                 throw new ProviderException
                     ("Unknown public key algorithm " + algorithm);
@@ -355,21 +387,21 @@
                         crtKey = false;
                     }
                     if (crtKey) {
-                        return new P11RSAPrivateKey
-                                (session, keyID, algorithm, keyLength, attributes);
+                        return new P11RSAPrivateKey(session, keyID, algorithm,
+                                keyLength, attributes);
                     } else {
-                        return new P11RSAPrivateNonCRTKey
-                                (session, keyID, algorithm, keyLength, attributes);
+                        return new P11RSAPrivateNonCRTKey(session, keyID,
+                                algorithm, keyLength, attributes);
                     }
                 case "DSA":
-                    return new P11DSAPrivateKey
-                            (session, keyID, algorithm, keyLength, attributes);
+                    return new P11DSAPrivateKey(session, keyID, algorithm,
+                            keyLength, attributes);
                 case "DH":
-                    return new P11DHPrivateKey
-                            (session, keyID, algorithm, keyLength, attributes);
+                    return new P11DHPrivateKey(session, keyID, algorithm,
+                            keyLength, attributes);
                 case "EC":
-                    return new P11ECPrivateKey
-                            (session, keyID, algorithm, keyLength, attributes);
+                    return new P11ECPrivateKey(session, keyID, algorithm,
+                            keyLength, attributes);
                 default:
                     throw new ProviderException
                             ("Unknown private key algorithm " + algorithm);
@@ -423,17 +455,19 @@
                     b = encoded;
                     if (b == null) {
                         Session tempSession = null;
+                        long keyID = this.getKeyID();
                         try {
                             tempSession = token.getOpSession();
                             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
                                 new CK_ATTRIBUTE(CKA_VALUE),
                             };
                             token.p11.C_GetAttributeValue
-                                (tempSession.id(), keyID, attributes);
+                                    (tempSession.id(), keyID, attributes);
                             b = attributes[0].getByteArray();
                         } catch (PKCS11Exception e) {
                             throw new ProviderException(e);
                         } finally {
+                            this.releaseKeyID();
                             token.releaseSession(tempSession);
                         }
                         encoded = b;
@@ -1091,6 +1125,153 @@
     }
 }
 
+final class NativeKeyHolder {
+
+    private static long nativeKeyWrapperKeyID = 0;
+    private static CK_MECHANISM nativeKeyWrapperMechanism = null;
+
+    private final P11Key p11Key;
+    private final byte[] nativeKeyInfo;
+
+    // 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;
+
+    NativeKeyHolder(P11Key p11Key, long keyID, Session keySession,
+            boolean extractKeyInfo, boolean isTokenObject) {
+        this.p11Key = p11Key;
+        this.keyID = keyID;
+        this.refCount = -1;
+        byte[] ki = null;
+        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) {
+                        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);
+                            }
+                        }
+                    }
+                    Session opSession = null;
+                    try {
+                        opSession = token.getOpSession();
+                        ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(),
+                            keyID, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
+                    } catch (PKCS11Exception e) {
+                        // best effort
+                    } finally {
+                        token.releaseSession(opSession);
+                    }
+                } catch (PKCS11Exception e) {
+                    // best effort
+                }
+            }
+        }
+        this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki);
+    }
+
+    long getKeyID() throws ProviderException {
+        if (this.nativeKeyInfo != null) {
+            synchronized(this.nativeKeyInfo) {
+                if (this.refCount == -1) {
+                    this.refCount = 0;
+                }
+                int cnt = (this.refCount)++;
+                if (keyID == 0) {
+                    if (cnt != 0) {
+                        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);
+                    } catch (PKCS11Exception e) {
+                        this.refCount--;
+                        throw new ProviderException("Error recreating native key", e);
+                    } finally {
+                        token.releaseSession(session);
+                    }
+                } else {
+                    if (cnt < 0) {
+                        throw new RuntimeException("ERROR: negative refCount");
+                    }
+                }
+            }
+        }
+        return keyID;
+    }
+
+    void releaseKeyID() {
+        if (this.nativeKeyInfo != null) {
+            synchronized(this.nativeKeyInfo) {
+                if (this.refCount == -1) {
+                    throw new RuntimeException("Error: miss match getKeyID call");
+                }
+                int cnt = --(this.refCount);
+                if (cnt == 0) {
+                    // destroy
+                    if (this.keyID == 0) {
+                        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();
+                } else {
+                    if (cnt < 0) {
+                        // should never happen as we start count at 1 and pair get/release calls
+                        throw new RuntimeException("wrong refCount value: " + cnt);
+                    }
+                }
+            }
+        }
+    }
+}
+
 /*
  * NOTE: Must use PhantomReference here and not WeakReference
  * otherwise the key maybe cleared before other objects which
@@ -1115,35 +1296,42 @@
         }
     }
 
-    // handle to the native key
-    private long keyID;
-    private Session session;
+    // handle to the native key and the session it is generated under
+    private final long keyID;
+    private final Session session;
 
-    SessionKeyRef(P11Key key , long keyID, Session session) {
-        super(key, refQueue);
+    SessionKeyRef(P11Key p11Key, long keyID, 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();
+
         refList.add(this);
         // TBD: run at some interval and not every time?
         drainRefQueueBounded();
     }
 
-    private void dispose() {
-        refList.remove(this);
-        if (session.token.isValid()) {
-            Session newSession = null;
+    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 {
-                newSession = session.token.getOpSession();
-                session.token.p11.C_DestroyObject(newSession.id(), keyID);
+                s = token.getOpSession();
+                token.p11.C_DestroyObject(s.id(), keyID);
             } catch (PKCS11Exception e) {
-                // ignore
+                // best effort
             } finally {
-                this.clear();
-                session.token.releaseSession(newSession);
-                session.removeObject();
+                token.releaseSession(s);
             }
         }
+        refList.remove(this);
+        this.clear();
+        session.removeObject();
+        return null;
     }
 
     public int compareTo(SessionKeyRef other) {
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
index 2ae655a..a6db3c8 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -201,6 +201,7 @@
             throw new IllegalStateException("Not initialized correctly");
         }
         Session session = null;
+        long privKeyID = privateKey.getKeyID();
         try {
             session = token.getOpSession();
             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -210,8 +211,9 @@
             attributes = token.getAttributes
                 (O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
             long keyID = token.p11.C_DeriveKey(session.id(),
-                new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
-                attributes);
+                    new CK_MECHANISM(mechanism, publicValue), privKeyID,
+                    attributes);
+
             attributes = new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE)
             };
@@ -237,6 +239,7 @@
         } catch (PKCS11Exception e) {
             throw new ProviderException("Could not derive key", e);
         } finally {
+            privateKey.releaseKeyID();
             publicValue = null;
             token.releaseSession(session);
         }
@@ -325,6 +328,7 @@
         }
         long keyType = CKK_GENERIC_SECRET;
         Session session = null;
+        long privKeyID = privateKey.getKeyID();
         try {
             session = token.getObjSession();
             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -334,8 +338,8 @@
             attributes = token.getAttributes
                 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
             long keyID = token.p11.C_DeriveKey(session.id(),
-                new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
-                attributes);
+                    new CK_MECHANISM(mechanism, publicValue), privKeyID,
+                    attributes);
             CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE_LEN),
             };
@@ -359,6 +363,7 @@
         } catch (PKCS11Exception e) {
             throw new InvalidKeyException("Could not derive key", e);
         } finally {
+            privateKey.releaseKeyID();
             publicValue = null;
             token.releaseSession(session);
         }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
index e5b8fa8..aee9542 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1486,6 +1486,7 @@
         }
     }
 
+    // retrieves the native key handle and either update it directly or make a copy
     private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
                 throws PKCS11Exception {
 
@@ -1493,23 +1494,22 @@
         // if session key, convert to token key.
 
         Session session = null;
+        long keyID = key.getKeyID();
         try {
             session = token.getOpSession();
             if (key.tokenObject == true) {
-
                 // token key - set new CKA_ID
 
                 CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
                                 new CK_ATTRIBUTE(CKA_ID, alias) };
                 token.p11.C_SetAttributeValue
-                                (session.id(), key.keyID, attrs);
+                                (session.id(), keyID, attrs);
                 if (debug != null) {
                     debug.println("updateP11Pkey set new alias [" +
                                 alias +
                                 "] for key entry");
                 }
             } else {
-
                 // session key - convert to token key and set CKA_ID
 
                 CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
@@ -1519,7 +1519,8 @@
                 if (attribute != null) {
                     attrs = addAttribute(attrs, attribute);
                 }
-                token.p11.C_CopyObject(session.id(), key.keyID, attrs);
+                // creates a new token key with the desired CKA_ID
+                token.p11.C_CopyObject(session.id(), keyID, attrs);
                 if (debug != null) {
                     debug.println("updateP11Pkey copied private session key " +
                                 "for [" +
@@ -1529,6 +1530,7 @@
             }
         } finally {
             token.releaseSession(session);
+            key.releaseKeyID();
         }
     }
 
@@ -1895,10 +1897,12 @@
             return attrs;
         }
         String alg = privateKey.getAlgorithm();
-        if (id && alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
+        if (alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
+            if (id) {
+                BigInteger n = ((RSAPublicKey)publicKey).getModulus();
+                attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
+            }
             // CKA_NETSCAPE_DB not needed for RSA public keys
-            BigInteger n = ((RSAPublicKey)publicKey).getModulus();
-            attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
         } else if (alg.equals("DSA") && (publicKey instanceof DSAPublicKey)) {
             BigInteger y = ((DSAPublicKey)publicKey).getY();
             if (id) {
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Mac.java b/jdk/src/share/classes/sun/security/pkcs11/P11Mac.java
index 2b0cbbc..56d0b1c 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Mac.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Mac.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@
 
 package sun.security.pkcs11;
 
-import java.util.*;
 import java.nio.ByteBuffer;
 
 import java.security.*;
@@ -54,27 +53,12 @@
  */
 final class P11Mac extends MacSpi {
 
-    /* unitialized, all fields except session have arbitrary values */
-    private final static int S_UNINIT   = 1;
-
-    /* session initialized, no data processed yet */
-    private final static int S_RESET    = 2;
-
-    /* session initialized, data processed */
-    private final static int S_UPDATE   = 3;
-
-    /* transitional state after doFinal() before we go to S_UNINIT */
-    private final static int S_DOFINAL  = 4;
-
     // token instance
     private final Token token;
 
     // algorithm name
     private final String algorithm;
 
-    // mechanism id
-    private final long mechanism;
-
     // mechanism object
     private final CK_MECHANISM ckMechanism;
 
@@ -87,8 +71,8 @@
     // associated session, if any
     private Session session;
 
-    // state, one of S_* above
-    private int state;
+    // initialization status
+    private boolean initialized;
 
     // one byte buffer for the update(byte) method, initialized on demand
     private byte[] oneByte;
@@ -98,7 +82,6 @@
         super();
         this.token = token;
         this.algorithm = algorithm;
-        this.mechanism = mechanism;
         Long params = null;
         switch ((int)mechanism) {
         case (int)CKM_MD5_HMAC:
@@ -131,47 +114,65 @@
             throw new ProviderException("Unknown mechanism: " + mechanism);
         }
         ckMechanism = new CK_MECHANISM(mechanism, params);
-        state = S_UNINIT;
-        initialize();
     }
 
-    private void ensureInitialized() throws PKCS11Exception {
-        token.ensureValid();
-        if (state == S_UNINIT) {
-            initialize();
+    // reset the states to the pre-initialized values
+    private void reset(boolean doCancel) {
+        if (!initialized) {
+            return;
+        }
+        initialized = false;
+        try {
+            if (session == null) {
+                return;
+            }
+            if (doCancel && token.explicitCancel) {
+                cancelOperation();
+            }
+        } finally {
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
         }
     }
 
     private void cancelOperation() {
         token.ensureValid();
-        if (state == S_UNINIT) {
+        if (session.hasObjects() == false) {
+            session = token.killSession(session);
             return;
+        } else {
+            try {
+                token.p11.C_SignFinal(session.id(), 0);
+            } catch (PKCS11Exception e) {
+                throw new ProviderException("Cancel failed", e);
+            }
         }
-        state = S_UNINIT;
-        if ((session == null) || (token.explicitCancel == false)) {
-            return;
-        }
-        try {
-            token.p11.C_SignFinal(session.id(), 0);
-        } catch (PKCS11Exception e) {
-            throw new ProviderException("Cancel failed", e);
+    }
+
+    private void ensureInitialized() throws PKCS11Exception {
+        if (!initialized) {
+            initialize();
         }
     }
 
     private void initialize() throws PKCS11Exception {
-        if (state == S_RESET) {
-            return;
+        if (p11Key == null) {
+            throw new ProviderException(
+                    "Operation cannot be performed without calling engineInit first");
         }
-        if (session == null) {
-            session = token.getOpSession();
+        token.ensureValid();
+        long p11KeyID = p11Key.getKeyID();
+        try {
+            if (session == null) {
+                session = token.getOpSession();
+            }
+            token.p11.C_SignInit(session.id(), ckMechanism, p11KeyID);
+        } catch (PKCS11Exception e) {
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
+            throw e;
         }
-        if (p11Key != null) {
-            token.p11.C_SignInit
-                (session.id(), ckMechanism, p11Key.keyID);
-            state = S_RESET;
-        } else {
-            state = S_UNINIT;
-        }
+        initialized = true;
     }
 
     // see JCE spec
@@ -181,18 +182,7 @@
 
     // see JCE spec
     protected void engineReset() {
-        // the framework insists on calling reset() after doFinal(),
-        // but we prefer to take care of reinitialization ourselves
-        if (state == S_DOFINAL) {
-            state = S_UNINIT;
-            return;
-        }
-        cancelOperation();
-        try {
-            initialize();
-        } catch (PKCS11Exception e) {
-            throw new ProviderException("reset() failed, ", e);
-        }
+        reset(true);
     }
 
     // see JCE spec
@@ -202,7 +192,7 @@
             throw new InvalidAlgorithmParameterException
                 ("Parameters not supported");
         }
-        cancelOperation();
+        reset(true);
         p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
         try {
             initialize();
@@ -215,13 +205,12 @@
     protected byte[] engineDoFinal() {
         try {
             ensureInitialized();
-            byte[] mac = token.p11.C_SignFinal(session.id(), 0);
-            state = S_DOFINAL;
-            return mac;
+            return token.p11.C_SignFinal(session.id(), 0);
         } catch (PKCS11Exception e) {
+            reset(true);
             throw new ProviderException("doFinal() failed", e);
         } finally {
-            session = token.releaseSession(session);
+            reset(false);
         }
     }
 
@@ -239,7 +228,6 @@
         try {
             ensureInitialized();
             token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
-            state = S_UPDATE;
         } catch (PKCS11Exception e) {
             throw new ProviderException("update() failed", e);
         }
@@ -261,7 +249,6 @@
             int ofs = byteBuffer.position();
             token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len);
             byteBuffer.position(ofs + len);
-            state = S_UPDATE;
         } catch (PKCS11Exception e) {
             throw new ProviderException("update() failed", e);
         }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
index 7b2b98a..2584399 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -195,7 +195,7 @@
     }
 
     private void implInit(int opmode, Key key) throws InvalidKeyException {
-        cancelOperation();
+        reset(true);
         p11Key = P11KeyFactory.convertKey(token, key, algorithm);
         boolean encrypt;
         if (opmode == Cipher.ENCRYPT_MODE) {
@@ -240,80 +240,105 @@
         }
     }
 
-    private void cancelOperation() {
-        token.ensureValid();
-        if (initialized == false) {
+    // reset the states to the pre-initialized values
+    private void reset(boolean doCancel) {
+        if (!initialized) {
             return;
         }
         initialized = false;
-        if ((session == null) || (token.explicitCancel == false)) {
-            return;
+        try {
+            if (session == null) {
+                return;
+            }
+            if (doCancel && token.explicitCancel) {
+                cancelOperation();
+            }
+        } finally {
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
         }
+    }
+
+    // should only called by reset as this method does not update other
+    // state variables such as "initialized"
+    private void cancelOperation() {
+        token.ensureValid();
         if (session.hasObjects() == false) {
             session = token.killSession(session);
             return;
-        }
-        try {
-            PKCS11 p11 = token.p11;
-            int inLen = maxInputSize;
-            int outLen = buffer.length;
-            switch (mode) {
-            case MODE_ENCRYPT:
-                p11.C_Encrypt
-                        (session.id(), buffer, 0, inLen, buffer, 0, outLen);
-                break;
-            case MODE_DECRYPT:
-                p11.C_Decrypt
-                        (session.id(), buffer, 0, inLen, buffer, 0, outLen);
-                break;
-            case MODE_SIGN:
-                byte[] tmpBuffer = new byte[maxInputSize];
-                p11.C_Sign
-                        (session.id(), tmpBuffer);
-                break;
-            case MODE_VERIFY:
-                p11.C_VerifyRecover
-                        (session.id(), buffer, 0, inLen, buffer, 0, outLen);
-                break;
-            default:
-                throw new ProviderException("internal error");
+        } else {
+            try {
+                PKCS11 p11 = token.p11;
+                int inLen = maxInputSize;
+                int outLen = buffer.length;
+                long sessId = session.id();
+                switch (mode) {
+                case MODE_ENCRYPT:
+                    p11.C_Encrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
+                    break;
+                case MODE_DECRYPT:
+                    p11.C_Decrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
+                    break;
+                case MODE_SIGN:
+                    byte[] tmpBuffer = new byte[maxInputSize];
+                    p11.C_Sign(sessId, tmpBuffer);
+                    break;
+                case MODE_VERIFY:
+                    p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
+                            0, outLen);
+                    break;
+                default:
+                    throw new ProviderException("internal error");
+                }
+            } catch (PKCS11Exception e) {
+                // XXX ensure this always works, ignore error
             }
-        } catch (PKCS11Exception e) {
-            // XXX ensure this always works, ignore error
         }
     }
 
     private void ensureInitialized() throws PKCS11Exception {
         token.ensureValid();
-        if (initialized == false) {
+        if (!initialized) {
             initialize();
         }
     }
 
     private void initialize() throws PKCS11Exception {
-        if (session == null) {
-            session = token.getOpSession();
+        if (p11Key == null) {
+            throw new ProviderException(
+                    "Operation cannot be performed without " +
+                    "calling engineInit first");
         }
-        PKCS11 p11 = token.p11;
-        CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
-        switch (mode) {
-        case MODE_ENCRYPT:
-            p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID);
-            break;
-        case MODE_DECRYPT:
-            p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID);
-            break;
-        case MODE_SIGN:
-            p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID);
-            break;
-        case MODE_VERIFY:
-            p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID);
-            break;
-        default:
-            throw new AssertionError("internal error");
+        long keyID = p11Key.getKeyID();
+        try {
+            if (session == null) {
+                session = token.getOpSession();
+            }
+            PKCS11 p11 = token.p11;
+            CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
+            switch (mode) {
+            case MODE_ENCRYPT:
+                p11.C_EncryptInit(session.id(), ckMechanism, keyID);
+                break;
+            case MODE_DECRYPT:
+                p11.C_DecryptInit(session.id(), ckMechanism, keyID);
+                break;
+            case MODE_SIGN:
+                p11.C_SignInit(session.id(), ckMechanism, keyID);
+                break;
+            case MODE_VERIFY:
+                p11.C_VerifyRecoverInit(session.id(), ckMechanism, keyID);
+                break;
+            default:
+                throw new AssertionError("internal error");
+            }
+            bufOfs = 0;
+            initialized = true;
+        } catch (PKCS11Exception e) {
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
+            throw e;
         }
-        bufOfs = 0;
-        initialized = true;
     }
 
     private void implUpdate(byte[] in, int inOfs, int inLen) {
@@ -376,8 +401,7 @@
             throw (BadPaddingException)new BadPaddingException
                 ("doFinal() failed").initCause(e);
         } finally {
-            initialized = false;
-            session = token.releaseSession(session);
+            reset(false);
         }
     }
 
@@ -451,13 +475,17 @@
             }
         }
         Session s = null;
+        long p11KeyID = p11Key.getKeyID();
+        long sKeyID = sKey.getKeyID();
         try {
             s = token.getOpSession();
             return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
-                p11Key.keyID, sKey.keyID);
+                    p11KeyID, sKeyID);
         } catch (PKCS11Exception e) {
             throw new InvalidKeyException("wrap() failed", e);
         } finally {
+            p11Key.releaseKeyID();
+            sKey.releaseKeyID();
             token.releaseSession(s);
         }
     }
@@ -516,6 +544,7 @@
         } else {
             Session s = null;
             SecretKey secretKey = null;
+            long p11KeyID = p11Key.getKeyID();
             try {
                 try {
                     s = token.getObjSession();
@@ -526,9 +555,10 @@
                         };
                     attributes = token.getAttributes(
                             O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
+
                     long keyID = token.p11.C_UnwrapKey(s.id(),
-                            new CK_MECHANISM(mechanism), p11Key.keyID,
-                            wrappedKey, attributes);
+                                    new CK_MECHANISM(mechanism), p11KeyID,
+                                    wrappedKey, attributes);
                     secretKey = P11Key.secretKey(s, keyID,
                             algorithm, 48 << 3, attributes);
                 } catch (PKCS11Exception e) {
@@ -552,6 +582,7 @@
 
                 return secretKey;
             } finally {
+                p11Key.releaseKeyID();
                 token.releaseSession(s);
             }
         }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
index 6c36de1..0fc06a7 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
@@ -262,7 +262,12 @@
                 new CK_ATTRIBUTE(CKA_MODULUS),
                 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
             KeySpec spec = new RSAPublicKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger()
@@ -288,7 +293,13 @@
                 new CK_ATTRIBUTE(CKA_EXPONENT_2),
                 new CK_ATTRIBUTE(CKA_COEFFICIENT),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
+
             KeySpec spec = new RSAPrivateCrtKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger(),
@@ -306,7 +317,13 @@
                 new CK_ATTRIBUTE(CKA_MODULUS),
                 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
             };
-            token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+            long keyID = key.getKeyID();
+            try {
+                token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+            } finally {
+                key.releaseKeyID();
+            }
+
             KeySpec spec = new RSAPrivateKeySpec(
                 attributes[0].getBigInteger(),
                 attributes[1].getBigInteger()
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
index f4306b3..e6ed887 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,20 +146,24 @@
             P11Key p11Key = (P11Key)key;
             if (p11Key.token == token) {
                 if (extraAttrs != null) {
+                    P11Key newP11Key = null;
                     Session session = null;
+                    long p11KeyID = p11Key.getKeyID();
                     try {
                         session = token.getObjSession();
                         long newKeyID = token.p11.C_CopyObject(session.id(),
-                                p11Key.keyID, extraAttrs);
-                        p11Key = (P11Key) (P11Key.secretKey(session,
+                            p11KeyID, extraAttrs);
+                        newP11Key = (P11Key) (P11Key.secretKey(session,
                                 newKeyID, p11Key.algorithm, p11Key.keyLength,
                                 extraAttrs));
                     } catch (PKCS11Exception p11e) {
                         throw new InvalidKeyException
                                 ("Cannot duplicate the PKCS11 key", p11e);
                     } finally {
+                        p11Key.releaseKeyID();
                         token.releaseSession(session);
                     }
+                    p11Key = newP11Key;
                 }
                 return p11Key;
             }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
index adfc633..af152d8 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -237,27 +237,33 @@
         this.md = md;
     }
 
-    private void ensureInitialized() {
-        token.ensureValid();
-        if (initialized == false) {
-            initialize();
+    // reset the states to the pre-initialized values
+    private void reset(boolean doCancel) {
+
+        if (!initialized) {
+            return;
+        }
+        initialized = false;
+        try {
+            if (session == null) {
+                return;
+            }
+            if (doCancel && token.explicitCancel) {
+                cancelOperation();
+            }
+        } finally {
+            p11Key.releaseKeyID();
+            session = token.releaseSession(session);
         }
     }
 
     private void cancelOperation() {
+
         token.ensureValid();
-        if (initialized == false) {
-            return;
-        }
-        initialized = false;
-        if ((session == null) || (token.explicitCancel == false)) {
-            return;
-        }
         if (session.hasObjects() == false) {
             session = token.killSession(session);
             return;
-        }
-        try {
+        } else {
             // "cancel" operation by finishing it
             // XXX make sure all this always works correctly
             if (mode == M_SIGN) {
@@ -277,8 +283,8 @@
                     throw new ProviderException("cancel failed", e);
                 }
             } else { // M_VERIFY
+                byte[] signature;
                 try {
-                    byte[] signature;
                     if (keyAlgorithm.equals("DSA")) {
                         signature = new byte[40];
                     } else {
@@ -296,31 +302,48 @@
                         token.p11.C_Verify(session.id(), digest, signature);
                     }
                 } catch (PKCS11Exception e) {
-                    // will fail since the signature is incorrect
-                    // XXX check error code
+                    long errorCode = e.getErrorCode();
+                    if ((errorCode == CKR_SIGNATURE_INVALID) ||
+                        (errorCode == CKR_SIGNATURE_LEN_RANGE)) {
+                        // expected since signature is incorrect
+                        return;
+                    }
+                    throw new ProviderException("cancel failed", e);
                 }
             }
-        } finally {
-            session = token.releaseSession(session);
+        }
+    }
+
+    private void ensureInitialized() {
+
+        if (!initialized) {
+            initialize();
         }
     }
 
     // assumes current state is initialized == false
     private void initialize() {
+
+        if (p11Key == null) {
+            throw new ProviderException(
+                    "Operation cannot be performed without " +
+                    "calling engineInit first");
+        }
+        long keyID = p11Key.getKeyID();
         try {
+            token.ensureValid();
             if (session == null) {
                 session = token.getOpSession();
             }
             if (mode == M_SIGN) {
                 token.p11.C_SignInit(session.id(),
-                        new CK_MECHANISM(mechanism), p11Key.keyID);
+                        new CK_MECHANISM(mechanism), keyID);
             } else {
                 token.p11.C_VerifyInit(session.id(),
-                        new CK_MECHANISM(mechanism), p11Key.keyID);
+                        new CK_MECHANISM(mechanism), keyID);
             }
-            initialized = true;
         } catch (PKCS11Exception e) {
-            // release session when initialization failed
+            p11Key.releaseKeyID();
             session = token.releaseSession(session);
             throw new ProviderException("Initialization failed", e);
         }
@@ -330,6 +353,7 @@
                 md.reset();
             }
         }
+        initialized = true;
     }
 
     private void checkKeySize(String keyAlgo, Key key)
@@ -412,6 +436,7 @@
     // see JCA spec
     protected void engineInitVerify(PublicKey publicKey)
             throws InvalidKeyException {
+
         if (publicKey == null) {
             throw new InvalidKeyException("Key must not be null");
         }
@@ -419,7 +444,7 @@
         if (publicKey != p11Key) {
             checkKeySize(keyAlgorithm, publicKey);
         }
-        cancelOperation();
+        reset(true);
         mode = M_VERIFY;
         p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
         initialize();
@@ -428,6 +453,7 @@
     // see JCA spec
     protected void engineInitSign(PrivateKey privateKey)
             throws InvalidKeyException {
+
         if (privateKey == null) {
             throw new InvalidKeyException("Key must not be null");
         }
@@ -435,7 +461,7 @@
         if (privateKey != p11Key) {
             checkKeySize(keyAlgorithm, privateKey);
         }
-        cancelOperation();
+        reset(true);
         mode = M_SIGN;
         p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
         initialize();
@@ -468,6 +494,7 @@
     // see JCA spec
     protected void engineUpdate(byte[] b, int ofs, int len)
             throws SignatureException {
+
         ensureInitialized();
         if (len == 0) {
             return;
@@ -486,8 +513,7 @@
                 }
                 bytesProcessed += len;
             } catch (PKCS11Exception e) {
-                initialized = false;
-                session = token.releaseSession(session);
+                reset(false);
                 throw new ProviderException(e);
             }
             break;
@@ -510,6 +536,7 @@
 
     // see JCA spec
     protected void engineUpdate(ByteBuffer byteBuffer) {
+
         ensureInitialized();
         int len = byteBuffer.remaining();
         if (len <= 0) {
@@ -535,8 +562,7 @@
                 bytesProcessed += len;
                 byteBuffer.position(ofs + len);
             } catch (PKCS11Exception e) {
-                initialized = false;
-                session = token.releaseSession(session);
+                reset(false);
                 throw new ProviderException("Update failed", e);
             }
             break;
@@ -553,13 +579,16 @@
             bytesProcessed += len;
             break;
         default:
+            reset(false);
             throw new ProviderException("Internal error");
         }
     }
 
     // see JCA spec
     protected byte[] engineSign() throws SignatureException {
+
         ensureInitialized();
+        boolean doCancel = true;
         try {
             byte[] signature;
             if (type == T_UPDATE) {
@@ -596,22 +625,25 @@
                     signature = token.p11.C_Sign(session.id(), data);
                 }
             }
+            doCancel = false;
+
             if (keyAlgorithm.equals("RSA") == false) {
                 return dsaToASN1(signature);
             } else {
                 return signature;
             }
         } catch (PKCS11Exception e) {
+            doCancel = false;
             throw new ProviderException(e);
         } finally {
-            initialized = false;
-            session = token.releaseSession(session);
+            reset(doCancel);
         }
     }
 
     // see JCA spec
     protected boolean engineVerify(byte[] signature) throws SignatureException {
         ensureInitialized();
+        boolean doCancel = true;
         try {
             if (keyAlgorithm.equals("DSA")) {
                 signature = asn1ToDSA(signature);
@@ -651,8 +683,10 @@
                     token.p11.C_Verify(session.id(), data, signature);
                 }
             }
+            doCancel = false;
             return true;
         } catch (PKCS11Exception e) {
+            doCancel = false;
             long errorCode = e.getErrorCode();
             if (errorCode == CKR_SIGNATURE_INVALID) {
                 return false;
@@ -667,10 +701,7 @@
             }
             throw new ProviderException(e);
         } finally {
-            // XXX we should not release the session if we abort above
-            // before calling C_Verify
-            initialized = false;
-            session = token.releaseSession(session);
+            reset(doCancel);
         }
     }
 
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java b/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
index 7cc1ec8..f684827 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
@@ -173,9 +173,13 @@
             }
             attributes = token.getAttributes
                 (O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
-            // the returned keyID is a dummy, ignore
-            long keyID = token.p11.C_DeriveKey(session.id(),
-                    ckMechanism, p11Key.keyID, attributes);
+            long p11KeyID = p11Key.getKeyID();
+            try {
+                token.p11.C_DeriveKey(session.id(),
+                        ckMechanism, p11KeyID, attributes);
+            } finally {
+                p11Key.releaseKeyID();
+            }
 
             CK_SSL3_KEY_MAT_OUT out = null;
             if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java b/jdk/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
index 6e4970d..aae6885 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
@@ -147,12 +147,13 @@
         }
 
         Session session = null;
+        long p11KeyID = p11Key.getKeyID();
         try {
             session = token.getObjSession();
             CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE,
                 CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
             long keyID = token.p11.C_DeriveKey(session.id(),
-                    ckMechanism, p11Key.keyID, attributes);
+                    ckMechanism, p11KeyID, attributes);
             int major, minor;
             if (ckVersion == null) {
                 major = -1;
@@ -161,12 +162,12 @@
                 major = ckVersion.major;
                 minor = ckVersion.minor;
             }
-            SecretKey key = P11Key.masterSecretKey(session, keyID,
+            return P11Key.masterSecretKey(session, keyID,
                 "TlsMasterSecret", 48 << 3, attributes, major, minor);
-            return key;
         } catch (Exception e) {
             throw new ProviderException("Could not generate key", e);
         } finally {
+            p11Key.releaseKeyID();
             token.releaseSession(session);
         }
     }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java b/jdk/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
index 4a143d7..d3ad925 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
@@ -143,34 +143,36 @@
                         Functions.getHashMechId(spec.getPRFHashAlg()),
                         spec.getOutputLength(), ulServerOrClient);
                 Session session = null;
+                long keyID = p11Key.getKeyID();
                 try {
                     session = token.getOpSession();
                     token.p11.C_SignInit(session.id(),
-                            new CK_MECHANISM(mechanism, params), p11Key.keyID);
+                            new CK_MECHANISM(mechanism, params), keyID);
                     token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
                     byte[] out = token.p11.C_SignFinal
                             (session.id(), spec.getOutputLength());
-                    k = new SecretKeySpec(out, "TlsPrf");
+                    return new SecretKeySpec(out, "TlsPrf");
                 } catch (PKCS11Exception e) {
                     throw new ProviderException("Could not calculate PRF", e);
                 } finally {
+                    p11Key.releaseKeyID();
                     token.releaseSession(session);
                 }
             } else {
                 throw new ProviderException("Only Finished message authentication code"+
                         " generation supported for TLS 1.2.");
             }
-            return k;
         }
 
         byte[] label = P11Util.getBytesUTF8(spec.getLabel());
 
         if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {
             Session session = null;
+            long keyID = p11Key.getKeyID();
             try {
                 session = token.getOpSession();
                 token.p11.C_SignInit
-                    (session.id(), new CK_MECHANISM(mechanism), p11Key.keyID);
+                        (session.id(), new CK_MECHANISM(mechanism), keyID);
                 token.p11.C_SignUpdate(session.id(), 0, label, 0, label.length);
                 token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
                 byte[] out = token.p11.C_SignFinal
@@ -179,6 +181,7 @@
             } catch (PKCS11Exception e) {
                 throw new ProviderException("Could not calculate PRF", e);
             } finally {
+                p11Key.releaseKeyID();
                 token.releaseSession(session);
             }
         }
@@ -189,15 +192,16 @@
         CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);
 
         Session session = null;
+        long keyID = p11Key.getKeyID();
         try {
             session = token.getOpSession();
-            long keyID = token.p11.C_DeriveKey(session.id(),
-                new CK_MECHANISM(mechanism, params), p11Key.keyID, null);
-            // ignore keyID, returned PRF bytes are in 'out'
+            token.p11.C_DeriveKey(session.id(),
+                new CK_MECHANISM(mechanism, params), keyID, null);
             return new SecretKeySpec(out, "TlsPrf");
         } catch (PKCS11Exception e) {
             throw new ProviderException("Could not calculate PRF", e);
         } finally {
+            p11Key.releaseKeyID();
             token.releaseSession(session);
         }
     }
diff --git a/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
index c5799b4..50ee726 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -1288,6 +1288,46 @@
  ******************************************************************************/
 
     /**
+     * getNativeKeyInfo gets the key object attributes and values as an opaque
+     * byte array to be used in createNativeKey method.
+     * (Key management)
+     *
+     * @param hSession the session's handle
+     * @param hKey key's handle
+     * @param hWrappingKey key handle for wrapping the extracted sensitive keys.
+     *        -1 if not used.
+     * @param pWrappingMech mechanism for wrapping the extracted sensitive keys
+     * @return an opaque byte array containing the key object attributes
+     *         and values
+     * @exception PKCS11Exception If an internal PKCS#11 function returns other
+     *            value than CKR_OK.
+     * @preconditions
+     * @postconditions
+     */
+    public native byte[] getNativeKeyInfo(long hSession, long hKey,
+            long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
+
+    /**
+     * createNativeKey creates a key object with attributes and values
+     * specified by parameter as an opaque byte array.
+     * (Key management)
+     *
+     * @param hSession the session's handle
+     * @param keyInfo opaque byte array containing key object attributes
+     *        and values
+     * @param hWrappingKey key handle for unwrapping the extracted sensitive keys.
+     *        -1 if not used.
+     * @param pWrappingMech mechanism for unwrapping the extracted sensitive keys
+     * @return key object handle
+     * @exception PKCS11Exception If an internal PKCS#11 function returns other
+     *            value than CKR_OK.
+     * @preconditions
+     * @postconditions
+     */
+    public native long createNativeKey(long hSession, byte[] keyInfo,
+            long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
+
+    /**
      * C_GenerateKey generates a secret key, creating a new key
      * object.
      * (Key management)
diff --git a/jdk/src/share/lib/security/java.policy b/jdk/src/share/lib/security/java.policy
index 120694d..59d99a9 100644
--- a/jdk/src/share/lib/security/java.policy
+++ b/jdk/src/share/lib/security/java.policy
@@ -45,5 +45,7 @@
         permission java.util.PropertyPermission "java.vm.version", "read";
         permission java.util.PropertyPermission "java.vm.vendor", "read";
         permission java.util.PropertyPermission "java.vm.name", "read";
+
+        permission java.util.PropertyPermission "sun.security.pkcs11.disableKeyExtraction", "read";
 };
 
diff --git a/jdk/src/share/native/common/jni_util.c b/jdk/src/share/native/common/jni_util.c
index 87cd00e..a414770 100644
--- a/jdk/src/share/native/common/jni_util.c
+++ b/jdk/src/share/native/common/jni_util.c
@@ -27,8 +27,7 @@
 #include <string.h>
 
 #include "jvm.h"
-#include "jni.h"
-#include "jni_util.h"
+#include "io_util.h"
 
 /* Due to a bug in the win32 C runtime library strings
  * such as "z:" need to be appended with a "." so we
@@ -683,10 +682,14 @@
 {
     jstring propname = 0;
     jstring enc = 0;
+    jclass strClazz = NULL;
 
     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
         return;
 
+    strClazz = JNU_ClassString(env);
+    CHECK_NULL(strClazz);
+
     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
     if (propname) {
         jboolean exc;
@@ -740,10 +743,12 @@
     (*env)->DeleteLocalRef(env, enc);
 
     /* Initialize method-id cache */
-    String_getBytes_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+    String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
                                              "getBytes", "(Ljava/lang/String;)[B");
-    String_init_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+    CHECK_NULL(String_getBytes_ID);
+    String_init_ID = (*env)->GetMethodID(env, strClazz,
                                          "<init>", "([BLjava/lang/String;)V");
+    CHECK_NULL(String_init_ID);
 }
 
 static jboolean isJNUEncodingSupported = JNI_FALSE;
@@ -777,8 +782,10 @@
         jbyteArray hab = 0;
         int len;
 
-        if (fastEncoding == NO_ENCODING_YET)
+        if (fastEncoding == NO_ENCODING_YET) {
             initializeEncoding(env);
+            JNU_CHECK_EXCEPTION_RETURN(env, NULL);
+        }
 
         if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
             return newString8859_1(env, str);
@@ -793,9 +800,11 @@
         len = (int)strlen(str);
         hab = (*env)->NewByteArray(env, len);
         if (hab != 0) {
+            jclass strClazz = JNU_ClassString(env);
+            CHECK_NULL_RETURN(strClazz, 0);
             (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
             if (jnuEncodingSupported(env)) {
-                result = (*env)->NewObject(env, JNU_ClassString(env),
+                result = (*env)->NewObject(env, strClazz,
                                            String_init_ID, hab, jnuEncoding);
             } else {
                 /*If the encoding specified in sun.jnu.encoding is not endorsed
@@ -804,9 +813,11 @@
                   StringCoding class will pickup the iso-8859-1 as the fallback
                   converter for us.
                  */
-                jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+                jmethodID mid = (*env)->GetMethodID(env, strClazz,
                                                     "<init>", "([B)V");
-                result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
+                if (mid != NULL) {
+                    result = (*env)->NewObject(env, strClazz, mid, hab);
+                }
             }
             (*env)->DeleteLocalRef(env, hab);
             return result;
@@ -832,8 +843,10 @@
         if (isCopy)
             *isCopy = JNI_TRUE;
 
-        if (fastEncoding == NO_ENCODING_YET)
+        if (fastEncoding == NO_ENCODING_YET) {
             initializeEncoding(env);
+            JNU_CHECK_EXCEPTION_RETURN(env, 0);
+        }
 
         if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
             return getString8859_1Chars(env, jstr);
@@ -848,9 +861,14 @@
         if (jnuEncodingSupported(env)) {
             hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
         } else {
-            jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
-                                                "getBytes", "()[B");
-            hab = (*env)->CallObjectMethod(env, jstr, mid);
+            jmethodID mid;
+            jclass strClazz = JNU_ClassString(env);
+            CHECK_NULL_RETURN(strClazz, 0);
+            mid = (*env)->GetMethodID(env, strClazz,
+                                           "getBytes", "()[B");
+            if (mid != NULL) {
+                hab = (*env)->CallObjectMethod(env, jstr, mid);
+            }
         }
 
         if (!(*env)->ExceptionCheck(env)) {
@@ -899,6 +917,7 @@
         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
             return 0;
         c = (*env)->FindClass(env, "java/lang/String");
+        CHECK_NULL_RETURN(c, NULL);
         cls = (*env)->NewGlobalRef(env, c);
         (*env)->DeleteLocalRef(env, c);
     }
@@ -914,6 +933,7 @@
         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
             return 0;
         c = (*env)->FindClass(env, "java/lang/Class");
+        CHECK_NULL_RETURN(c, NULL);
         cls = (*env)->NewGlobalRef(env, c);
         (*env)->DeleteLocalRef(env, c);
     }
@@ -929,6 +949,7 @@
         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
             return 0;
         c = (*env)->FindClass(env, "java/lang/Object");
+        CHECK_NULL_RETURN(c, NULL);
         cls = (*env)->NewGlobalRef(env, c);
         (*env)->DeleteLocalRef(env, c);
     }
@@ -944,6 +965,7 @@
         if ((*env)->EnsureLocalCapacity(env, 1) < 0)
             return 0;
         c = (*env)->FindClass(env, "java/lang/Throwable");
+        CHECK_NULL_RETURN(c, NULL);
         cls = (*env)->NewGlobalRef(env, c);
         (*env)->DeleteLocalRef(env, c);
     }
@@ -993,8 +1015,11 @@
 {
     static jmethodID mid = NULL;
     if (mid == NULL) {
-        mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals",
+        jclass objClazz = JNU_ClassObject(env);
+        CHECK_NULL_RETURN(objClazz, JNI_FALSE);
+        mid = (*env)->GetMethodID(env, objClazz, "equals",
                                   "(Ljava/lang/Object;)Z");
+        CHECK_NULL_RETURN(mid, JNI_FALSE);
     }
     return (*env)->CallBooleanMethod(env, object1, mid, object2);
 }
@@ -1096,7 +1121,9 @@
     } else {
         jclass cls = (*env)->GetObjectClass(env, object);
         jstring clsName = JNU_ToString(env, cls);
-        JNU_PrintString(env, hdr, clsName);
+        if (clsName == NULL) {
+            JNU_PrintString(env, hdr, clsName);
+        }
         (*env)->DeleteLocalRef(env, cls);
         (*env)->DeleteLocalRef(env, clsName);
     }
diff --git a/jdk/src/share/native/sun/font/freetypeScaler.c b/jdk/src/share/native/sun/font/freetypeScaler.c
index 122c54b..530e941 100644
--- a/jdk/src/share/native/sun/font/freetypeScaler.c
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -402,10 +402,18 @@
     return errCode;
 }
 
-/* ftsynth.c uses (0x10000, 0x06000, 0x0, 0x10000) matrix to get oblique
-   outline.  Therefore x coordinate will change by 0x06000*y.
-   Note that y coordinate does not change. */
-#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*6/16) : 0)
+/* ftsynth.c uses (0x10000, 0x0366A, 0x0, 0x10000) matrix to get oblique
+   outline.  Therefore x coordinate will change by 0x0366A*y.
+   Note that y coordinate does not change. These values are based on
+   libfreetype version 2.9.1. */
+#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*0x366A/0x10000) : 0)
+
+/* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24
+ * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has
+ * been taken from libfreetype version 2.6 and remain valid at least up to
+ * 2.9.1. */
+#define BOLD_MODIFIER(units_per_EM, y_scale) \
+    (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0)
 
 /*
  * Class:     sun_font_FreetypeFontScaler
@@ -484,7 +492,9 @@
     /* max advance */
     mx = (jfloat) FT26Dot6ToFloat(
                      scalerInfo->face->size->metrics.max_advance +
-                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height));
+                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
+                     BOLD_MODIFIER(scalerInfo->face->units_per_EM,
+                             scalerInfo->face->size->metrics.y_scale));
     my = 0;
 
     metrics = (*env)->NewObject(env,
@@ -680,7 +690,7 @@
     UInt16 width, height;
     GlyphInfo *glyphInfo;
     int glyph_index;
-    int renderFlags = FT_LOAD_RENDER, target;
+    int renderFlags = FT_LOAD_DEFAULT, target;
     FT_GlyphSlot ftglyph;
 
     FTScalerContext* context =
diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
index 9824da2..5109cd8 100644
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
@@ -54,6 +54,444 @@
 
 #include "sun_security_pkcs11_wrapper_PKCS11.h"
 
+#ifdef P11_ENABLE_GETNATIVEKEYINFO
+
+#define CK_ATTRIBUTES_TEMPLATE_LENGTH (CK_ULONG)61U
+
+static CK_ATTRIBUTE ckpAttributesTemplate[CK_ATTRIBUTES_TEMPLATE_LENGTH] = {
+        {CKA_CLASS, 0, 0},
+        {CKA_TOKEN, 0, 0},
+        {CKA_PRIVATE, 0, 0},
+        {CKA_LABEL, 0, 0},
+        {CKA_APPLICATION, 0, 0},
+        {CKA_VALUE, 0, 0},
+        {CKA_OBJECT_ID, 0, 0},
+        {CKA_CERTIFICATE_TYPE, 0, 0},
+        {CKA_ISSUER, 0, 0},
+        {CKA_SERIAL_NUMBER, 0, 0},
+        {CKA_AC_ISSUER, 0, 0},
+        {CKA_OWNER, 0, 0},
+        {CKA_ATTR_TYPES, 0, 0},
+        {CKA_TRUSTED, 0, 0},
+        {CKA_KEY_TYPE, 0, 0},
+        {CKA_SUBJECT, 0, 0},
+        {CKA_ID, 0, 0},
+        {CKA_SENSITIVE, 0, 0},
+        {CKA_ENCRYPT, 0, 0},
+        {CKA_DECRYPT, 0, 0},
+        {CKA_WRAP, 0, 0},
+        {CKA_UNWRAP, 0, 0},
+        {CKA_SIGN, 0, 0},
+        {CKA_SIGN_RECOVER, 0, 0},
+        {CKA_VERIFY, 0, 0},
+        {CKA_VERIFY_RECOVER, 0, 0},
+        {CKA_DERIVE, 0, 0},
+        {CKA_START_DATE, 0, 0},
+        {CKA_END_DATE, 0, 0},
+        {CKA_MODULUS, 0, 0},
+        {CKA_MODULUS_BITS, 0, 0},
+        {CKA_PUBLIC_EXPONENT, 0, 0},
+        {CKA_PRIVATE_EXPONENT, 0, 0},
+        {CKA_PRIME_1, 0, 0},
+        {CKA_PRIME_2, 0, 0},
+        {CKA_EXPONENT_1, 0, 0},
+        {CKA_EXPONENT_2, 0, 0},
+        {CKA_COEFFICIENT, 0, 0},
+        {CKA_PRIME, 0, 0},
+        {CKA_SUBPRIME, 0, 0},
+        {CKA_BASE, 0, 0},
+        {CKA_PRIME_BITS, 0, 0},
+        {CKA_SUB_PRIME_BITS, 0, 0},
+        {CKA_VALUE_BITS, 0, 0},
+        {CKA_VALUE_LEN, 0, 0},
+        {CKA_EXTRACTABLE, 0, 0},
+        {CKA_LOCAL, 0, 0},
+        {CKA_NEVER_EXTRACTABLE, 0, 0},
+        {CKA_ALWAYS_SENSITIVE, 0, 0},
+        {CKA_KEY_GEN_MECHANISM, 0, 0},
+        {CKA_MODIFIABLE, 0, 0},
+        {CKA_ECDSA_PARAMS, 0, 0},
+        {CKA_EC_PARAMS, 0, 0},
+        {CKA_EC_POINT, 0, 0},
+        {CKA_SECONDARY_AUTH, 0, 0},
+        {CKA_AUTH_PIN_FLAGS, 0, 0},
+        {CKA_HW_FEATURE_TYPE, 0, 0},
+        {CKA_RESET_ON_INIT, 0, 0},
+        {CKA_HAS_RESET, 0, 0},
+        {CKA_VENDOR_DEFINED, 0, 0},
+        {CKA_NETSCAPE_DB, 0, 0},
+};
+
+/*
+ * Class:     sun_security_pkcs11_wrapper_PKCS11
+ * Method:    getNativeKeyInfo
+ * Signature: (JJJLsun/security/pkcs11/wrapper/CK_MECHANISM;)[B
+ * Parametermapping:                         *PKCS11*
+ * @param   jlong         jSessionHandle     CK_SESSION_HANDLE hSession
+ * @param   jlong         jKeyHandle         CK_OBJECT_HANDLE hObject
+ * @param   jlong         jWrappingKeyHandle CK_OBJECT_HANDLE hObject
+ * @param   jobject       jWrappingMech      CK_MECHANISM_PTR pMechanism
+ * @return  jbyteArray    jNativeKeyInfo     -
+ */
+JNIEXPORT jbyteArray JNICALL
+Java_sun_security_pkcs11_wrapper_PKCS11_getNativeKeyInfo
+    (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jKeyHandle,
+    jlong jWrappingKeyHandle, jobject jWrappingMech)
+{
+    jbyteArray returnValue = NULL;
+    CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
+    CK_OBJECT_HANDLE ckObjectHandle = jLongToCKULong(jKeyHandle);
+    CK_ATTRIBUTE_PTR ckpAttributes = NULL;
+    CK_RV rv;
+    jbyteArray nativeKeyInfoArray = NULL;
+    jbyteArray nativeKeyInfoWrappedKeyArray = NULL;
+    jbyte* nativeKeyInfoArrayRaw = NULL;
+    jbyte* nativeKeyInfoWrappedKeyArrayRaw = NULL;
+    unsigned int sensitiveAttributePosition = (unsigned int)-1;
+    unsigned int i = 0U;
+    unsigned long totalDataSize = 0UL, attributesCount = 0UL;
+    unsigned long totalCkAttributesSize = 0UL, totalNativeKeyInfoArraySize = 0UL;
+    unsigned long* wrappedKeySizePtr = NULL;
+    jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
+    jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
+    jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
+    CK_MECHANISM ckMechanism;
+    char iv[16] = {0x0};
+    CK_ULONG ckWrappedKeyLength = 0U;
+    unsigned long* wrappedKeySizeWrappedKeyArrayPtr = NULL;
+    CK_BYTE_PTR wrappedKeyBufferPtr = NULL;
+    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
+    CK_OBJECT_CLASS class;
+    CK_KEY_TYPE keyType;
+    CK_BBOOL sensitive;
+    CK_BBOOL netscapeAttributeValueNeeded = CK_FALSE;
+    CK_ATTRIBUTE ckNetscapeAttributesTemplate[4];
+    ckNetscapeAttributesTemplate[0].type = CKA_CLASS;
+    ckNetscapeAttributesTemplate[1].type = CKA_KEY_TYPE;
+    ckNetscapeAttributesTemplate[2].type = CKA_SENSITIVE;
+    ckNetscapeAttributesTemplate[3].type = CKA_NETSCAPE_DB;
+    ckNetscapeAttributesTemplate[0].pValue = &class;
+    ckNetscapeAttributesTemplate[1].pValue = &keyType;
+    ckNetscapeAttributesTemplate[2].pValue = &sensitive;
+    ckNetscapeAttributesTemplate[3].pValue = 0;
+    ckNetscapeAttributesTemplate[0].ulValueLen = sizeof(class);
+    ckNetscapeAttributesTemplate[1].ulValueLen = sizeof(keyType);
+    ckNetscapeAttributesTemplate[2].ulValueLen = sizeof(sensitive);
+    ckNetscapeAttributesTemplate[3].ulValueLen = 0;
+
+    if (ckpFunctions == NULL) { goto cleanup; }
+
+    // If key is private and of DSA or EC type, NSS may require CKA_NETSCAPE_DB
+    // attribute to unwrap it.
+    rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+            ckNetscapeAttributesTemplate,
+            sizeof(ckNetscapeAttributesTemplate)/sizeof(CK_ATTRIBUTE));
+
+    if (rv == CKR_OK && class == CKO_PRIVATE_KEY &&
+            (keyType == CKK_EC || keyType == CKK_DSA) &&
+            sensitive == CK_TRUE &&
+            ckNetscapeAttributesTemplate[3].ulValueLen == CK_UNAVAILABLE_INFORMATION) {
+        // We cannot set the attribute through C_SetAttributeValue here
+        // because it might be read-only. However, we can add it to
+        // the extracted buffer.
+        netscapeAttributeValueNeeded = CK_TRUE;
+        TRACE0("DEBUG: override CKA_NETSCAPE_DB attr value to TRUE\n");
+    }
+
+    ckpAttributes = (CK_ATTRIBUTE_PTR)malloc(
+            CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+    if (ckpAttributes == NULL) {
+        throwOutOfMemoryError(env, 0);
+        goto cleanup;
+    }
+    memcpy(ckpAttributes, ckpAttributesTemplate,
+            CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+
+    // Get sizes for value buffers
+    // NOTE: may return an error code but length values are filled anyways
+    (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+            ckpAttributes, CK_ATTRIBUTES_TEMPLATE_LENGTH);
+
+    for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
+        if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
+            totalDataSize += (ckpAttributes+i)->ulValueLen;
+            if ((ckpAttributes+i)->type == CKA_SENSITIVE) {
+                 sensitiveAttributePosition = attributesCount;
+                 TRACE0("DEBUG: GetNativeKeyInfo key is sensitive");
+            }
+            attributesCount++;
+        }
+    }
+
+    if (netscapeAttributeValueNeeded) {
+        attributesCount++;
+    }
+
+    // Allocate a single buffer to hold valid attributes and attribute's values
+    // Buffer structure: [ attributes-size, [ ... attributes ... ],
+    //                   values-size, [ ... values ... ], wrapped-key-size,
+    //                   [ ... wrapped-key ... ] ]
+    //     * sizes are expressed in bytes and data type is unsigned long
+    totalCkAttributesSize = attributesCount * sizeof(CK_ATTRIBUTE);
+    TRACE1("DEBUG: GetNativeKeyInfo attributesCount = %lu\n", attributesCount);
+    TRACE1("DEBUG: GetNativeKeyInfo sizeof CK_ATTRIBUTE = %lu\n", sizeof(CK_ATTRIBUTE));
+    TRACE1("DEBUG: GetNativeKeyInfo totalCkAttributesSize = %lu\n", totalCkAttributesSize);
+    TRACE1("DEBUG: GetNativeKeyInfo totalDataSize = %lu\n", totalDataSize);
+
+    totalNativeKeyInfoArraySize =
+            totalCkAttributesSize + sizeof(unsigned long) * 3 + totalDataSize;
+
+    TRACE1("DEBUG: GetNativeKeyInfo totalNativeKeyInfoArraySize = %lu\n", totalNativeKeyInfoArraySize);
+
+    nativeKeyInfoArray = (*env)->NewByteArray(env, totalNativeKeyInfoArraySize);
+    if (nativeKeyInfoArray == NULL) {
+        goto cleanup;
+    }
+
+    nativeKeyInfoArrayRaw = (*env)->GetByteArrayElements(env, nativeKeyInfoArray,
+            NULL);
+    if (nativeKeyInfoArrayRaw == NULL) {
+        goto cleanup;
+    }
+
+    wrappedKeySizePtr = (unsigned long*)(nativeKeyInfoArrayRaw +
+            sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize);
+    memcpy(nativeKeyInfoArrayRaw, &totalCkAttributesSize, sizeof(unsigned long));
+
+    memcpy(nativeKeyInfoArrayRaw + sizeof(unsigned long) + totalCkAttributesSize,
+        &totalDataSize, sizeof(unsigned long));
+
+    memset(wrappedKeySizePtr, 0, sizeof(unsigned long));
+
+    nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
+            sizeof(unsigned long);
+    nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
+    nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
+            totalCkAttributesSize + sizeof(unsigned long) * 2;
+
+    for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
+        if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
+            (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type =
+                    (ckpAttributes+i)->type;
+            (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen =
+                    (ckpAttributes+i)->ulValueLen;
+            if ((ckpAttributes+i)->ulValueLen != 0) {
+                (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
+                        nativeKeyInfoArrayRawDataPtr;
+            } else {
+                (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue = 0;
+            }
+            nativeKeyInfoArrayRawDataPtr +=
+                    (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
+            nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
+        }
+    }
+
+    TRACE0("DEBUG: GetNativeKeyInfo finished prepping nativeKeyInfoArray\n");
+
+    // Get attribute's values
+    rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+            (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+            attributesCount);
+    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+        goto cleanup;
+    }
+
+    TRACE0("DEBUG: GetNativeKeyInfo 1st C_GetAttributeValue call passed\n");
+
+    if (netscapeAttributeValueNeeded) {
+        (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type = CKA_NETSCAPE_DB;
+        // Value is not needed, public key is not used
+    }
+
+    if ((sensitiveAttributePosition != (unsigned int)-1) &&
+        *(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes)
+                +sensitiveAttributePosition))->pValue) == CK_TRUE) {
+        // Key is sensitive. Need to extract it wrapped.
+        if (jWrappingKeyHandle != -1) {
+
+            jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
+            rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
+                    jLongToCKULong(jWrappingKeyHandle), ckObjectHandle,
+                    NULL_PTR, &ckWrappedKeyLength);
+            if (ckWrappedKeyLength != 0) {
+                // Allocate space for getting the wrapped key
+                nativeKeyInfoWrappedKeyArray = (*env)->NewByteArray(env,
+                        totalNativeKeyInfoArraySize + ckWrappedKeyLength);
+                if (nativeKeyInfoWrappedKeyArray == NULL) {
+                    goto cleanup;
+                }
+                nativeKeyInfoWrappedKeyArrayRaw =
+                        (*env)->GetByteArrayElements(env,
+                                nativeKeyInfoWrappedKeyArray, NULL);
+                if (nativeKeyInfoWrappedKeyArrayRaw == NULL) {
+                    goto cleanup;
+                }
+                memcpy(nativeKeyInfoWrappedKeyArrayRaw, nativeKeyInfoArrayRaw,
+                        totalNativeKeyInfoArraySize);
+                wrappedKeySizeWrappedKeyArrayPtr =
+                        (unsigned long*)(nativeKeyInfoWrappedKeyArrayRaw +
+                        sizeof(unsigned long)*2 + totalCkAttributesSize +
+                        totalDataSize);
+                memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
+                TRACE1("DEBUG: GetNativeKeyInfo 1st C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+
+                wrappedKeyBufferPtr =
+                        (unsigned char*)wrappedKeySizeWrappedKeyArrayPtr +
+                        sizeof(unsigned long);
+                rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
+                        jLongToCKULong(jWrappingKeyHandle),ckObjectHandle,
+                        wrappedKeyBufferPtr, &ckWrappedKeyLength);
+                if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+                    goto cleanup;
+                }
+                memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
+                TRACE1("DEBUG: GetNativeKeyInfo 2nd C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+            } else {
+                goto cleanup;
+            }
+        } else {
+            goto cleanup;
+        }
+        returnValue = nativeKeyInfoWrappedKeyArray;
+    } else {
+        returnValue = nativeKeyInfoArray;
+    }
+
+cleanup:
+    if (ckpAttributes != NULL) {
+        free(ckpAttributes);
+    }
+
+    if (nativeKeyInfoArrayRaw != NULL) {
+        (*env)->ReleaseByteArrayElements(env, nativeKeyInfoArray,
+                nativeKeyInfoArrayRaw, 0);
+    }
+
+    if (nativeKeyInfoWrappedKeyArrayRaw != NULL) {
+        (*env)->ReleaseByteArrayElements(env, nativeKeyInfoWrappedKeyArray,
+                nativeKeyInfoWrappedKeyArrayRaw, 0);
+    }
+
+    if (nativeKeyInfoArray != NULL && returnValue != nativeKeyInfoArray) {
+        (*env)->DeleteLocalRef(env, nativeKeyInfoArray);
+    }
+
+    if (nativeKeyInfoWrappedKeyArray != NULL
+            && returnValue != nativeKeyInfoWrappedKeyArray) {
+        (*env)->DeleteLocalRef(env, nativeKeyInfoWrappedKeyArray);
+    }
+
+    return returnValue;
+}
+#endif
+
+#ifdef P11_ENABLE_CREATENATIVEKEY
+/*
+ * Class:     sun_security_pkcs11_wrapper_PKCS11
+ * Method:    createNativeKey
+ * Signature: (J[BJLsun/security/pkcs11/wrapper/CK_MECHANISM;)J
+ * Parametermapping:                          *PKCS11*
+ * @param   jlong         jSessionHandle      CK_SESSION_HANDLE hSession
+ * @param   jbyteArray    jNativeKeyInfo      -
+ * @param   jlong         jWrappingKeyHandle  CK_OBJECT_HANDLE hObject
+ * @param   jobject       jWrappingMech       CK_MECHANISM_PTR pMechanism
+ * @return  jlong         jKeyHandle          CK_OBJECT_HANDLE hObject
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_security_pkcs11_wrapper_PKCS11_createNativeKey
+    (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jNativeKeyInfo,
+    jlong jWrappingKeyHandle, jobject jWrappingMech)
+{
+    CK_OBJECT_HANDLE ckObjectHandle;
+    CK_RV rv;
+    CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
+    jbyte* nativeKeyInfoArrayRaw = NULL;
+    jlong jObjectHandle = 0L;
+    unsigned long totalCkAttributesSize = 0UL;
+    unsigned long nativeKeyInfoCkAttributesCount = 0UL;
+    jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
+    jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
+    jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
+    unsigned long totalDataSize = 0UL;
+    unsigned long* wrappedKeySizePtr = NULL;
+    unsigned int i = 0U;
+    CK_MECHANISM ckMechanism;
+    char iv[16] = {0x0};
+    CK_ULONG ckWrappedKeyLength = 0UL;
+    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
+
+    if (ckpFunctions == NULL) { goto cleanup; }
+
+    nativeKeyInfoArrayRaw =
+            (*env)->GetByteArrayElements(env, jNativeKeyInfo, NULL);
+    if (nativeKeyInfoArrayRaw == NULL) {
+        goto cleanup;
+    }
+
+    memcpy(&totalCkAttributesSize, nativeKeyInfoArrayRaw, sizeof(unsigned long));
+    TRACE1("DEBUG: createNativeKey totalCkAttributesSize = %lu\n", totalCkAttributesSize);
+    nativeKeyInfoCkAttributesCount = totalCkAttributesSize/sizeof(CK_ATTRIBUTE);
+    TRACE1("DEBUG: createNativeKey nativeKeyInfoCkAttributesCount = %lu\n", nativeKeyInfoCkAttributesCount);
+
+    nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
+            sizeof(unsigned long);
+    nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
+    nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
+            totalCkAttributesSize + sizeof(unsigned long) * 2;
+    memcpy(&totalDataSize, (nativeKeyInfoArrayRaw + totalCkAttributesSize + sizeof(unsigned long)),
+            sizeof(unsigned long));
+    TRACE1("DEBUG: createNativeKey totalDataSize = %lu\n", totalDataSize);
+
+    wrappedKeySizePtr = (unsigned long*)(nativeKeyInfoArrayRaw +
+            sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize);
+
+    memcpy(&ckWrappedKeyLength, wrappedKeySizePtr, sizeof(unsigned long));
+    TRACE1("DEBUG: createNativeKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+
+    for (i = 0; i < nativeKeyInfoCkAttributesCount; i++) {
+        if ((*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen
+                > 0) {
+            (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
+                    nativeKeyInfoArrayRawDataPtr;
+        }
+        nativeKeyInfoArrayRawDataPtr +=
+                (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
+        nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
+    }
+
+    if (ckWrappedKeyLength == 0) {
+        // Not a wrapped key
+        rv = (*ckpFunctions->C_CreateObject)(ckSessionHandle,
+                (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+                jLongToCKULong(nativeKeyInfoCkAttributesCount), &ckObjectHandle);
+    } else {
+        // Wrapped key
+        jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
+        rv = (*ckpFunctions->C_UnwrapKey)(ckSessionHandle, &ckMechanism,
+                jLongToCKULong(jWrappingKeyHandle),
+                (CK_BYTE_PTR)(wrappedKeySizePtr + 1), ckWrappedKeyLength,
+                (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+                jLongToCKULong(nativeKeyInfoCkAttributesCount),
+                &ckObjectHandle);
+    }
+    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+        goto cleanup;
+    }
+
+    jObjectHandle = ckULongToJLong(ckObjectHandle);
+
+cleanup:
+
+    if (nativeKeyInfoArrayRaw != NULL) {
+        (*env)->ReleaseByteArrayElements(env, jNativeKeyInfo,
+                nativeKeyInfoArrayRaw, JNI_ABORT);
+    }
+
+    return jObjectHandle;
+}
+#endif
+
 #ifdef P11_ENABLE_C_GENERATEKEY
 /*
  * Class:     sun_security_pkcs11_wrapper_PKCS11
diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
index 0f62b3e..00174e1 100644
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
@@ -548,6 +548,7 @@
 #define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600)
 
 #define CKA_VENDOR_DEFINED     0x80000000
+#define CKA_NETSCAPE_DB        0xD5A0DB00
 
 
 /* CK_ATTRIBUTE is a structure that includes the type, length
diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
index b8042c0..e60ae99 100644
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
@@ -148,6 +148,8 @@
 #undef  P11_ENABLE_C_GETFUNCTIONSTATUS
 #undef  P11_ENABLE_C_CANCELFUNCTION
 #undef  P11_ENABLE_C_WAITFORSLOTEVENT
+#define P11_ENABLE_GETNATIVEKEYINFO
+#define P11_ENABLE_CREATENATIVEKEY
 
 /* include the platform dependent part of the header */
 #include "p11_md.h"
diff --git a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
index a53c289..cd15654 100644
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
@@ -1566,6 +1566,7 @@
             CHECK_NULL_RETURN(ni_class, NULL);
         }
         ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
+        JNU_CHECK_EXCEPTION_RETURN(env, NULL);
         if (ni) {
             return ni;
         }
diff --git a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
index 850d8ad..753725f 100644
--- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
+++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
@@ -210,6 +210,7 @@
 
     if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+        return IOS_THROWN;
     }
 
     return convertReturnVal(env, (jint)written, JNI_FALSE);
@@ -258,6 +259,7 @@
 
     if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+        return IOS_THROWN;
     }
 
     return convertLongReturnVal(env, totalWritten, JNI_FALSE);
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index 8f34ed2..b94b292 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -112,6 +112,9 @@
 
 # jdk_awt
 
+# 8221305
+java/awt/FontMetrics/MaxAdvanceIsMax.java             solaris-all,macosx-all
+
 ############################################################################
 
 # jdk_beans
diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index a868430..f839cf0 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -20,6 +20,33 @@
 #  questions.
 #
 
+###############################################################################
+#
+# Tiered testing definitions
+#
+
+tier1 = \
+    :jdk_lang \
+    :jdk_util \
+    :jdk_math
+
+tier2 = \
+    :jdk_io \
+    :jdk_nio \
+    :jdk_net \
+    :jdk_rmi \
+    :jdk_time \
+    :jdk_security \
+    :jdk_text \
+    :core_tools \
+    :jdk_other \
+    :jdk_svc
+
+###############################################################################
+#
+# Other test definitions; generally smaller granularity than tiers
+#
+
 # java.lang package and VM runtime support
 jdk_lang = \
     java/lang \
diff --git a/jdk/test/java/awt/FontMetrics/MaxAdvanceIsMax.java b/jdk/test/java/awt/FontMetrics/MaxAdvanceIsMax.java
new file mode 100644
index 0000000..9c13170
--- /dev/null
+++ b/jdk/test/java/awt/FontMetrics/MaxAdvanceIsMax.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8218854
+ * @requires jdk.version.major >= 8
+ * @run main/othervm MaxAdvanceIsMax
+ */
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class MaxAdvanceIsMax {
+
+    private static boolean debug = true;
+
+    private static final class AntialiasHint {
+        private Object aaHint;
+        private String asString = "";
+
+        AntialiasHint(Object aaHint) {
+            if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+                asString += "FT_LOAD_TARGET_MONO";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) {
+                asString += "FT_LOAD_TARGET_NORMAL";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB)) {
+                asString += "FT_LOAD_TARGET_LCD";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)) {
+                asString += "FT_LOAD_TARGET_LCD_V";
+            }
+            this.aaHint = aaHint;
+        }
+
+        public Object getHint() {
+            return aaHint;
+        }
+
+        public String toString() {
+            return asString;
+        }
+    }
+
+    private static final AntialiasHint[] antialiasHints = {
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)
+    };
+
+    private static final class StyleAndSize {
+        int style;
+        float size;
+        public StyleAndSize(int style, float size) {
+            this.style = style;
+            this.size = size;
+        }
+    };
+
+    private static final StyleAndSize[] stylesAndSizes = new StyleAndSize[] {
+        new StyleAndSize(Font.BOLD | Font.ITALIC, 10)
+    };
+
+    public static void main(String[] args) throws Exception {
+        GraphicsEnvironment e =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        Font[] fonts = e.getAllFonts();
+        BufferedImage bi = new BufferedImage(500, 500,
+                BufferedImage.TYPE_INT_RGB);
+        for (AntialiasHint antialiasHint : antialiasHints) {
+            for (Font f : fonts) {
+                for (StyleAndSize styleAndSize : stylesAndSizes) {
+                    f = f.deriveFont(styleAndSize.style, styleAndSize.size);
+                    Graphics2D g2d = bi.createGraphics();
+                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+                            antialiasHint.getHint());
+                    FontMetrics fm = g2d.getFontMetrics(f);
+                    int[] width;
+                    int maxWidth = -1;
+                    int maxAdvance = fm.getMaxAdvance();
+                    if (debug) {
+                        System.out.println("Testing " + f + " in " +
+                                antialiasHint);
+                        System.out.println("getMaxAdvance: " + maxAdvance);
+                    }
+                    if (maxAdvance != -1) {
+                        String failureMessage = null;
+                        width = fm.getWidths();
+                        for (int j = 0; j < width.length; j++) {
+                            if (width[j] > maxWidth) {
+                                maxWidth = width[j];
+                            }
+                            if (width[j] > maxAdvance) {
+                                failureMessage = "FAILED: getMaxAdvance is " +
+                                                 "not max for font: " +
+                                                 f.toString() +
+                                                 " getMaxAdvance(): " +
+                                                 maxAdvance +
+                                                 " getWidths()[" + j + "]: " +
+                                                 width[j];
+                                throw new Exception(failureMessage);
+                            }
+                        }
+                    }
+                    if (debug) {
+                        System.out.println("Max char width: " + maxWidth);
+                        System.out.println("PASSED");
+                        System.out.println(".........................");
+                    }
+                }
+            }
+        }
+        System.out.println("TEST PASS - OK");
+    }
+}
diff --git a/jdk/test/java/awt/font/TextLayout/FontGlyphCompare.java b/jdk/test/java/awt/font/TextLayout/FontGlyphCompare.java
new file mode 100644
index 0000000..4935b34
--- /dev/null
+++ b/jdk/test/java/awt/font/TextLayout/FontGlyphCompare.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/* @test
+ * @bug 8214002
+ * @requires (os.family == "windows")
+ * @summary verify MS Mincho's Plain & Italic style
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class FontGlyphCompare {
+
+    static BufferedImage getFontImage(Font font, String text) {
+        int x = 1;
+        int y = 15;
+        int w = 10;
+        int h = 18;
+        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = (Graphics2D)bi.getGraphics();
+        g.setColor(Color.black);
+        g.fillRect(0, 0, w, h);
+        g.setColor(Color.white);
+        g.setFont(font);
+        g.drawString(text, x, y);
+        return bi;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String osName = System.getProperty("os.name");
+        System.out.println("OS is " + osName);
+        osName = osName.toLowerCase();
+        if (!osName.startsWith("windows")) {
+            return;
+        }
+        Font msMincho = new Font("MS Mincho", Font.PLAIN, 16);
+        String family = msMincho.getFamily(java.util.Locale.ENGLISH);
+        if (!family.equalsIgnoreCase("MS Mincho")) {
+            System.out.println("Japanese fonts not installed");
+            return;
+        }
+        String s = "|";
+        BufferedImage bi1 = getFontImage(new Font("MS Mincho", Font.PLAIN, 16), s);
+        int h1 = bi1.getHeight();
+        int w1 = bi1.getWidth();
+        BufferedImage bi2 = getFontImage(new Font("MS Mincho", Font.ITALIC, 16), s);
+        int h2 = bi2.getHeight();
+        int w2 = bi2.getWidth();
+        if ((h1 == h2) && (w1 == w2)) {
+            int cnt = 0;
+            for(int yy = 0; yy < h1; yy++) {
+                for(int xx = 0; xx < w1; xx++) {
+                    if (bi1.getRGB(xx, yy) != bi2.getRGB(xx, yy)) {
+                        cnt++;
+                    }
+                }
+            }
+            if (cnt == 0) {
+                throw new Exception("Test failed");
+            }
+        }
+    }
+}
diff --git a/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForName.java b/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForName.java
new file mode 100644
index 0000000..5847288
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForName.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.URLClassLoader;
+
+/*
+ * This class is loaded by the custom URLClassLoader, and then calls
+ * Class.forName();
+ */
+public class ClassForName implements Runnable {
+    static {
+        if (!(ClassForName.class.getClassLoader() instanceof URLClassLoader)) {
+            throw new RuntimeException("Supposed to be loaded by URLClassLoader");
+        }
+    }
+
+    public void run() {
+        try {
+            Class.forName(java.util.List.class.getName(), false,
+                          ClassLoader.getSystemClassLoader());
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java b/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
new file mode 100644
index 0000000..d243103
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8151486
+ * @summary Call Class.forName() on the system classloader from a class loaded
+ *          from a custom classloader.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Utils jdk.testlibrary.JarUtils
+ * @build ClassForName ClassForNameLeak
+ * @run main/othervm/policy=test.policy -Djava.security.manager ClassForNameLeak
+ */
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.testlibrary.Utils;
+import jdk.testlibrary.JarUtils;
+
+/*
+ * Create .jar, load ClassForName from .jar using a URLClassLoader
+ */
+public class ClassForNameLeak {
+    private static final long TIMEOUT = (long)(5000.0 * Utils.TIMEOUT_FACTOR);
+    private static final String TESTCLASSES = System.getProperty("test.classes", ".");
+    private static final String CLASSFILENAME = "ClassForName.class";
+    private static final int THREADS = 10;
+    private static final ReferenceQueue<ClassLoader> rq = new ReferenceQueue<>();
+
+    // Use a new classloader to load the ClassForName class, then run its
+    // Runnable.
+    public static PhantomReference<ClassLoader> loadAndRun(Path jarFilePath)
+            throws Exception {
+        ClassLoader classLoader = new URLClassLoader(
+                new URL[]{jarFilePath.toUri().toURL()}) {
+            @Override public String toString() { return "LeakedClassLoader"; }
+        };
+
+        Class<?> loadClass = Class.forName("ClassForName", true, classLoader);
+        ((Runnable) loadClass.newInstance()).run();
+
+        PhantomReference<ClassLoader> ref = new PhantomReference<>(classLoader, rq);
+        System.out.println("returning phantom ref: " + ref + " to " + classLoader);
+        return ref;
+    }
+
+    public static void main(final String[] args) throws Exception {
+        Path classFile = FileSystems.getDefault().getPath(TESTCLASSES,
+                                                          CLASSFILENAME);
+
+        // Create a temporary .jar file containing ClassForName.class
+        Path testClassesDir = Paths.get(TESTCLASSES);
+        Path jarFilePath = Files.createTempFile("cfn", ".jar");
+        JarUtils.createJarFile(jarFilePath, testClassesDir, classFile);
+        jarFilePath.toFile().deleteOnExit();
+
+        // Remove the ClassForName.class file that jtreg built, to make sure
+        // we're loading from the tmp .jar
+        Files.delete(classFile);
+
+        // Make simultaneous calls to the test method, to stress things a bit
+        ExecutorService es = Executors.newFixedThreadPool(THREADS);
+
+        List<Callable<PhantomReference<ClassLoader>>> callables =
+                Stream.generate(() -> {
+                    Callable<PhantomReference<ClassLoader>> cprcl = () -> {
+                        return loadAndRun(jarFilePath);
+                    };
+                    return cprcl;
+                }).limit(THREADS).collect(Collectors.toList());
+
+        List<Future<PhantomReference<ClassLoader>>> refs = es.invokeAll(callables);
+
+        // Give the GC a chance to enqueue the PhantomReferences
+        for (int i = 0; i < 10; i++) {
+            System.gc();
+        }
+        // Make sure all PhantomReferences to the leaked classloader are enqueued
+        for (int j = 0; j < THREADS; j++) {
+            Reference rmRef = rq.remove(TIMEOUT);
+            if (rmRef == null) {
+                throw new RuntimeException("ClassLoader was never enqueued!");
+            } else {
+                System.out.println("Enqueued " + rmRef);
+            }
+        }
+        System.out.println("All Classloaders successfully enqued");
+    }
+}
diff --git a/jdk/test/java/lang/ClassLoader/forNameLeak/test.policy b/jdk/test/java/lang/ClassLoader/forNameLeak/test.policy
new file mode 100644
index 0000000..46145b9
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/forNameLeak/test.policy
@@ -0,0 +1,6 @@
+grant {
+  permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "getClassLoader";
+  permission java.util.PropertyPermission "*", "read"; /* for Utils */
+};
diff --git a/jdk/test/java/net/NetworkInterface/IPv4Only.java b/jdk/test/java/net/NetworkInterface/IPv4Only.java
index 4d0bc3d..76bf0b8 100644
--- a/jdk/test/java/net/NetworkInterface/IPv4Only.java
+++ b/jdk/test/java/net/NetworkInterface/IPv4Only.java
@@ -22,8 +22,8 @@
  */
 
 /* @test
- * @bug   6964714
- * @run main/othervm IPv4Only
+ * @bug 6964714 8226928
+ * @run main/othervm -Djava.net.preferIPv4Stack=true IPv4Only
  * @summary Test the networkinterface listing with java.net.preferIPv4Stack=true.
  */
 
@@ -34,8 +34,6 @@
 
 public class IPv4Only {
     public static void main(String[] args) throws Exception {
-        System.setProperty("java.net.preferIPv4Stack","true");
-
         Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
         while (nifs.hasMoreElements()) {
             NetworkInterface nif = nifs.nextElement();
diff --git a/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java b/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java
new file mode 100644
index 0000000..6479a44
--- /dev/null
+++ b/jdk/test/javax/crypto/Cipher/EmptyFinalBuffer.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6946830
+ * @summary Test the Cipher.doFinal() with 0-length buffer
+ * @key randomness
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class EmptyFinalBuffer {
+
+    private static final String[] ALGOS = {
+        "AES/ECB/PKCS5Padding", "AES/CBC/PKCS5Padding"
+    };
+
+    public static void main(String[] args) throws Exception {
+
+        Provider[] provs = Security.getProviders();
+
+        SecretKey key = new SecretKeySpec(new byte[16], "AES");
+
+        boolean testFailed = false;
+        for (Provider p : provs) {
+            System.out.println("Testing: " + p.getName());
+            for (String algo : ALGOS) {
+                System.out.print("Algo: " + algo);
+                Cipher c;
+                try {
+                    c = Cipher.getInstance(algo, p);
+                } catch (NoSuchAlgorithmException nsae) {
+                    // skip
+                    System.out.println("=> No Support");
+                    continue;
+                }
+                c.init(Cipher.ENCRYPT_MODE, key);
+                AlgorithmParameters params = c.getParameters();
+                c.init(Cipher.DECRYPT_MODE, key, params);
+                try {
+                    byte[] out = c.doFinal(new byte[0]);
+                    System.out.println("=> Accepted w/ " +
+                        (out == null? "null" : (out.length + "-byte")) +
+                        " output");
+                } catch (Exception e) {
+                    testFailed = true;
+                    System.out.println("=> Rejected w/ Exception");
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (testFailed) {
+            throw new Exception("One or more tests failed");
+        } else {
+            System.out.println("All tests passed");
+        }
+    }
+}
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 5a630db..9d0e80c 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -1002,4 +1002,7 @@
 563e06335c252222c825a1fd67425b99581dbac2 jdk8u222-b06
 1b641cb01496dfa3d13b7587e76b22d76bfe51c6 jdk8u222-b07
 e5ee6728508d72b987758116d9b0a23e4f3830c1 jdk8u222-b08
+2ad39b194cc1b7fa1f368b044e86f43a2b6552b1 jdk8u232-b00
 6aa4f05982eb70dc746f84a152c4e5e0b4a7261e jdk8u222-b09
+32df4483e2e387a85688bad69c398dc4c7bc2cfa jdk8u222-b10
+32df4483e2e387a85688bad69c398dc4c7bc2cfa jdk8u222-ga
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 054a9d3..1cdcdfd 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -1036,4 +1036,7 @@
 8c7734737f76cbb888ddd78689cbe446b976a6b4 jdk8u222-b06
 2ce015266d7555da1b4dea46df7044d1c942180c jdk8u222-b07
 e18754960730dea198e73d07a17c79bc1c30e51f jdk8u222-b08
+22144dab9c5d489af564e1d3ffbadc293c8dc445 jdk8u232-b00
 6e564bba54d07236fbe0b3e756aca5c7df38a952 jdk8u222-b09
+0a5ba9e191cf8978fd3c66a53ea41b2bbdeec10b jdk8u222-b10
+0a5ba9e191cf8978fd3c66a53ea41b2bbdeec10b jdk8u222-ga