# HG changeset patch # User herrick # Date 1569988479 14400 # Node ID a44c029e85db410a0f25c9adeac0ca8a0c8b3bf8 # Parent 788704ff2559b5d7cc4eb470b1e5e7623cfe69e5# Parent 91d236715160b8493a20b10920ee73e5b58ae59c Merge diff -r 788704ff2559 -r a44c029e85db make/autoconf/basics.m4 --- a/make/autoconf/basics.m4 Tue Oct 01 18:53:13 2019 -0400 +++ b/make/autoconf/basics.m4 Tue Oct 01 23:54:39 2019 -0400 @@ -213,8 +213,10 @@ if test "x[$]$1" != x; then new_path="[$]$1" - if [ [[ "$new_path" = ~* ]] ]; then - # Use eval to expand a potential ~ + # Use eval to expand a potential ~. This technique does not work if there + # are spaces in the path (which is valid at this point on Windows), so only + # try to apply it if there is an actual ~ first in the path. + if [ [[ "$new_path" = "~"* ]] ]; then eval new_path="$new_path" if test ! -f "$new_path" && test ! -d "$new_path"; then AC_MSG_ERROR([The new_path of $1, which resolves as "$new_path", is not found.]) diff -r 788704ff2559 -r a44c029e85db src/hotspot/cpu/x86/assembler_x86.cpp --- a/src/hotspot/cpu/x86/assembler_x86.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/cpu/x86/assembler_x86.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -4742,6 +4742,25 @@ emit_int8((unsigned char)0xA5); } +void Assembler::roundsd(XMMRegister dst, XMMRegister src, int32_t rmode) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x0B); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)rmode); +} + +void Assembler::roundsd(XMMRegister dst, Address src, int32_t rmode) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + simd_prefix(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x0B); + emit_operand(dst, src); + emit_int8((unsigned char)rmode); +} + void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -5539,6 +5558,49 @@ emit_operand(dst, src); } +void Assembler::vroundpd(XMMRegister dst, XMMRegister src, int32_t rmode, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x09); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)(rmode)); +} + +void Assembler::vroundpd(XMMRegister dst, Address src, int32_t rmode, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x09); + emit_operand(dst, src); + emit_int8((unsigned char)(rmode)); +} + +void Assembler::vrndscalepd(XMMRegister dst, XMMRegister src, int32_t rmode, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x09); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)(rmode)); +} + +void Assembler::vrndscalepd(XMMRegister dst, Address src, int32_t rmode, int vector_len) { + assert(VM_Version::supports_evex(), "requires EVEX support"); + assert(dst != xnoreg, "sanity"); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x09); + emit_operand(dst, src); + emit_int8((unsigned char)(rmode)); +} + + void Assembler::vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionAttr attributes(vector_len, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); diff -r 788704ff2559 -r a44c029e85db src/hotspot/cpu/x86/assembler_x86.hpp --- a/src/hotspot/cpu/x86/assembler_x86.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/cpu/x86/assembler_x86.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -1856,6 +1856,9 @@ void sqrtsd(XMMRegister dst, Address src); void sqrtsd(XMMRegister dst, XMMRegister src); + void roundsd(XMMRegister dst, Address src, int32_t rmode); + void roundsd(XMMRegister dst, XMMRegister src, int32_t rmode); + // Compute Square Root of Scalar Single-Precision Floating-Point Value void sqrtss(XMMRegister dst, Address src); void sqrtss(XMMRegister dst, XMMRegister src); @@ -2020,6 +2023,12 @@ void vsqrtps(XMMRegister dst, XMMRegister src, int vector_len); void vsqrtps(XMMRegister dst, Address src, int vector_len); + // Round Packed Double precision value. + void vroundpd(XMMRegister dst, XMMRegister src, int32_t rmode, int vector_len); + void vroundpd(XMMRegister dst, Address src, int32_t rmode, int vector_len); + void vrndscalepd(XMMRegister dst, XMMRegister src, int32_t rmode, int vector_len); + void vrndscalepd(XMMRegister dst, Address src, int32_t rmode, int vector_len); + // Bitwise Logical AND of Packed Floating-Point Values void andpd(XMMRegister dst, XMMRegister src); void andps(XMMRegister dst, XMMRegister src); diff -r 788704ff2559 -r a44c029e85db src/hotspot/cpu/x86/macroAssembler_x86.cpp --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -3661,6 +3661,15 @@ } } +void MacroAssembler::roundsd(XMMRegister dst, AddressLiteral src, int32_t rmode, Register scratch_reg) { + if (reachable(src)) { + Assembler::roundsd(dst, as_Address(src), rmode); + } else { + lea(scratch_reg, src); + Assembler::roundsd(dst, Address(scratch_reg, 0), rmode); + } +} + void MacroAssembler::subss(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { Assembler::subss(dst, as_Address(src)); diff -r 788704ff2559 -r a44c029e85db src/hotspot/cpu/x86/macroAssembler_x86.hpp --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -1180,6 +1180,10 @@ void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, AddressLiteral src); + void roundsd(XMMRegister dst, XMMRegister src, int32_t rmode) { Assembler::roundsd(dst, src, rmode); } + void roundsd(XMMRegister dst, Address src, int32_t rmode) { Assembler::roundsd(dst, src, rmode); } + void roundsd(XMMRegister dst, AddressLiteral src, int32_t rmode, Register scratch_reg); + void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); } void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); } void sqrtss(XMMRegister dst, AddressLiteral src); diff -r 788704ff2559 -r a44c029e85db src/hotspot/cpu/x86/x86.ad --- a/src/hotspot/cpu/x86/x86.ad Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/cpu/x86/x86.ad Tue Oct 01 23:54:39 2019 -0400 @@ -1485,6 +1485,10 @@ ret_value = false; } break; + case Op_RoundDoubleMode: + if (UseSSE < 4) + ret_value = false; + break; } return ret_value; // Per default match rules are supported. @@ -1536,6 +1540,10 @@ if (vlen != 4) ret_value = false; break; + case Op_RoundDoubleModeV: + if (VM_Version::supports_avx() == false) + ret_value = false; + break; } } @@ -2854,6 +2862,108 @@ ins_pipe(pipe_slow); %} + +instruct roundD_reg(legRegD dst, legRegD src, immU8 rmode) %{ + predicate(UseSSE>=4); + match(Set dst (RoundDoubleMode src rmode)); + format %{ "roundsd $dst, $src" %} + ins_cost(150); + ins_encode %{ + __ roundsd($dst$$XMMRegister, $src$$XMMRegister, $rmode$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct roundD_mem(legRegD dst, memory src, immU8 rmode) %{ + predicate(UseSSE>=4); + match(Set dst (RoundDoubleMode (LoadD src) rmode)); + format %{ "roundsd $dst, $src" %} + ins_cost(150); + ins_encode %{ + __ roundsd($dst$$XMMRegister, $src$$Address, $rmode$$constant); + %} + ins_pipe(pipe_slow); +%} + +instruct roundD_imm(legRegD dst, immD con, immU8 rmode, rRegI scratch_reg) %{ + predicate(UseSSE>=4); + match(Set dst (RoundDoubleMode con rmode)); + effect(TEMP scratch_reg); + format %{ "roundsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} + ins_cost(150); + ins_encode %{ + __ roundsd($dst$$XMMRegister, $constantaddress($con), $rmode$$constant, $scratch_reg$$Register); + %} + ins_pipe(pipe_slow); +%} + +instruct vround2D_reg(legVecX dst, legVecX src, immU8 rmode) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "vroundpd $dst, $src, $rmode\t! round packed2D" %} + ins_encode %{ + int vector_len = 0; + __ vroundpd($dst$$XMMRegister, $src$$XMMRegister, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround2D_mem(legVecX dst, memory mem, immU8 rmode) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); + format %{ "vroundpd $dst, $mem, $rmode\t! round packed2D" %} + ins_encode %{ + int vector_len = 0; + __ vroundpd($dst$$XMMRegister, $mem$$Address, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround4D_reg(legVecY dst, legVecY src, legVecY rmode) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "vroundpd $dst, $src, $rmode\t! round packed4D" %} + ins_encode %{ + int vector_len = 1; + __ vroundpd($dst$$XMMRegister, $src$$XMMRegister, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround4D_mem(legVecY dst, memory mem, immU8 rmode) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); + format %{ "vroundpd $dst, $mem, $rmode\t! round packed4D" %} + ins_encode %{ + int vector_len = 1; + __ vroundpd($dst$$XMMRegister, $mem$$Address, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + + +instruct vround8D_reg(vecZ dst, vecZ src, immU8 rmode) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "vrndscalepd $dst, $src, $rmode\t! round packed8D" %} + ins_encode %{ + int vector_len = 2; + __ vrndscalepd($dst$$XMMRegister, $src$$XMMRegister, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vround8D_mem(vecZ dst, memory mem, immU8 rmode) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); + format %{ "vrndscalepd $dst, $mem, $rmode\t! round packed8D" %} + ins_encode %{ + int vector_len = 2; + __ vrndscalepd($dst$$XMMRegister, $mem$$Address, $rmode$$constant, vector_len); + %} + ins_pipe( pipe_slow ); +%} + instruct onspinwait() %{ match(OnSpinWait); ins_cost(200); diff -r 788704ff2559 -r a44c029e85db src/hotspot/os/windows/os_windows.cpp --- a/src/hotspot/os/windows/os_windows.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/os/windows/os_windows.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -4159,128 +4159,137 @@ } } -// The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c -// Creates an UNC path from a single byte path. Return buffer is -// allocated in C heap and needs to be freed by the caller. -// Returns NULL on error. -static wchar_t* create_unc_path(const char* path, errno_t &err) { - wchar_t* wpath = NULL; - size_t converted_chars = 0; - size_t path_len = strlen(path) + 1; // includes the terminating NULL - if (path[0] == '\\' && path[1] == '\\') { - if (path[2] == '?' && path[3] == '\\'){ - // if it already has a \\?\ don't do the prefix - wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len); +// Returns the given path as an absolute wide path in unc format. The returned path is NULL +// on error (with err being set accordingly) and should be freed via os::free() otherwise. +// additional_space is the number of additionally allocated wchars after the terminating L'\0'. +// This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for +// short paths. +static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { + if ((path == NULL) || (path[0] == '\0')) { + err = ENOENT; + return NULL; + } + + size_t path_len = strlen(path); + // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. + char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal); + wchar_t* result = NULL; + + if (buf == NULL) { + err = ENOMEM; + } else { + memcpy(buf, path, path_len + 1); + os::native_path(buf); + + wchar_t* prefix; + int prefix_off = 0; + bool is_abs = true; + bool needs_fullpath = true; + + if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { + prefix = L"\\\\?\\"; + } else if (buf[0] == '\\' && buf[1] == '\\') { + assert(buf[2] != '\\'); + + if (buf[2] == '?' && buf[3] == '\\') { + prefix = L""; + needs_fullpath = false; } else { - err = ENOMEM; + prefix = L"\\\\?\\UNC"; + prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path } } else { - // only UNC pathname includes double slashes here - wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - ::wcscpy(wpath, L"\\\\?\\UNC\0"); - err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); - } else { - err = ENOMEM; + is_abs = false; + prefix = L"\\\\?\\"; + } + + size_t buf_len = strlen(buf); + size_t prefix_len = wcslen(prefix); + size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN; + size_t result_size = prefix_len + full_path_size - prefix_off; + result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal); + + if (result == NULL) { + err = ENOMEM; + } else { + size_t converted_chars; + wchar_t* path_start = result + prefix_len - prefix_off; + err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len); + + if ((err == ERROR_SUCCESS) && needs_fullpath) { + wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal); + + if (tmp == NULL) { + err = ENOMEM; + } else { + if (!_wfullpath(tmp, path_start, full_path_size)) { + err = ENOENT; + } else { + ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t)); + } + + os::free(tmp); + } + } + + memcpy(result, prefix, sizeof(wchar_t) * prefix_len); + + // Remove trailing pathsep (not for \\?\:\, since it would make it relative) + size_t result_len = wcslen(result); + + if (result[result_len - 1] == L'\\') { + if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { + result[result_len - 1] = L'\0'; + } } } - } else { - wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - ::wcscpy(wpath, L"\\\\?\\\0"); - err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); - } else { - err = ENOMEM; - } - } - return wpath; -} - -static void destroy_unc_path(wchar_t* wpath) { - os::free(wpath); + } + + os::free(buf); + + if (err != ERROR_SUCCESS) { + os::free(result); + result = NULL; + } + + return result; } int os::stat(const char *path, struct stat *sbuf) { - char* pathbuf = (char*)os::strdup(path, mtInternal); - if (pathbuf == NULL) { - errno = ENOMEM; + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err); + + if (wide_path == NULL) { + errno = err; return -1; } - os::native_path(pathbuf); - int ret; - WIN32_FILE_ATTRIBUTE_DATA file_data; - // Not using stat() to avoid the problem described in JDK-6539723 - if (strlen(path) < MAX_PATH) { - BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data); - if (!bret) { - errno = ::GetLastError(); - ret = -1; - } - else { - file_attribute_data_to_stat(sbuf, file_data); - ret = 0; - } - } else { - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(pathbuf, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(pathbuf); - errno = err; - return -1; - } - BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data); - if (!bret) { - errno = ::GetLastError(); - ret = -1; - } else { - file_attribute_data_to_stat(sbuf, file_data); - ret = 0; - } - destroy_unc_path(wpath); - } - os::free(pathbuf); - return ret; + + WIN32_FILE_ATTRIBUTE_DATA file_data;; + BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data); + os::free(wide_path); + + if (!bret) { + errno = ::GetLastError(); + return -1; + } + + file_attribute_data_to_stat(sbuf, file_data); + return 0; } static HANDLE create_read_only_file_handle(const char* file) { - if (file == NULL) { - return INVALID_HANDLE_VALUE; - } - - char* nativepath = (char*)os::strdup(file, mtInternal); - if (nativepath == NULL) { - errno = ENOMEM; + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(file, err); + + if (wide_path == NULL) { + errno = err; return INVALID_HANDLE_VALUE; } - os::native_path(nativepath); - - size_t len = strlen(nativepath); - HANDLE handle = INVALID_HANDLE_VALUE; - - if (len < MAX_PATH) { - handle = ::CreateFile(nativepath, 0, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } else { - errno_t err = ERROR_SUCCESS; - wchar_t* wfile = create_unc_path(nativepath, err); - if (err != ERROR_SUCCESS) { - if (wfile != NULL) { - destroy_unc_path(wfile); - } - os::free(nativepath); - return INVALID_HANDLE_VALUE; - } - handle = ::CreateFileW(wfile, 0, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - destroy_unc_path(wfile); - } - - os::free(nativepath); + + HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + os::free(wide_path); + return handle; } @@ -4329,7 +4338,6 @@ return result; } - #define FT2INT64(ft) \ ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) @@ -4434,38 +4442,22 @@ return DontYieldALot; } -// This method is a slightly reworked copy of JDK's sysOpen -// from src/windows/hpi/src/sys_api_md.c - int os::open(const char *path, int oflag, int mode) { - char* pathbuf = (char*)os::strdup(path, mtInternal); - if (pathbuf == NULL) { - errno = ENOMEM; + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err); + + if (wide_path == NULL) { + errno = err; return -1; } - os::native_path(pathbuf); - int ret; - if (strlen(path) < MAX_PATH) { - ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); - } else { - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(pathbuf, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(pathbuf); - errno = err; - return -1; - } - ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode); - if (ret == -1) { - errno = ::GetLastError(); - } - destroy_unc_path(wpath); - } - os::free(pathbuf); - return ret; + int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode); + os::free(wide_path); + + if (fd == -1) { + errno = ::GetLastError(); + } + + return fd; } FILE* os::open(int fd, const char* mode) { @@ -4474,37 +4466,26 @@ // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { - char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal); - if (search_path == NULL) { - errno = ENOMEM; - return false; - } - strcpy(search_path, path); - os::native_path(search_path); - // Append "*", or possibly "\\*", to path - if (search_path[1] == ':' && - (search_path[2] == '\0' || - (search_path[2] == '\\' && search_path[3] == '\0'))) { - // No '\\' needed for cases like "Z:" or "Z:\" - strcat(search_path, "*"); - } - else { - strcat(search_path, "\\*"); - } - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(search_path, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(search_path); + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err, 2); + + if (wide_path == NULL) { errno = err; return false; } + + // Make sure we end with "\\*" + if (wide_path[wcslen(wide_path) - 1] == L'\\') { + wcscat(wide_path, L"*"); + } else { + wcscat(wide_path, L"\\*"); + } + WIN32_FIND_DATAW fd; - HANDLE f = ::FindFirstFileW(wpath, &fd); - destroy_unc_path(wpath); + HANDLE f = ::FindFirstFileW(wide_path, &fd); + os::free(wide_path); bool is_empty = true; + if (f != INVALID_HANDLE_VALUE) { while (is_empty && ::FindNextFileW(f, &fd)) { // An empty directory contains only the current directory file @@ -4515,8 +4496,10 @@ } } FindClose(f); - } - os::free(search_path); + } else { + errno = ::GetLastError(); + } + return is_empty; } diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/adlc/formssel.cpp --- a/src/hotspot/share/adlc/formssel.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/adlc/formssel.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -4047,6 +4047,7 @@ strcmp(opType,"FmaD") == 0 || strcmp(opType,"FmaF") == 0 || strcmp(opType,"RoundDouble")==0 || + strcmp(opType,"RoundDoubleMode")==0 || strcmp(opType,"RoundFloat")==0 || strcmp(opType,"ReverseBytesI")==0 || strcmp(opType,"ReverseBytesL")==0 || @@ -4175,7 +4176,7 @@ "URShiftVB","URShiftVS","URShiftVI","URShiftVL", "MaxReductionV", "MinReductionV", "ReplicateB","ReplicateS","ReplicateI","ReplicateL","ReplicateF","ReplicateD", - "LoadVector","StoreVector", + "RoundDoubleModeV","LoadVector","StoreVector", "FmaVD", "FmaVF","PopCountVI", // Next are not supported currently. "PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D", diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/classfile/vmSymbols.cpp --- a/src/hotspot/share/classfile/vmSymbols.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/classfile/vmSymbols.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -575,6 +575,9 @@ case vmIntrinsics::_intBitsToFloat: case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_longBitsToDouble: + case vmIntrinsics::_ceil: + case vmIntrinsics::_floor: + case vmIntrinsics::_rint: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/classfile/vmSymbols.hpp --- a/src/hotspot/share/classfile/vmSymbols.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -766,6 +766,7 @@ do_name(tan_name,"tan") do_name(atan2_name,"atan2") do_name(sqrt_name,"sqrt") \ do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \ do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \ + do_name(floor_name, "floor") do_name(ceil_name, "ceil") do_name(rint_name, "rint") \ \ do_name(addExact_name,"addExact") \ do_name(decrementExact_name,"decrementExact") \ @@ -781,6 +782,9 @@ do_intrinsic(_iabs, java_lang_Math, abs_name, int_int_signature, F_S) \ do_intrinsic(_labs, java_lang_Math, abs_name, long_long_signature, F_S) \ do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ + do_intrinsic(_floor, java_lang_Math, floor_name, double_double_signature, F_S) \ + do_intrinsic(_ceil, java_lang_Math, ceil_name, double_double_signature, F_S) \ + do_intrinsic(_rint, java_lang_Math, rint_name, double_double_signature, F_S) \ do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \ do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \ do_intrinsic(_datan2, java_lang_Math, atan2_name, double2_double_signature, F_S) \ diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -327,14 +327,25 @@ ShenandoahHeapRegion* next_from_region(ShenandoahHeapRegionSet* slice) { ShenandoahHeapRegion* from_region = _heap_regions.next(); - while (from_region != NULL && (!from_region->is_move_allowed() || from_region->is_humongous())) { + // Look for next candidate for this slice: + while (from_region != NULL) { + // Empty region: get it into the slice to defragment the slice itself. + // We could have skipped this without violating correctness, but we really + // want to compact all live regions to the start of the heap, which sometimes + // means moving them into the fully empty regions. + if (from_region->is_empty()) break; + + // Can move the region, and this is not the humongous region. Humongous + // moves are special cased here, because their moves are handled separately. + if (from_region->is_move_allowed() && !from_region->is_humongous()) break; + from_region = _heap_regions.next(); } if (from_region != NULL) { assert(slice != NULL, "sanity"); assert(!from_region->is_humongous(), "this path cannot handle humongous regions"); - assert(from_region->is_move_allowed(), "only regions that can be moved in mark-compact"); + assert(from_region->is_empty() || from_region->is_move_allowed(), "only regions that can be moved in mark-compact"); slice->add_region(from_region); } diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/c2compiler.cpp --- a/src/hotspot/share/opto/c2compiler.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/c2compiler.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -462,6 +462,11 @@ case vmIntrinsics::_writebackPostSync0: if (!Matcher::match_rule_supported(Op_CacheWBPostSync)) return false; break; + case vmIntrinsics::_rint: + case vmIntrinsics::_ceil: + case vmIntrinsics::_floor: + if (!Matcher::match_rule_supported(Op_RoundDoubleMode)) return false; + break; case vmIntrinsics::_hashCode: case vmIntrinsics::_identityHashCode: case vmIntrinsics::_getClass: diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/classes.hpp --- a/src/hotspot/share/opto/classes.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/classes.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -274,6 +274,8 @@ macro(Return) macro(Root) macro(RoundDouble) +macro(RoundDoubleMode) +macro(RoundDoubleModeV) macro(RoundFloat) macro(SafePoint) macro(SafePointScalarObject) diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/convertnode.cpp --- a/src/hotspot/share/opto/convertnode.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/convertnode.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -531,4 +531,16 @@ return phase->type( in(1) ); } - +//============================================================================= +//------------------------------Identity--------------------------------------- +// Remove redundant roundings. +Node* RoundDoubleModeNode::Identity(PhaseGVN* phase) { + int op = in(1)->Opcode(); + // Redundant rounding e.g. floor(ceil(n)) -> ceil(n) + if(op == Op_RoundDoubleMode) return in(1); + return this; +} +const Type* RoundDoubleModeNode::Value(PhaseGVN* phase) const { + return Type::DOUBLE; +} +//============================================================================= diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/convertnode.hpp --- a/src/hotspot/share/opto/convertnode.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/convertnode.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -212,5 +212,16 @@ virtual const Type* Value(PhaseGVN* phase) const; }; +//-----------------------------RoundDoubleModeNode----------------------------- +class RoundDoubleModeNode: public Node { + public: + RoundDoubleModeNode(Node *in1, Node * rmode): Node(0, in1, rmode) {} + virtual int Opcode() const; + virtual const Type *bottom_type() const { return Type::DOUBLE; } + virtual uint ideal_reg() const { return Op_RegD; } + virtual Node* Identity(PhaseGVN* phase); + virtual const Type* Value(PhaseGVN* phase) const; +}; + #endif // SHARE_OPTO_CONVERTNODE_HPP diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/library_call.cpp --- a/src/hotspot/share/opto/library_call.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/library_call.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -534,6 +534,9 @@ case vmIntrinsics::_identityHashCode: return inline_native_hashcode(/*!virtual*/ false, is_static); case vmIntrinsics::_getClass: return inline_native_getClass(); + case vmIntrinsics::_ceil: + case vmIntrinsics::_floor: + case vmIntrinsics::_rint: case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: @@ -1818,6 +1821,9 @@ switch (id) { case vmIntrinsics::_dabs: n = new AbsDNode( arg); break; case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break; + case vmIntrinsics::_ceil: n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(2))); break; + case vmIntrinsics::_floor: n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(1))); break; + case vmIntrinsics::_rint: n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(0))); break; default: fatal_unexpected_iid(id); break; } set_result(_gvn.transform(n)); @@ -1891,6 +1897,9 @@ runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); // These intrinsics are supported on all hardware + case vmIntrinsics::_ceil: + case vmIntrinsics::_floor: + case vmIntrinsics::_rint: return Matcher::match_rule_supported(Op_RoundDoubleMode) ? inline_double_math(id) : false; case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_double_math(id) : false; case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_double_math(id) : false; case vmIntrinsics::_fabs: return Matcher::match_rule_supported(Op_AbsF) ? inline_math(id) : false; diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/superword.cpp --- a/src/hotspot/share/opto/superword.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/superword.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -2401,6 +2401,12 @@ const TypePtr* atyp = n->adr_type(); vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen); vlen_in_bytes = vn->as_StoreVector()->memory_size(); + } else if (VectorNode::is_roundopD(n)) { + Node* in1 = vector_opd(p, 1); + Node* in2 = low_adr->in(2); + assert(in2->is_Con(), "Constant rounding mode expected."); + vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); + vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else if (VectorNode::is_muladds2i(n)) { assert(n->req() == 5u, "MulAddS2I should have 4 operands."); Node* in1 = vector_opd(p, 1); diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/vectornode.cpp --- a/src/hotspot/share/opto/vectornode.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/vectornode.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -128,6 +128,9 @@ case Op_NegD: assert(bt == T_DOUBLE, "must be"); return Op_NegVD; + case Op_RoundDoubleMode: + assert(bt == T_DOUBLE, "must be"); + return Op_RoundDoubleModeV; case Op_SqrtF: assert(bt == T_FLOAT, "must be"); return Op_SqrtVF; @@ -259,6 +262,13 @@ return false; } +bool VectorNode::is_roundopD(Node *n) { + if (n->Opcode() == Op_RoundDoubleMode) { + return true; + } + return false; +} + bool VectorNode::is_shift(Node* n) { switch (n->Opcode()) { case Op_LShiftI: @@ -407,6 +417,8 @@ case Op_MinV: return new MinVNode(n1, n2, vt); case Op_MaxV: return new MaxVNode(n1, n2, vt); + case Op_RoundDoubleModeV: return new RoundDoubleModeVNode(n1, n2, vt); + case Op_MulAddVS2VI: return new MulAddVS2VINode(n1, n2, vt); default: fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); diff -r 788704ff2559 -r a44c029e85db src/hotspot/share/opto/vectornode.hpp --- a/src/hotspot/share/opto/vectornode.hpp Tue Oct 01 18:53:13 2019 -0400 +++ b/src/hotspot/share/opto/vectornode.hpp Tue Oct 01 23:54:39 2019 -0400 @@ -70,6 +70,7 @@ static bool is_type_transition_short_to_int(Node* n); static bool is_type_transition_to_int(Node* n); static bool is_muladds2i(Node* n); + static bool is_roundopD(Node * n); static bool is_invariant_vector(Node* n); // [Start, end) half-open range defining which operands are vectors static void vector_operands(Node* n, uint* start, uint* end); @@ -447,6 +448,13 @@ SqrtVFNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} virtual int Opcode() const; }; +//------------------------------RoundDoubleVNode-------------------------------- +// Vector round double +class RoundDoubleModeVNode : public VectorNode { + public: + RoundDoubleModeVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; //------------------------------SqrtVDNode-------------------------------------- // Vector Sqrt double diff -r 788704ff2559 -r a44c029e85db src/java.base/share/classes/java/lang/Math.java --- a/src/java.base/share/classes/java/lang/Math.java Tue Oct 01 18:53:13 2019 -0400 +++ b/src/java.base/share/classes/java/lang/Math.java Tue Oct 01 23:54:39 2019 -0400 @@ -440,6 +440,7 @@ * floating-point value that is greater than or equal to * the argument and is equal to a mathematical integer. */ + @HotSpotIntrinsicCandidate public static double ceil(double a) { return StrictMath.ceil(a); // default impl. delegates to StrictMath } @@ -459,6 +460,7 @@ * floating-point value that less than or equal to the argument * and is equal to a mathematical integer. */ + @HotSpotIntrinsicCandidate public static double floor(double a) { return StrictMath.floor(a); // default impl. delegates to StrictMath } @@ -478,6 +480,7 @@ * @return the closest floating-point value to {@code a} that is * equal to a mathematical integer. */ + @HotSpotIntrinsicCandidate public static double rint(double a) { return StrictMath.rint(a); // default impl. delegates to StrictMath } diff -r 788704ff2559 -r a44c029e85db src/java.base/share/classes/sun/net/www/http/HttpClient.java --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java Tue Oct 01 18:53:13 2019 -0400 +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java Tue Oct 01 23:54:39 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -707,11 +707,7 @@ } else { // try once more openServer(); - if (needsTunneling()) { - MessageHeader origRequests = requests; - httpuc.doTunneling(); - requests = origRequests; - } + checkTunneling(httpuc); afterConnect(); writeRequests(requests, poster); return parseHTTP(responses, pi, httpuc); @@ -722,6 +718,18 @@ } + // Check whether tunnel must be open and open it if necessary + // (in the case of HTTPS with proxy) + private void checkTunneling(HttpURLConnection httpuc) throws IOException { + if (needsTunneling()) { + MessageHeader origRequests = requests; + PosterOutputStream origPoster = poster; + httpuc.doTunneling(); + requests = origRequests; + poster = origPoster; + } + } + private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc) throws IOException { /* If "HTTP/*" is found in the beginning, return true. Let @@ -849,11 +857,7 @@ closeServer(); cachedHttpClient = false; openServer(); - if (needsTunneling()) { - MessageHeader origRequests = requests; - httpuc.doTunneling(); - requests = origRequests; - } + checkTunneling(httpuc); afterConnect(); writeRequests(requests, poster); return parseHTTP(responses, pi, httpuc); diff -r 788704ff2559 -r a44c029e85db src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c --- a/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c Tue Oct 01 18:53:13 2019 -0400 +++ b/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c Tue Oct 01 23:54:39 2019 -0400 @@ -511,7 +511,7 @@ if (buffer == NULL) { RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory"); } - strncpy(buffer, allowed_peers, len); + memcpy(buffer, allowed_peers, len); buffer[len] = '\0'; jdwpTransportError err = parseAllowedPeersInternal(buffer); diff -r 788704ff2559 -r a44c029e85db src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java --- a/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java Tue Oct 01 18:53:13 2019 -0400 +++ b/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java Tue Oct 01 23:54:39 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,7 @@ private static class Result extends Error { static final long serialVersionUID = -5942088234594905629L; + @SuppressWarnings("serial") // Not statically typed as Serializable final TreePath expressionPath; Result(TreePath path) { diff -r 788704ff2559 -r a44c029e85db test/hotspot/gtest/runtime/test_os_windows.cpp --- a/test/hotspot/gtest/runtime/test_os_windows.cpp Tue Oct 01 18:53:13 2019 -0400 +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp Tue Oct 01 23:54:39 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,4 +85,595 @@ << "Failed to allocate memory at requested location " << expected_location << " of size " << expected_allocation_size; } +// The types of path modifications we randomly apply to a path. They should not change the file designated by the path. +enum ModsFilter { + Allow_None = 0, // No modifications + Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1. + Allow_Dot_Path = 2, // Add /. segments at random positions + Allow_Dot_Dot_Path = 4, // Add /../ segments at random positions. + Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path +}; + +// The mode in which to run. +enum Mode { + TEST, // Runs the test. This is the normal modus. + EXAMPLES, // Runs example which document the behaviour of the Windows system calls. + BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath. +}; + +// Parameters of the test. +static ModsFilter mods_filter = Allow_All; +static int mods_per_path = 50; // The number of variants of a path we try. +static Mode mode = TEST; + + +// Utility methods +static void get_current_dir_w(wchar_t* path, size_t size) { + DWORD count = GetCurrentDirectoryW((DWORD) size, path); + EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError(); + EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size; +} + +#define WITH_ABS_PATH(path) \ + wchar_t abs_path[JVM_MAXPATHLEN]; \ + wchar_t cwd[JVM_MAXPATHLEN]; \ + get_current_dir_w(cwd, JVM_MAXPATHLEN); \ + wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path)) + +static bool file_exists_w(const wchar_t* path) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); +} + +static void create_rel_directory_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create directory: \"" << path << "\" already exists"; + BOOL result = CreateDirectoryW(abs_path, NULL); + EXPECT_TRUE(result) << "Failed to create directory \"" << path << "\" " << GetLastError(); +} + +static void delete_empty_rel_directory_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists"; + BOOL result = RemoveDirectoryW(abs_path); + EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError(); +} + +static void create_rel_file_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create file: \"" << path << "\" already exists"; + HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError(); + CloseHandle(h); +} + +static void delete_rel_file_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists"; + BOOL result = DeleteFileW(abs_path); + EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError(); +} + +static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) { + size_t converted; + errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1); + EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string"; + + return err == ERROR_SUCCESS; +} + +static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) { + size_t already_used = dest - start; + size_t len = wcslen(to_copy); + + if (already_used + len < size) { + wcscpy_s(dest, size - already_used, to_copy); + } + + return dest + wcslen(to_copy); +} + +// The currently finite list of seperator sequences we might use instead of '\\'. +static const wchar_t* sep_replacements[] = { + L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/" +}; + +// Takes a path and modifies it in a way that it should still designate the same file. +static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) { + wchar_t* dest = result; + const wchar_t* src = path; + const wchar_t* path_start; + + if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) { + path_start = src + 8; + } else if (wcsncmp(src, L"\\\\?\\", 4) == 0) { + if (src[5] == L':') { + path_start = src + 6; + } else { + path_start = wcschr(src + 4, L'\\'); + } + } else if (wcsncmp(src, L"\\\\", 2) == 0) { + path_start = wcschr(src + 2, L'?'); + + if (path_start == NULL) { + path_start = wcschr(src + 2, L'\\'); + } else { + path_start = wcschr(path_start, L'\\'); + } + } else { + path_start = wcschr(src + 1, L'\\'); + } + + bool allow_sep_change = (mods_filter & Allow_Sep_Mods) && (os::random() & 1) == 0; + bool allow_dot_change = (mods_filter & Allow_Dot_Path) && (os::random() & 1) == 0; + bool allow_dotdot_change = (mods_filter & Allow_Dot_Dot_Path) && (os::random() & 1) == 0; + + while ((*src != L'\0') && (result + size > dest)) { + wchar_t c = *src; + *dest = c; + ++src; + ++dest; + + if (c == L'\\') { + if (allow_sep_change && (os::random() & 3) == 3) { + int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0])); + + if (i >= 0) { + const wchar_t* replacement = sep_replacements[i]; + dest = my_wcscpy_s(dest - 1, size, result, replacement); + } + } else if (path_start != NULL) { + if (allow_dotdot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { + wchar_t const* last_sep = src - 2; + + while (last_sep[0] != L'\\') { + --last_sep; + } + + if (last_sep > path_start) { + dest = my_wcscpy_s(dest, size, result, L"../"); + src = last_sep + 1; + } + } else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { + dest = my_wcscpy_s(dest, size, result, L"./"); + } + } + } + } + + while (is_dir && ((os::random() & 15) == 1)) { + dest = my_wcscpy_s(dest, size, result, L"/"); + } + + if (result + size > dest) { + *dest = L'\0'; + } + + // Use this modification only if not too close to the max size. + return result + size - 10 > dest; +} + +static void check_dir_impl(wchar_t* path, bool should_be_empty) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; + EXPECT_EQ(st.st_mode & S_IFMT, S_IFDIR) << "\"" << path << "\" is not a directory according to os::stat"; + errno = ERROR_SUCCESS; + bool is_empty = os::dir_is_empty(buf); + errno_t err = errno; + EXPECT_EQ(is_empty, should_be_empty) << "os::dir_is_empty assumed \"" << path << "\" is " + << (should_be_empty ? "not ": "") << "empty"; + EXPECT_EQ(err, ERROR_SUCCESS) << "os::dir_is_empty failed for \"" << path << "\"with errno " << err; + } +} + +static void check_file_impl(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; + EXPECT_EQ(st.st_mode & S_IFMT, S_IFREG) << "\"" << path << "\" is not a regular file according to os::stat"; + int fd = os::open(buf, O_RDONLY, 0); + EXPECT_NE(fd, -1) << "os::open failed for \"" << path << "\" with errno " << errno; + if (fd >= 0) { + ::close(fd); + } + } +} + +static void check_file_not_present_impl(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + int stat_ret; + EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\""; + if (stat_ret != -1) { + // Only check open if stat not already failed. + int fd = os::open(buf, O_RDONLY, 0); + EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\""; + if (fd >= 0) { + ::close(fd); + } + } + } +} + +static void check_dir(wchar_t* path, bool should_be_empty) { + check_dir_impl(path, should_be_empty); + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) { + check_dir_impl(tmp, should_be_empty); + } + } +} + +static void check_file(wchar_t* path) { + check_file_impl(path); + + // Check os::same_files at least somewhat. + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + wchar_t mod[JVM_MAXPATHLEN]; + + if (unnormalize_path(mod, JVM_MAXPATHLEN, false, path)) { + char mod_c[JVM_MAXPATHLEN]; + if (convert_to_cstring(mod_c, JVM_MAXPATHLEN, mod)) { + EXPECT_EQ(os::same_files(buf, mod_c), true) << "os::same files failed for \\" << path << "\" and \"" << mod_c << "\""; + } + } + } + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { + check_file_impl(tmp); + } + } +} + +static void check_file_not_present(wchar_t* path) { + check_file_not_present_impl(path); + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { + check_file_not_present_impl(tmp); + } + } +} + +static void record_path(char const* name, char const* len_name, wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + ::testing::Test::RecordProperty(name, buf); + snprintf(buf, JVM_MAXPATHLEN, "%d", (int) wcslen(path)); + ::testing::Test::RecordProperty(len_name, buf); + } +} + +static void bench_path(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + int reps = 100000; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + jlong wtime[2]; + + for (int t = 0; t < 2; ++t) { + wtime[t] = os::javaTimeNanos(); + + for (int i = 0; i < reps; ++i) { + bool succ = false; + size_t buf_len = strlen(buf); + wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal); + + if (w_path != NULL) { + size_t converted_chars; + if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) { + if (t == 1) { + wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal); + + if (tmp) { + if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) { + succ = true; + } + + // Note that we really don't use the full path name, but just add the cost of running _wfullpath. + os::free(tmp); + } + if (!succ) { + printf("Failed fullpathing \"%s\"\n", buf); + return; + } + succ = false; + } + HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h != INVALID_HANDLE_VALUE) { + ::CloseHandle(h); + succ = true; + } + } + } + + os::free(w_path); + if (!succ) { + printf("Failed getting W*attr. \"%s\"\n", buf); + return; + } + } + + wtime[t] = os::javaTimeNanos() - wtime[t]; + } + + jlong ctime = os::javaTimeNanos(); + + for (int i = 0; i < reps; ++i) { + HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h == INVALID_HANDLE_VALUE) { + return; + } + + ::CloseHandle(h); + } + + ctime = os::javaTimeNanos() - ctime; + + printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf, + 0.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps); + } +} + +static void print_attr_result_for_path(wchar_t* path) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + struct stat st; + char buf[JVM_MAXPATHLEN]; + wchar_t abs[JVM_MAXPATHLEN]; + + _wfullpath(abs, path, JVM_MAXPATHLEN); + printf("Checking \"%ls\" (%d chars):\n", path, (int) wcslen(path)); + printf("_wfullpath %ls (%d chars)\n", abs, (int) wcslen(abs)); + BOOL bret = ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); + printf("GetFileAttributesExW() %s\n", bret ? "success" : "failed"); + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data); + printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed"); + + bool succ = os::stat(buf, &st) != -1; + printf("os::stat() %s\n", succ ? "success" : "failed"); + } +} + +static void print_attr_result(wchar_t* format, ...) { + va_list argptr; + wchar_t buf[JVM_MAXPATHLEN]; + + va_start(argptr, format); + wvsprintfW(buf, format, argptr); + print_attr_result_for_path(buf); + va_end(argptr); +} + +#define RECORD_PATH(name) record_path(#name, #name "Len", name) +#define NAME_PART_50 L"01234567890123456789012345678901234567890123456789" +#define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 + +// Test which tries to find out if the os::stat, os::open, os::same_files and os::dir_is_empty methods +// can handle long path names correctly. +TEST_VM(os_windows, handle_long_paths) { + static wchar_t cwd[JVM_MAXPATHLEN]; + static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN]; + static wchar_t long_rel_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN]; + static wchar_t file_rel_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_path[JVM_MAXPATHLEN]; + static wchar_t file_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN]; + static wchar_t file_unc_path[JVM_MAXPATHLEN]; + static wchar_t root_dir_path[JVM_MAXPATHLEN]; + static wchar_t root_rel_dir_path[JVM_MAXPATHLEN]; + + wchar_t* dir_prefix = L"os_windows_long_paths_dir_"; + wchar_t* empty_dir_name = L"empty_directory_with_long_path"; + wchar_t* not_empty_dir_name = L"not_empty_directory_with_long_path"; + wchar_t* file_name = L"file"; + wchar_t dir_letter; + WIN32_FILE_ATTRIBUTE_DATA file_data; + bool can_test_unc = false; + + get_current_dir_w(cwd, sizeof(cwd) / sizeof(wchar_t)); + dir_letter = (cwd[1] == L':' ? cwd[0] : L'\0'); + int cwd_len = (int) wcslen(cwd); + int dir_prefix_len = (int) wcslen(dir_prefix); + int rel_path_len = MAX2(dir_prefix_len, 235 - cwd_len); + + memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len); + + for (int i = dir_prefix_len; i < rel_path_len; ++i) { + nearly_long_rel_path[i] = L'L'; + } + + nearly_long_rel_path[rel_path_len] = L'\0'; + + wsprintfW(long_rel_path, L"%ls\\%ls", nearly_long_rel_path, NAME_PART_250); + wsprintfW(empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, empty_dir_name); + wsprintfW(not_empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, not_empty_dir_name); + wsprintfW(nearly_long_file_rel_path, L"%ls\\%ls", nearly_long_rel_path, file_name); + wsprintfW(file_rel_path, L"%ls\\%ls\\%ls", nearly_long_rel_path, not_empty_dir_name, file_name); + wsprintfW(nearly_long_path, L"\\\\?\\%ls\\%ls", cwd, nearly_long_rel_path); + wsprintfW(empty_dir_path, L"%ls\\%ls", nearly_long_path, empty_dir_name); + wsprintfW(not_empty_dir_path, L"%ls\\%ls", nearly_long_path, not_empty_dir_name); + wsprintfW(nearly_long_file_path, L"%ls\\%ls", nearly_long_path, file_name); + wsprintfW(file_path, L"%ls\\%ls\\%ls", nearly_long_path, not_empty_dir_name, file_name); + wsprintfW(nearly_long_unc_path, L"\\\\localhost\\%lc$\\%s", dir_letter, nearly_long_path + 7); + wsprintfW(empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, empty_dir_name); + wsprintfW(not_empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, not_empty_dir_name); + wsprintfW(nearly_long_file_unc_path, L"%ls\\%ls", nearly_long_unc_path, file_name); + wsprintfW(file_unc_path, L"%s\\%s\\%s", nearly_long_unc_path, not_empty_dir_name, file_name); + wsprintfW(root_dir_path, L"%lc:\\", dir_letter); + wsprintfW(root_rel_dir_path, L"%lc:", dir_letter); + + RECORD_PATH(long_rel_path); + RECORD_PATH(nearly_long_rel_path); + RECORD_PATH(nearly_long_path); + RECORD_PATH(nearly_long_unc_path); + RECORD_PATH(empty_dir_rel_path); + RECORD_PATH(empty_dir_path); + RECORD_PATH(empty_dir_unc_path); + RECORD_PATH(not_empty_dir_rel_path); + RECORD_PATH(not_empty_dir_path); + RECORD_PATH(not_empty_dir_unc_path); + RECORD_PATH(nearly_long_file_rel_path); + RECORD_PATH(nearly_long_file_path); + RECORD_PATH(nearly_long_file_unc_path); + RECORD_PATH(file_rel_path); + RECORD_PATH(file_path); + RECORD_PATH(file_unc_path); + + create_rel_directory_w(nearly_long_rel_path); + create_rel_directory_w(long_rel_path); + create_rel_directory_w(empty_dir_rel_path); + create_rel_directory_w(not_empty_dir_rel_path); + create_rel_file_w(nearly_long_file_rel_path); + create_rel_file_w(file_rel_path); + + // For UNC path test we assume that the current DRIVE has a share + // called "$" (so for D: we expect \\localhost\D$ to be + // the same). Since this is only an assumption, we have to skip + // the UNC tests if the share is missing. + if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) { + printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter); + } else { + can_test_unc = true; + } + + if (mode == BENCH) { + bench_path(nearly_long_path + 4); + bench_path(nearly_long_rel_path); + bench_path(nearly_long_file_path + 4); + bench_path(nearly_long_file_rel_path); + } else if (mode == EXAMPLES) { + printf("Working directory: %ls", cwd); + + if (dir_letter) { + static wchar_t top_buf[JVM_MAXPATHLEN]; + wchar_t* top_path = wcschr(cwd + 3, L'\\'); + + if (top_path) { + size_t top_len = (top_path - cwd) - 3; + + memcpy(top_buf, cwd + 3, top_len * 2); + top_buf[top_len] = L'\0'; + top_path = top_buf; + } + + print_attr_result(L"%lc:\\", dir_letter); + print_attr_result(L"%lc:\\.\\", dir_letter); + + if (top_path) { + print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path); + } + + print_attr_result(L"%lc:", dir_letter); + print_attr_result(L"%lc:.", dir_letter); + print_attr_result(L"%lc:\\COM1", dir_letter); + print_attr_result(L"%lc:\\PRN", dir_letter); + print_attr_result(L"%lc:\\PRN\\COM1", dir_letter); + print_attr_result(L"\\\\?\\UNC\\localhost\\%lc$\\", dir_letter); + print_attr_result(L"\\\\?\\UNC\\\\localhost\\%lc$\\", dir_letter); + print_attr_result(nearly_long_unc_path); + print_attr_result(L"%ls\\.\\", nearly_long_unc_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_unc_path, nearly_long_rel_path); + print_attr_result(L"\\\\?\\UNC\\%ls", nearly_long_unc_path + 2); + print_attr_result(file_unc_path); + print_attr_result(L"%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path, not_empty_dir_name, not_empty_dir_name, file_name); + print_attr_result(L"%ls\\%ls\\.\\%ls", nearly_long_unc_path, not_empty_dir_name, file_name); + print_attr_result(L"\\\\?\\UNC\\%ls", file_unc_path + 2); + print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\.\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, file_name); + print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, not_empty_dir_name, file_name); + } + + print_attr_result(nearly_long_rel_path); + print_attr_result(L"%ls\\.\\", nearly_long_rel_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); + print_attr_result(L"%\\\\?\\%ls", nearly_long_rel_path); + print_attr_result(L"\\\\?\\%ls\\.\\", nearly_long_rel_path); + print_attr_result(L"\\\\?\\%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); + + print_attr_result(nearly_long_path + 4); + print_attr_result(L"%ls\\.\\", nearly_long_path + 4); + print_attr_result(L"%ls\\..\\%ls", nearly_long_path + 4, nearly_long_rel_path); + print_attr_result(nearly_long_path); + print_attr_result(L"%ls\\.\\", nearly_long_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_path, nearly_long_rel_path); + } else { + check_file_not_present(L""); + + // Check relative paths + check_dir(nearly_long_rel_path, false); + check_dir(long_rel_path, true); + check_dir(empty_dir_rel_path, true); + check_dir(not_empty_dir_rel_path, false); + check_file(nearly_long_file_rel_path); + check_file(file_rel_path); + + // Check absolute paths + if (dir_letter) { + check_dir(root_dir_path, false); + check_dir(root_rel_dir_path, false); + } + + check_dir(cwd, false); + check_dir(nearly_long_path + 4, false); + check_dir(empty_dir_path + 4, true); + check_dir(not_empty_dir_path + 4, false); + check_file(nearly_long_file_path + 4); + check_file(file_path + 4); + + // Check UNC paths + if (can_test_unc) { + check_dir(nearly_long_unc_path, false); + check_dir(empty_dir_unc_path, true); + check_dir(not_empty_dir_unc_path, false); + check_file(nearly_long_file_unc_path); + check_file(file_unc_path); + } + + // Check handling of :/../:/path/... + // The other drive letter should not overwrite the original one. + if (dir_letter) { + static wchar_t tmp[JVM_MAXPATHLEN]; + wchar_t* other_letter = dir_letter == L'D' ? L"C" : L"D"; + wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", nearly_long_file_path, other_letter, nearly_long_file_path + 2); + check_file_not_present(tmp); + wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", file_path, other_letter, file_path + 2); + check_file_not_present(tmp); + } + } + + delete_rel_file_w(file_rel_path); + delete_rel_file_w(nearly_long_file_rel_path); + delete_empty_rel_directory_w(not_empty_dir_rel_path); + delete_empty_rel_directory_w(empty_dir_rel_path); + delete_empty_rel_directory_w(long_rel_path); + delete_empty_rel_directory_w(nearly_long_rel_path); +} + #endif diff -r 788704ff2559 -r a44c029e85db test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java --- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java Tue Oct 01 23:54:39 2019 -0400 @@ -87,6 +87,9 @@ test_divv(a0, a1, -VALUE); test_diva(a0, a1, a3); test_negc(a0, a1); + test_rint(a0, a1); + test_ceil(a0, a1); + test_floor(a0, a1); } // Test and verify results System.out.println("Verification"); @@ -351,6 +354,56 @@ errn += verify("test_negc: ", i, a0[i], (double)(-((double)(ADD_INIT+i)))); } + // To test -ve and +ve Zero scenarios. + double [] other_corner_cases = { -0.0, 0.0, 9.007199254740992E15 }; + double [] other_corner_cases_res = new double[3]; + test_floor(a0, a1); + errn += verify("test_floor: ", 0, a0[0], Double.NaN); + errn += verify("test_floor: ", 1, a0[1], Double.POSITIVE_INFINITY); + errn += verify("test_floor: ", 2, a0[2], Double.NEGATIVE_INFINITY); + errn += verify("test_floor: ", 3, a0[3], Double.MAX_VALUE); + errn += verify("test_floor: ", 4, a0[4], 0.0); + errn += verify("test_floor: ", 5, a0[5], 0.0); + for (int i=6; i 0) @@ -577,6 +630,37 @@ } } + static void test_rint(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.rint(a1[i] + ((double)(i))/1000); + } + } + static void test_ceil(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.ceil(a1[i] + ((double)(i))/1000); + } + } + static void test_floor(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.floor(a1[i] + ((double)(i))/1000); + } + } + static void test_rint_cc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.rint(a1[i]); + } + } + static void test_ceil_cc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.ceil(a1[i]); + } + } + static void test_floor_cc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = Math.floor(a1[i]); + } + } + static int verify(String text, int i, double elem, double val) { if (elem != val && !(Double.isNaN(elem) && Double.isNaN(val))) { System.err.println(text + "[" + i + "] = " + elem + " != " + val); diff -r 788704ff2559 -r a44c029e85db test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java --- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java Tue Oct 01 23:54:39 2019 -0400 @@ -26,7 +26,7 @@ * @bug 8229016 8231055 * @summary Test correct elimination of array allocation with arraycopy to itself. * @library /test/lib - * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test* * compiler.escapeAnalysis.TestSelfArrayCopy */ diff -r 788704ff2559 -r a44c029e85db test/hotspot/jtreg/runtime/LoadClass/LongBCP.java --- a/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java Tue Oct 01 23:54:39 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import jdk.test.lib.Platform; import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; @@ -126,13 +125,8 @@ bootCP, "Hello"); output = new OutputAnalyzer(pb.start()); - if (!Platform.isWindows()) { - output.shouldContain("Hello World") - .shouldHaveExitValue(0); - } else { - output.shouldContain("Could not find or load main class Hello") - .shouldHaveExitValue(1); - } + output.shouldContain("Hello World") + .shouldHaveExitValue(0); // total relative path length exceeds MAX_PATH destDir = Paths.get(destDir.toString(), "yyyyyyyy"); @@ -144,12 +138,7 @@ bootCP, "Hello"); output = new OutputAnalyzer(pb.start()); - if (!Platform.isWindows()) { - output.shouldContain("Hello World") - .shouldHaveExitValue(0); - } else { - output.shouldContain("Could not find or load main class Hello") - .shouldHaveExitValue(1); - } + output.shouldContain("Hello World") + .shouldHaveExitValue(0); } } diff -r 788704ff2559 -r a44c029e85db test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java Tue Oct 01 23:54:39 2019 -0400 @@ -42,6 +42,8 @@ * @library /vmTestbase * /test/lib * @requires os.family != "aix" + * @comment Test is incompatible with ZGC, due to ZGC's address space requirements. + * @requires vm.gc != "Z" * @run driver jdk.test.lib.FileInstaller . . * @build nsk.jvmti.Allocate.alloc001 * @run shell alloc001.sh diff -r 788704ff2559 -r a44c029e85db test/jdk/ProblemList.txt --- a/test/jdk/ProblemList.txt Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/ProblemList.txt Tue Oct 01 23:54:39 2019 -0400 @@ -250,7 +250,7 @@ java/awt/font/TextLayout/TextLayoutBounds.java 8169188 generic-all java/awt/font/StyledMetrics/BoldSpace.java 8198422 linux-all java/awt/FontMetrics/FontCrash.java 8198336 windows-all -java/awt/FontMetrics/MaxAdvanceIsMax.java 8221305 solaris-all,macosx-all +java/awt/FontMetrics/MaxAdvanceIsMax.java 8221305,8231495 solaris-all,macosx-all,linux-all java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 generic-all java/awt/image/DrawImage/IncorrectClipXorModeSW2Surface.java 8196025 windows-all java/awt/image/DrawImage/IncorrectClipXorModeSurface2Surface.java 8196025 windows-all diff -r 788704ff2559 -r a44c029e85db test/jdk/java/io/File/SetLastModified.java --- a/test/jdk/java/io/File/SetLastModified.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/java/io/File/SetLastModified.java Tue Oct 01 23:54:39 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, 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 @@ -23,6 +23,7 @@ /* @test @bug 4091757 6652379 8177809 + @requires os.maxMemory >= 16G @summary Basic test for setLastModified method */ diff -r 788704ff2559 -r a44c029e85db test/jdk/java/net/MulticastSocket/UnreferencedMulticastSockets.java --- a/test/jdk/java/net/MulticastSocket/UnreferencedMulticastSockets.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/java/net/MulticastSocket/UnreferencedMulticastSockets.java Tue Oct 01 23:54:39 2019 -0400 @@ -50,6 +50,7 @@ import java.util.ArrayDeque; import java.util.List; import java.util.Optional; +import java.util.concurrent.Phaser; import java.util.concurrent.TimeUnit; import jdk.test.lib.net.IPSupport; @@ -72,11 +73,14 @@ static class Server implements Runnable { MulticastSocket ss; - + final int port; + final Phaser phaser = new Phaser(2); Server() throws IOException { + InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress serverAddress = - new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + new InetSocketAddress(loopback, 0); ss = new MulticastSocket(serverAddress); + port = ss.getLocalPort(); System.out.printf(" DatagramServer addr: %s: %d%n", this.getHost(), this.getPort()); pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverMulticastSocket")); @@ -89,7 +93,7 @@ } int getPort() { - return ss.getLocalPort(); + return port; } // Receive a byte and send back a byte @@ -98,12 +102,18 @@ byte[] buffer = new byte[50]; DatagramPacket p = new DatagramPacket(buffer, buffer.length); ss.receive(p); + System.out.printf("Server: ping received from: %s%n", p.getSocketAddress()); + phaser.arriveAndAwaitAdvance(); // await the client... buffer[0] += 1; + System.out.printf("Server: sending echo to: %s%n", p.getSocketAddress()); ss.send(p); // send back +1 + System.out.printf("Server: awaiting client%n"); + phaser.arriveAndAwaitAdvance(); // await the client... // do NOT close but 'forget' the socket reference + System.out.printf("Server: forgetting socket...%n"); ss = null; - } catch (Exception ioe) { + } catch (Throwable ioe) { ioe.printStackTrace(); } } @@ -112,8 +122,11 @@ public static void main(String args[]) throws Exception { IPSupport.throwSkippedExceptionIfNonOperational(); + InetSocketAddress clientAddress = + new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + // Create and close a MulticastSocket to warm up the FD count for side effects. - try (MulticastSocket s = new MulticastSocket(0)) { + try (MulticastSocket s = new MulticastSocket(clientAddress)) { // no-op; close immediately s.getLocalPort(); // no-op } @@ -126,8 +139,33 @@ Thread thr = new Thread(svr); thr.start(); - MulticastSocket client = new MulticastSocket(0); - System.out.printf(" client bound port: %d%n", client.getLocalPort()); + // It is possible under some circumstances that the client + // might get bound to the same port than the server: this + // would make the test fail - so if this happen we try to + // bind to a specific port by incrementing the server port. + MulticastSocket client = null; + int serverPort = svr.getPort(); + int maxtries = 20; + for (int i = 0; i < maxtries; i++) { + try { + System.out.printf("Trying to bind client to: %s%n", clientAddress); + client = new MulticastSocket(clientAddress); + if (client.getLocalPort() != svr.getPort()) break; + client.close(); + } catch (IOException x) { + System.out.printf("Couldn't create client after %d attempts: %s%n", i, x); + if (i == maxtries) throw x; + } + if (i == maxtries) { + String msg = String.format("Couldn't create client after %d attempts", i); + System.out.println(msg); + throw new AssertionError(msg); + } + clientAddress = new InetSocketAddress(clientAddress.getAddress(), serverPort + i); + } + + System.out.printf(" client bound port: %s:%d%n", + client.getLocalAddress(), client.getLocalPort()); client.connect(svr.getHost(), svr.getPort()); pendingSockets.add(new NamedWeak(client, pendingQueue, "clientMulticastSocket")); extractRefs(client, "clientMulticastSocket"); @@ -136,14 +174,17 @@ msg[0] = 1; DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort()); client.send(p); + System.out.printf(" ping sent to: %s:%d%n", svr.getHost(), svr.getPort()); + svr.phaser.arriveAndAwaitAdvance(); // wait until the server has received its packet p = new DatagramPacket(msg, msg.length); client.receive(p); - System.out.printf("echo received from: %s%n", p.getSocketAddress()); + System.out.printf(" echo received from: %s%n", p.getSocketAddress()); if (msg[0] != 2) { throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]); } + svr.phaser.arriveAndAwaitAdvance(); // let the server null out its socket // Do NOT close the MulticastSocket; forget it diff -r 788704ff2559 -r a44c029e85db test/jdk/java/net/SocketImpl/SocketImplCombinations.java --- a/test/jdk/java/net/SocketImpl/SocketImplCombinations.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/java/net/SocketImpl/SocketImplCombinations.java Tue Oct 01 23:54:39 2019 -0400 @@ -68,7 +68,7 @@ * Test creating a connected Socket, it should be created with a platform SocketImpl. */ public void testNewSocket2() throws IOException { - try (ServerSocket ss = new ServerSocket(0)) { + try (ServerSocket ss = boundServerSocket()) { try (Socket s = new Socket(ss.getInetAddress(), ss.getLocalPort())) { SocketImpl si = getSocketImpl(s); assertTrue(isSocksSocketImpl(si)); @@ -127,7 +127,7 @@ Socket s = new Socket((SocketImpl) null) { }; try (s) { assertTrue(getSocketImpl(s) == null); - s.bind(new InetSocketAddress(0)); // force SocketImpl to be created + s.bind(loopbackSocketAddress()); // force SocketImpl to be created SocketImpl si = getSocketImpl(s); assertTrue(isSocksSocketImpl(si)); SocketImpl delegate = getDelegate(si); @@ -218,7 +218,7 @@ Socket s = new Socket((SocketImpl) null) { }; try (s) { assertTrue(getSocketImpl(s) == null); - s.bind(new InetSocketAddress(0)); // force SocketImpl to be created + s.bind(loopbackSocketAddress()); // force SocketImpl to be created assertTrue(getSocketImpl(s) instanceof CustomSocketImpl); } } finally { @@ -378,7 +378,7 @@ public void testServerSocketAccept5a() throws IOException { SocketImpl serverImpl = new CustomSocketImpl(true); try (ServerSocket ss = new ServerSocket(serverImpl) { }) { - ss.bind(new InetSocketAddress(0)); + ss.bind(loopbackSocketAddress()); expectThrows(IOException.class, ss::accept); } } @@ -566,16 +566,36 @@ } /** + * Returns a new InetSocketAddress with the loopback interface + * and port 0. + */ + static InetSocketAddress loopbackSocketAddress() { + InetAddress loopback = InetAddress.getLoopbackAddress(); + return new InetSocketAddress(loopback, 0); + } + + /** + * Returns a ServerSocket bound to a port on the loopback address + */ + static ServerSocket boundServerSocket() throws IOException { + ServerSocket ss = new ServerSocket(); + ss.bind(loopbackSocketAddress()); + return ss; + } + + /** * Creates a ServerSocket that returns the given Socket from accept. */ static ServerSocket serverSocketToAccept(Socket s) throws IOException { - return new ServerSocket(0) { + ServerSocket ss = new ServerSocket() { @Override public Socket accept() throws IOException { implAccept(s); return s; } }; + ss.bind(loopbackSocketAddress()); + return ss; } /** @@ -590,7 +610,7 @@ return s; } }; - ss.bind(new InetSocketAddress(0)); + ss.bind(loopbackSocketAddress()); return ss; } diff -r 788704ff2559 -r a44c029e85db test/jdk/java/net/httpclient/DigestEchoServer.java --- a/test/jdk/java/net/httpclient/DigestEchoServer.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/java/net/httpclient/DigestEchoServer.java Tue Oct 01 23:54:39 2019 -0400 @@ -26,6 +26,8 @@ import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; + +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -1568,8 +1570,8 @@ @Override public void run() { try { + int c = 0; try { - int c; while ((c = is.read()) != -1) { os.write(c); os.flush(); @@ -1578,11 +1580,13 @@ if (DEBUG) System.out.print(tag); } is.close(); + } catch (IOException ex) { + if (DEBUG || !stopped && c > -1) + ex.printStackTrace(System.out); + end.completeExceptionally(ex); } finally { - os.close(); + try {os.close();} catch (Throwable t) {} } - } catch (IOException ex) { - if (DEBUG) ex.printStackTrace(System.out); } finally { end.complete(null); } @@ -1632,10 +1636,12 @@ @Override public void run() { Socket clientConnection = null; + Socket targetConnection = null; try { while (!stopped) { System.out.println(now() + "Tunnel: Waiting for client"); Socket toClose; + targetConnection = clientConnection = null; try { toClose = clientConnection = ss.accept(); if (NO_LINGER) { @@ -1649,7 +1655,6 @@ } System.out.println(now() + "Tunnel: Client accepted"); StringBuilder headers = new StringBuilder(); - Socket targetConnection = null; InputStream ccis = clientConnection.getInputStream(); OutputStream ccos = clientConnection.getOutputStream(); Writer w = new OutputStreamWriter( @@ -1769,28 +1774,44 @@ end1 = new CompletableFuture<>()); Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-', end2 = new CompletableFuture<>()); - end = CompletableFuture.allOf(end1, end2); + var end11 = end1.whenComplete((r, t) -> exceptionally(end2, t)); + var end22 = end2.whenComplete((r, t) -> exceptionally(end1, t)); + end = CompletableFuture.allOf(end11, end22); + Socket tc = targetConnection; end.whenComplete( (r,t) -> { try { toClose.close(); } catch (IOException x) { } + try { tc.close(); } catch (IOException x) { } finally {connectionCFs.remove(end);} }); connectionCFs.add(end); + targetConnection = clientConnection = null; t1.start(); t2.start(); } } catch (Throwable ex) { - try { - ss.close(); - } catch (IOException ex1) { - ex.addSuppressed(ex1); - } + close(clientConnection, ex); + close(targetConnection, ex); + close(ss, ex); ex.printStackTrace(System.err); } finally { System.out.println(now() + "Tunnel: exiting (stopped=" + stopped + ")"); connectionCFs.forEach(cf -> cf.complete(null)); } } + + void exceptionally(CompletableFuture cf, Throwable t) { + if (t != null) cf.completeExceptionally(t); + } + + void close(Closeable c, Throwable e) { + if (c == null) return; + try { + c.close(); + } catch (IOException x) { + e.addSuppressed(x); + } + } } /** diff -r 788704ff2559 -r a44c029e85db test/jdk/sun/net/www/http/HttpClient/B8209178.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/net/www/http/HttpClient/B8209178.java Tue Oct 01 23:54:39 2019 -0400 @@ -0,0 +1,409 @@ +/* + * 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 8209178 + * @modules java.base/sun.net.www java.base/sun.security.x509 java.base/sun.security.tools.keytool + * @library /test/lib + * @run main/othervm -Dsun.net.http.retryPost=true B8209178 + * @run main/othervm -Dsun.net.http.retryPost=false B8209178 + * @summary Proxied HttpsURLConnection doesn't send BODY when retrying POST request + */ + +import java.io.*; +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import javax.net.ssl.*; + +import com.sun.net.httpserver.*; +import jdk.test.lib.net.URIBuilder; +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.x509.X500Name; + +public class B8209178 { + static { + try { + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); + SSLContext.setDefault(new TestSSLContext().get()); + } catch (Exception ex) { + throw new ExceptionInInitializerError(ex); + } + } + + static final String RESPONSE = "

Hello World!"; + static final String PATH = "/foo/"; + static final String RETRYPOST = System.getProperty("sun.net.http.retryPost"); + + static HttpServer createHttpsServer() throws IOException, NoSuchAlgorithmException { + HttpsServer server = HttpsServer.create(); + HttpContext context = server.createContext(PATH); + context.setHandler(new HttpHandler() { + + boolean simulateError = true; + + @Override + public void handle(HttpExchange he) throws IOException { + + System.out.printf("%s - received request on : %s%n", + Thread.currentThread().getName(), + he.getRequestURI()); + System.out.printf("%s - received request headers : %s%n", + Thread.currentThread().getName(), + new HashMap(he.getRequestHeaders())); + + InputStream requestBody = he.getRequestBody(); + String body = B8209178.toString(requestBody); + + System.out.printf("%s - received request body : %s%n", + Thread.currentThread().getName(), body); + + if (simulateError) { + simulateError = false; + + System.out.printf("%s - closing connection unexpectedly ... %n", + Thread.currentThread().getName(), he.getRequestHeaders()); + + he.close(); // try not to respond anything the first time ... + return; + } + + he.getResponseHeaders().add("encoding", "UTF-8"); + he.sendResponseHeaders(200, RESPONSE.length()); + he.getResponseBody().write(RESPONSE.getBytes(StandardCharsets.UTF_8)); + he.close(); + } + }); + + server.setHttpsConfigurator(new Configurator(SSLContext.getDefault())); + server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + return server; + } + + public static void main(String[] args) throws IOException, NoSuchAlgorithmException { + HttpServer server = createHttpsServer(); + server.start(); + try { + new B8209178().test(server); + + } finally { + server.stop(0); + System.out.println("Server stopped"); + } + } + + public void test(HttpServer server /*, HttpClient.Version version*/) throws IOException { + System.out.println("System property retryPost: " + RETRYPOST); + System.out.println("Server is: " + server.getAddress()); + System.out.println("Verifying communication with server"); + URI uri = URIBuilder.newBuilder() + .scheme("https") + .host(server.getAddress().getAddress()) + .port(server.getAddress().getPort()) + .path(PATH + "x") + .buildUnchecked(); + + TunnelingProxy proxy = new TunnelingProxy(server); + proxy.start(); + + try { + System.out.println("Proxy started"); + Proxy p = new Proxy(Proxy.Type.HTTP, + InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort())); + System.out.println("Verifying communication with proxy"); + + callHttpsServerThroughProxy(uri, p); + + } finally { + System.out.println("Stopping proxy"); + proxy.stop(); + System.out.println("Proxy stopped"); + } + } + + private void callHttpsServerThroughProxy(URI uri, Proxy p) throws IOException { + HttpsURLConnection urlConnection = (HttpsURLConnection) uri.toURL().openConnection(p); + + urlConnection.setConnectTimeout(1000); + urlConnection.setReadTimeout(3000); + urlConnection.setDoInput(true); + urlConnection.setDoOutput(true); + urlConnection.setRequestMethod("POST"); + urlConnection.setUseCaches(false); + + urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + urlConnection.setRequestProperty("charset", "utf-8"); + urlConnection.setRequestProperty("Connection", "keep-alive"); + + String urlParameters = "param1=a¶m2=b¶m3=c"; + byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8); + + OutputStream outputStream = urlConnection.getOutputStream(); + outputStream.write(postData); + outputStream.close(); + + int responseCode; + + try { + responseCode = urlConnection.getResponseCode(); + System.out.printf(" ResponseCode : %s%n", responseCode); + String output; + InputStream inputStream = (responseCode < 400) ? urlConnection.getInputStream() : urlConnection.getErrorStream(); + output = toString(inputStream); + inputStream.close(); + System.out.printf(" Output from server : %s%n", output); + + if (responseCode == 200) { // OK ! + } else { + throw new RuntimeException("Bad response Code : " + responseCode); + } + } catch (SocketException se) { + if (RETRYPOST.equals("true")) { // Should not get here with the fix + throw new RuntimeException("Unexpected Socket Exception: " + se); + } else { + System.out.println("Socket Exception received as expected: " + se); + } + } + } + + static class TunnelingProxy { + final Thread accept; + final ServerSocket ss; + final boolean DEBUG = false; + final HttpServer serverImpl; + + TunnelingProxy(HttpServer serverImpl) throws IOException { + this.serverImpl = serverImpl; + ss = new ServerSocket(); + accept = new Thread(this::accept); + } + + void start() throws IOException { + ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + accept.start(); + } + + // Pipe the input stream to the output stream + private synchronized Thread pipe(InputStream is, OutputStream os, char tag) { + return new Thread("TunnelPipe(" + tag + ")") { + @Override + public void run() { + try { + try { + int c; + while ((c = is.read()) != -1) { + os.write(c); + os.flush(); + // if DEBUG prints a + or a - for each transferred + // character. + if (DEBUG) System.out.print(tag); + } + is.close(); + } finally { + os.close(); + } + } catch (IOException ex) { + if (DEBUG) ex.printStackTrace(System.out); + } + } + }; + } + + public InetSocketAddress getAddress() { + return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort()); + } + + // This is a bit shaky. It doesn't handle continuation + // lines, but our client shouldn't send any. + // Read a line from the input stream, swallowing the final + // \r\n sequence. Stops at the first \n, doesn't complain + // if it wasn't preceded by '\r'. + // + String readLine(InputStream r) throws IOException { + StringBuilder b = new StringBuilder(); + int c; + while ((c = r.read()) != -1) { + if (c == '\n') { + break; + } + b.appendCodePoint(c); + } + if (b.codePointAt(b.length() - 1) == '\r') { + b.delete(b.length() - 1, b.length()); + } + return b.toString(); + } + + public void accept() { + Socket clientConnection = null; + try { + while (true) { + System.out.println("Tunnel: Waiting for client"); + Socket previous = clientConnection; + try { + clientConnection = ss.accept(); + } catch (IOException io) { + if (DEBUG) io.printStackTrace(System.out); + break; + } finally { + // we have only 1 client at a time, so it is safe + // to close the previous connection here + if (previous != null) previous.close(); + } + System.out.println("Tunnel: Client accepted"); + Socket targetConnection = null; + InputStream ccis = clientConnection.getInputStream(); + OutputStream ccos = clientConnection.getOutputStream(); + Writer w = new OutputStreamWriter(ccos, "UTF-8"); + PrintWriter pw = new PrintWriter(w); + System.out.println("Tunnel: Reading request line"); + String requestLine = readLine(ccis); + System.out.println("Tunnel: Request status line: " + requestLine); + if (requestLine.startsWith("CONNECT ")) { + // We should probably check that the next word following + // CONNECT is the host:port of our HTTPS serverImpl. + // Some improvement for a followup! + + // Read all headers until we find the empty line that + // signals the end of all headers. + while (!requestLine.equals("")) { + System.out.println("Tunnel: Reading header: " + + (requestLine = readLine(ccis))); + } + + // Open target connection + targetConnection = new Socket( + serverImpl.getAddress().getAddress(), + serverImpl.getAddress().getPort()); + + // Then send the 200 OK response to the client + System.out.println("Tunnel: Sending " + + "HTTP/1.1 200 OK\r\n\r\n"); + pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + pw.flush(); + } else { + // This should not happen + throw new IOException("Tunnel: Unexpected status line: " + + requestLine); + } + + // Pipe the input stream of the client connection to the + // output stream of the target connection and conversely. + // Now the client and target will just talk to each other. + System.out.println("Tunnel: Starting tunnel pipes"); + Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); + Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); + t1.start(); + t2.start(); + + // We have only 1 client... wait until it has finished before + // accepting a new connection request. + System.out.println("Tunnel: Waiting for pipes to close"); + t1.join(); + t2.join(); + System.out.println("Tunnel: Done - waiting for next client"); + } + } catch (Throwable ex) { + try { + ss.close(); + } catch (IOException ex1) { + ex.addSuppressed(ex1); + } + ex.printStackTrace(System.err); + } + } + + void stop() throws IOException { + ss.close(); + } + } + + static class Configurator extends HttpsConfigurator { + public Configurator(SSLContext ctx) { + super(ctx); + } + + @Override + public void configure(HttpsParameters params) { + params.setSSLParameters(getSSLContext().getSupportedSSLParameters()); + } + } + + + static class TestSSLContext { + + SSLContext ssl; + + public TestSSLContext() throws Exception { + init(); + } + + private void init() throws Exception { + + CertAndKeyGen keyGen = new CertAndKeyGen("RSA", "SHA1WithRSA", null); + keyGen.generate(1024); + + //Generate self signed certificate + X509Certificate[] chain = new X509Certificate[1]; + chain[0] = keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long) 365 * 24 * 3600); + + char[] passphrase = "passphrase".toCharArray(); + + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, passphrase); // must be "initialized" ... + + ks.setKeyEntry("server", keyGen.getPrivateKey(), passphrase, chain); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ks); + + ssl = SSLContext.getInstance("TLS"); + ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + + public SSLContext get() { + return ssl; + } + } + + // ############################################################################################### + + private static String toString(InputStream inputStream) throws IOException { + StringBuilder sb = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + int i = bufferedReader.read(); + while (i != -1) { + sb.append((char) i); + i = bufferedReader.read(); + } + bufferedReader.close(); + return sb.toString(); + } +} diff -r 788704ff2559 -r a44c029e85db test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java --- a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java Tue Oct 01 23:54:39 2019 -0400 @@ -30,12 +30,13 @@ * @summary Known Answer Test for AES cipher with GCM mode support in * PKCS11 provider. */ -import java.security.*; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.math.*; - -import java.util.*; +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; public class TestKATForGCM extends PKCS11Test { @@ -319,15 +320,21 @@ System.out.println("Test Passed!"); } } catch (Exception e) { - double ver = getNSSInfo("nss"); - if (ver < 3.251d && p.getName().contains("SunPKCS11-NSS") && - System.getProperty("os.name").equals("SunOS")) { - // buggy behaviour from solaris on 11.2 OS (nss < 3.251) - System.out.println("Skipping: SunPKCS11-NSS: Old NSS: " + ver); - return; // OK - } else { - throw e; + System.out.println("Exception occured using " + p.getName() + " version " + p.getVersionStr()); + + if (isNSS(p)) { + double ver = getNSSInfo("nss"); + String osName = System.getProperty("os.name"); + if (ver < 3.251d && osName.equals("SunOS")) { + // buggy behaviour from solaris on 11.2 OS (nss < 3.251) + System.out.println("Skipping: SunPKCS11-NSS: Old NSS: " + ver); + return; // OK + } else if (ver > 3.139 && ver < 3.15 && osName.equals("Linux")) { + // warn about buggy behaviour on Linux with nss 3.14 + System.out.println("Warning: old NSS " + ver + " might be problematic, consider upgrading it"); + } } + throw e; } } } diff -r 788704ff2559 -r a44c029e85db test/jtreg-ext/requires/VMProps.java --- a/test/jtreg-ext/requires/VMProps.java Tue Oct 01 18:53:13 2019 -0400 +++ b/test/jtreg-ext/requires/VMProps.java Tue Oct 01 23:54:39 2019 -0400 @@ -235,7 +235,22 @@ */ protected String vmJvmci() { // builds with jvmci have this flag - return "" + (WB.getBooleanVMFlag("EnableJVMCI") != null); + if (WB.getBooleanVMFlag("EnableJVMCI") == null) { + return "false"; + } + + switch (GC.selected()) { + case Serial: + case Parallel: + case G1: + // These GCs are supported with JVMCI + return "true"; + default: + break; + } + + // Every other GC is not supported + return "false"; } /** @@ -356,7 +371,24 @@ } else { jaotc = bin.resolve("jaotc"); } - return "" + Files.exists(jaotc); + + if (!Files.exists(jaotc)) { + // No jaotc => no AOT + return "false"; + } + + switch (GC.selected()) { + case Serial: + case Parallel: + case G1: + // These GCs are supported with AOT + return "true"; + default: + break; + } + + // Every other GC is not supported + return "false"; } /* diff -r 788704ff2559 -r a44c029e85db test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/math/FpRoundingBenchmark.java Tue Oct 01 23:54:39 2019 -0400 @@ -0,0 +1,78 @@ +// +// 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 +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// +package org.openjdk.bench.java.math; + +import java.util.Random; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class FpRoundingBenchmark { + + @Param({"1024"}) + public int TESTSIZE; + + public double[] DargV1; + + public double[] Res; + + public final double[] DspecialVals = { + 0.0, -0.0, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY}; + + @Setup(Level.Trial) + public void BmSetup() { + int i = 0; + Random r = new Random(1024); + DargV1 = new double[TESTSIZE]; + Res = new double[TESTSIZE]; + + for (; i < DspecialVals.length; i++) { + DargV1[i] = DspecialVals[i]; + } + + for (; i < TESTSIZE; i++) { + DargV1[i] = r.nextDouble()*TESTSIZE; + } + } + + @Benchmark + public void testceil(Blackhole bh) { + for (int i = 0; i < TESTSIZE; i++) + Res[i] = Math.ceil(DargV1[i]); + } + + @Benchmark + public void testfloor(Blackhole bh) { + for (int i = 0; i < TESTSIZE; i++) + Res[i] = Math.floor(DargV1[i]); + } + + @Benchmark + public void testrint(Blackhole bh) { + for (int i = 0; i < TESTSIZE; i++) + Res[i] = Math.rint(DargV1[i]); + } +}