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