# HG changeset patch # User Gilles Duboscq # Date 1486397937 -3600 # Node ID 9b69cec6d01b85dd21552db5a899a5768096211e # Parent 9a740aa0d87b5db4358363c5f1271fed2a78d9ee# Parent 90f94521c3515e5f27af0ab9b31d036e88bb322a Merge with jdk8u121-b13 diff -r 9a740aa0d87b -r 9b69cec6d01b .hgtags --- a/.hgtags Sat Feb 04 15:24:10 2017 +0100 +++ b/.hgtags Mon Feb 06 17:18:57 2017 +0100 @@ -895,6 +895,10 @@ f6daf04c0f48dab5420ad63d21da82a7fa4e3ad7 jdk8u102-b13 ac29c9c1193aef5d480b200ed94c5d579243c17b jdk8u102-b14 96e1c72fc617d3c6c125bcfc9182f77fc6aa38e6 jdk8u102-b31 +c8988d2e4212583ec0f04591c8e241ad3cf95674 jdk8u102-b32 +9050d85e29600400ce4ba2b4db9616388082ae08 jdk8u102-b33 +b678b66d1538af31bac7cf5e74c029395607decd jdk8u102-b34 +8a2db0a6c499250050b59f9a47acd9ea80de92c2 jdk8u102-b35 ceecf88e5c2c09bfabf5926581e6d0b0f65f5148 jdk8u111-b00 e73d79ce00e4a0451e464c7a73d9c911d01e169a jdk8u111-b01 d584a614818562e1187e1a15c202aec01491caeb jdk8u111-b02 @@ -910,6 +914,36 @@ 055bc2a065a503e8714ff7ad27e6197dc0339efa jdk8u111-b12 c3b42c43c230f10e79ae850ee9062fe86d3c75c9 jdk8u111-b13 05a6a5823aa58a0a4720a328a9db484f21d573bc jdk8u111-b14 +b09a69142dd3bf78ca66bb0c99046ca7cccbdda9 jdk8u112-b00 +cf1faa9100dd8c8df6e1a604aaf613d037f51ebf jdk8u112-b01 +f22b5be95347c669a1463d9e05ec3bf11420208e jdk8u112-b02 +f2f59d888427b1db336766bc8cd272f2b2d84e1a jdk8u112-b03 +c171546c49b5ff57bcb74bb54e8860647f83f268 jdk8u112-b04 +4b7af794466ba22461ed043a1394df43e4993c4f jdk8u112-b06 +55ed9b0a35e4ad4bb5ca3f393f6749e81ad9fef0 jdk8u112-b07 +670f8169b83c6af14339fe37b2a2b8384dc2149b jdk8u112-b08 +1ccd27199595fedefcd1ca4a335e049887c63107 jdk8u112-b09 +2de719469e959ae1f7bd4fd64af8470f1d03d3bb jdk8u112-b10 +c2ca4df6580822835f3b21436b79e123910c4eb5 jdk8u112-b11 +44dcadfb9e7038a1ae288a99a728526ed97d2b7c jdk8u112-b12 +7bc1061f52cfc5ce4cbfd42dd2dcdc91e7efce72 jdk8u112-b13 +c2c4db2a42a215c98a4f027edb8bbb00dd62d9b9 jdk8u112-b14 +b28d012a24cab8f4ceeee0c9d3252969757423ed jdk8u112-b15 +e134dc1879b72124e478be01680b0646a2fbf585 jdk8u112-b16 +87440ed4e1de7753a436f957d35555d8b4e26f1d jdk8u112-b31 +3b0e5f01891f5ebbf67797b1aae786196f1bb4f6 jdk8u121-b00 +251a2493b1857f2ff4f11eab2dfd8b2fe8ed441b jdk8u121-b01 +70c4a50f576a01ec975d0a02b3642ee33db39ed8 jdk8u121-b02 +fa3bb4153a28b45a7a80cbf1058979b8f1c8b104 jdk8u121-b03 +35cff8508ca15dc18c598501cab160aee7220d44 jdk8u121-b04 +f71447f104ce7b018a08bf1cf385438525744d13 jdk8u121-b05 +49a2fc91c46f3d73aac7dbd420a4a007fe453ef8 jdk8u121-b06 +f31c7533cfcb55acfb8dc5b31779d3a64708f5ce jdk8u121-b07 +02a3d0dcbeddd8507d9a4b1f5a9f83aca75e5acb jdk8u121-b08 +8cae1bdbd73cb1a84afad07a8e18467f56560bc4 jdk8u121-b09 +f26f6895c9dfb32dfb4c228d69b371d8ab118536 jdk8u121-b10 +11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11 +b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12 b124e22eb772806c13d942cc110de38da0108147 graal-0.1 483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2 9535eccd2a115f6c6f0b15efb508b11ff74cc0d3 graal-0.3 diff -r 9a740aa0d87b -r 9b69cec6d01b LICENSE --- a/LICENSE Sat Feb 04 15:24:10 2017 +0100 +++ b/LICENSE Mon Feb 06 17:18:57 2017 +0100 @@ -3,7 +3,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -287,8 +287,8 @@ more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/ppc/vm/compiledIC_ppc.cpp --- a/src/cpu/ppc/vm/compiledIC_ppc.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/ppc/vm/compiledIC_ppc.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -94,7 +94,7 @@ const int IC_pos_in_java_to_interp_stub = 8; #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { #ifdef COMPILER2 // Get the mark within main instrs section which is set to the address of the call. address call_addr = cbuf.insts_mark(); @@ -106,8 +106,7 @@ // Start the stub. address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); if (stub == NULL) { - Compile::current()->env()->record_out_of_memory_failure(); - return; + return NULL; // CodeCache is full } // For java_to_interp stubs we use R11_scratch1 as scratch register @@ -149,6 +148,7 @@ // End the stub. __ end_a_stub(); + return stub; #else ShouldNotReachHere(); #endif diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/ppc/vm/ppc.ad --- a/src/cpu/ppc/vm/ppc.ad Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/ppc/vm/ppc.ad Mon Feb 06 17:18:57 2017 +0100 @@ -1171,7 +1171,7 @@ // Start the stub. address stub = __ start_a_stub(Compile::MAX_stubs_size/2); if (stub == NULL) { - Compile::current()->env()->record_out_of_memory_failure(); + ciEnv::current()->record_failure("CodeCache is full"); return; } @@ -1249,7 +1249,7 @@ // Emit the trampoline stub which will be related to the branch-and-link below. CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset); - if (Compile::current()->env()->failing()) { return offsets; } // Code cache may be full. + if (ciEnv::current()->failing()) { return offsets; } // Code cache may be full. __ relocate(rtype); } @@ -3488,7 +3488,7 @@ // Emit the trampoline stub which will be related to the branch-and-link below. CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); - if (Compile::current()->env()->failing()) { return; } // Code cache may be full. + if (ciEnv::current()->failing()) { return; } // Code cache may be full. __ relocate(_optimized_virtual ? relocInfo::opt_virtual_call_type : relocInfo::static_call_type); } @@ -3501,7 +3501,11 @@ __ bl(__ pc()); // Emits a relocation. // The stub for call to interpreter. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} @@ -3546,7 +3550,11 @@ assert(_method, "execute next statement conditionally"); // The stub for call to interpreter. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } // Restore original sp. __ ld(R11_scratch1, 0, R1_SP); // Load caller sp. @@ -5461,7 +5469,7 @@ %} // Match loading integer and casting it to long. -instruct loadI2L(iRegLdst dst, memory mem) %{ +instruct loadI2L(iRegLdst dst, memoryAlg4 mem) %{ match(Set dst (ConvI2L (LoadI mem))); predicate(_kids[0]->_leaf->as_Load()->is_unordered()); ins_cost(MEMORY_REF_COST); @@ -5477,7 +5485,7 @@ %} // Match loading integer and casting it to long - acquire. -instruct loadI2L_ac(iRegLdst dst, memory mem) %{ +instruct loadI2L_ac(iRegLdst dst, memoryAlg4 mem) %{ match(Set dst (ConvI2L (LoadI mem))); ins_cost(3*MEMORY_REF_COST); diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp --- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -431,6 +431,9 @@ __ mov(length()->as_register(), O4); ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } __ call(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); __ delayed()->nop(); diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/sparc/vm/compiledIC_sparc.cpp --- a/src/cpu/sparc/vm/compiledIC_sparc.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/sparc/vm/compiledIC_sparc.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -53,7 +53,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { // Stub is fixed up when the corresponding call is converted from calling // compiled code to calling interpreted code. // set (empty), G5 @@ -65,9 +65,10 @@ MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(to_interp_stub_size()); - guarantee(base != NULL, "out of space"); + address base = __ start_a_stub(to_interp_stub_size()); + if (base == NULL) { + return NULL; // CodeBuffer::expand failed. + } // Static stub relocation stores the instruction address of the call. __ relocate(static_stub_Relocation::spec(mark)); @@ -80,10 +81,11 @@ __ delayed()->nop(); - assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); + assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); // Update current stubs pointer and restore code_end. __ end_a_stub(); + return base; } #undef __ diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/sparc/vm/sparc.ad Mon Feb 06 17:18:57 2017 +0100 @@ -1775,9 +1775,11 @@ AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point()); MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_exception_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed + address base = __ start_a_stub(size_exception_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } int offset = __ offset(); @@ -1798,9 +1800,11 @@ AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack()); MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_deopt_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed + address base = __ start_a_stub(size_deopt_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } int offset = __ offset(); __ save_frame(0); @@ -2601,7 +2605,12 @@ emit_call_reloc(cbuf, $meth$$method, relocInfo::static_call_type); } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + // Stub does not fit into scratch buffer if TraceJumps is enabled + if (stub == NULL && !(TraceJumps && Compile::current()->in_scratch_emit_size())) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/c1_CodeStubs_x86.cpp --- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -502,6 +502,9 @@ ce->align_call(lir_static_call); ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); __ call(resolve); diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/compiledIC_x86.cpp --- a/src/cpu/x86/vm/compiledIC_x86.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/x86/vm/compiledIC_x86.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -50,7 +50,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { // Stub is fixed up when the corresponding call is converted from // calling compiled code to calling interpreted code. // movq rbx, 0 @@ -64,10 +64,10 @@ // That's why we must use the macroassembler to generate a stub. MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(to_interp_stub_size()); - guarantee(base != NULL, "out of space"); - + address base = __ start_a_stub(to_interp_stub_size()); + if (base == NULL) { + return NULL; // CodeBuffer::expand failed. + } // Static stub relocation stores the instruction address of the call. __ relocate(static_stub_Relocation::spec(mark), Assembler::imm_operand); // Static stub relocation also tags the Method* in the code-stream. @@ -75,10 +75,11 @@ // This is recognized as unresolved by relocs/nativeinst/ic code. __ jump(RuntimeAddress(__ pc())); - assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); + assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size"); // Update current stubs pointer and restore insts_end. __ end_a_stub(); + return base; } #undef __ diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/macroAssembler_x86.cpp diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/x86.ad --- a/src/cpu/x86/vm/x86.ad Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/x86/vm/x86.ad Mon Feb 06 17:18:57 2017 +0100 @@ -550,7 +550,10 @@ // That's why we must use the macroassembler to generate a handler. MacroAssembler _masm(&cbuf); address base = __ start_a_stub(size_exception_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } int offset = __ offset(); __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); @@ -565,7 +568,10 @@ // That's why we must use the macroassembler to generate a handler. MacroAssembler _masm(&cbuf); address base = __ start_a_stub(size_deopt_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } int offset = __ offset(); #ifdef _LP64 diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/x86/vm/x86_32.ad Mon Feb 06 17:18:57 2017 +0100 @@ -1870,7 +1870,11 @@ static_call_Relocation::spec(), RELOC_IMM32 ); } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/x86/vm/x86_64.ad Mon Feb 06 17:18:57 2017 +0100 @@ -2125,7 +2125,11 @@ } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/zero/vm/compiledIC_zero.cpp --- a/src/cpu/zero/vm/compiledIC_zero.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/zero/vm/compiledIC_zero.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -60,8 +60,9 @@ // ---------------------------------------------------------------------------- -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { ShouldNotReachHere(); // Only needed for COMPILER2. + return NULL; } int CompiledStaticCall::to_interp_stub_size() { diff -r 9a740aa0d87b -r 9b69cec6d01b src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -220,9 +220,16 @@ // Push our result for (int i = 0; i < result_slots; i++) { // Adjust result to smaller - intptr_t res = result[-i]; + union { + intptr_t res; + jint res_jint; + }; + res = result[-i]; if (result_slots == 1) { - res = narrow(method->result_type(), res); + BasicType t = method->result_type(); + if (is_subword_type(t)) { + res_jint = (jint)narrow(t, res_jint); + } } stack->push(res); } diff -r 9a740aa0d87b -r 9b69cec6d01b src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/os/linux/vm/os_linux.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -3047,6 +3047,48 @@ return addr == MAP_FAILED ? NULL : addr; } +// Allocate (using mmap, NO_RESERVE, with small pages) at either a given request address +// (req_addr != NULL) or with a given alignment. +// - bytes shall be a multiple of alignment. +// - req_addr can be NULL. If not NULL, it must be a multiple of alignment. +// - alignment sets the alignment at which memory shall be allocated. +// It must be a multiple of allocation granularity. +// Returns address of memory or NULL. If req_addr was not NULL, will only return +// req_addr or NULL. +static char* anon_mmap_aligned(size_t bytes, size_t alignment, char* req_addr) { + + size_t extra_size = bytes; + if (req_addr == NULL && alignment > 0) { + extra_size += alignment; + } + + char* start = (char*) ::mmap(req_addr, extra_size, PROT_NONE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, + -1, 0); + if (start == MAP_FAILED) { + start = NULL; + } else { + if (req_addr != NULL) { + if (start != req_addr) { + ::munmap(start, extra_size); + start = NULL; + } + } else { + char* const start_aligned = (char*) align_ptr_up(start, alignment); + char* const end_aligned = start_aligned + bytes; + char* const end = start + extra_size; + if (start_aligned > start) { + ::munmap(start, start_aligned - start); + } + if (end_aligned < end) { + ::munmap(end_aligned, end - end_aligned); + } + start = start_aligned; + } + } + return start; +} + // Don't update _highest_vm_reserved_address, because there might be memory // regions above addr + size. If so, releasing a memory region only creates // a hole in the address space, it doesn't help prevent heap-stack collision. @@ -3331,54 +3373,133 @@ #define SHM_HUGETLB 04000 #endif +#define shm_warning_format(format, ...) \ + do { \ + if (UseLargePages && \ + (!FLAG_IS_DEFAULT(UseLargePages) || \ + !FLAG_IS_DEFAULT(UseSHM) || \ + !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { \ + warning(format, __VA_ARGS__); \ + } \ + } while (0) + +#define shm_warning(str) shm_warning_format("%s", str) + +#define shm_warning_with_errno(str) \ + do { \ + int err = errno; \ + shm_warning_format(str " (error = %d)", err); \ + } while (0) + +static char* shmat_with_alignment(int shmid, size_t bytes, size_t alignment) { + assert(is_size_aligned(bytes, alignment), "Must be divisible by the alignment"); + + if (!is_size_aligned(alignment, SHMLBA)) { + assert(false, "Code below assumes that alignment is at least SHMLBA aligned"); + return NULL; + } + + // To ensure that we get 'alignment' aligned memory from shmat, + // we pre-reserve aligned virtual memory and then attach to that. + + char* pre_reserved_addr = anon_mmap_aligned(bytes, alignment, NULL); + if (pre_reserved_addr == NULL) { + // Couldn't pre-reserve aligned memory. + shm_warning("Failed to pre-reserve aligned memory for shmat."); + return NULL; + } + + // SHM_REMAP is needed to allow shmat to map over an existing mapping. + char* addr = (char*)shmat(shmid, pre_reserved_addr, SHM_REMAP); + + if ((intptr_t)addr == -1) { + int err = errno; + shm_warning_with_errno("Failed to attach shared memory."); + + assert(err != EACCES, "Unexpected error"); + assert(err != EIDRM, "Unexpected error"); + assert(err != EINVAL, "Unexpected error"); + + // Since we don't know if the kernel unmapped the pre-reserved memory area + // we can't unmap it, since that would potentially unmap memory that was + // mapped from other threads. + return NULL; + } + + return addr; +} + +static char* shmat_at_address(int shmid, char* req_addr) { + if (!is_ptr_aligned(req_addr, SHMLBA)) { + assert(false, "Requested address needs to be SHMLBA aligned"); + return NULL; + } + + char* addr = (char*)shmat(shmid, req_addr, 0); + + if ((intptr_t)addr == -1) { + shm_warning_with_errno("Failed to attach shared memory."); + return NULL; + } + + return addr; +} + +static char* shmat_large_pages(int shmid, size_t bytes, size_t alignment, char* req_addr) { + // If a req_addr has been provided, we assume that the caller has already aligned the address. + if (req_addr != NULL) { + assert(is_ptr_aligned(req_addr, os::large_page_size()), "Must be divisible by the large page size"); + assert(is_ptr_aligned(req_addr, alignment), "Must be divisible by given alignment"); + return shmat_at_address(shmid, req_addr); + } + + // Since shmid has been setup with SHM_HUGETLB, shmat will automatically + // return large page size aligned memory addresses when req_addr == NULL. + // However, if the alignment is larger than the large page size, we have + // to manually ensure that the memory returned is 'alignment' aligned. + if (alignment > os::large_page_size()) { + assert(is_size_aligned(alignment, os::large_page_size()), "Must be divisible by the large page size"); + return shmat_with_alignment(shmid, bytes, alignment); + } else { + return shmat_at_address(shmid, NULL); + } +} + char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec) { // "exec" is passed in but not used. Creating the shared image for // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages && UseSHM, "only for SHM large pages"); assert(is_ptr_aligned(req_addr, os::large_page_size()), "Unaligned address"); - - if (!is_size_aligned(bytes, os::large_page_size()) || alignment > os::large_page_size()) { + assert(is_ptr_aligned(req_addr, alignment), "Unaligned address"); + + if (!is_size_aligned(bytes, os::large_page_size())) { return NULL; // Fallback to small pages. } - key_t key = IPC_PRIVATE; - char *addr; - - bool warn_on_failure = UseLargePages && - (!FLAG_IS_DEFAULT(UseLargePages) || - !FLAG_IS_DEFAULT(UseSHM) || - !FLAG_IS_DEFAULT(LargePageSizeInBytes) - ); - char msg[128]; - // Create a large shared memory region to attach to based on size. - // Currently, size is the total size of the heap - int shmid = shmget(key, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W); + // Currently, size is the total size of the heap. + int shmid = shmget(IPC_PRIVATE, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W); if (shmid == -1) { - // Possible reasons for shmget failure: - // 1. shmmax is too small for Java heap. - // > check shmmax value: cat /proc/sys/kernel/shmmax - // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax - // 2. not enough large page memory. - // > check available large pages: cat /proc/meminfo - // > increase amount of large pages: - // echo new_value > /proc/sys/vm/nr_hugepages - // Note 1: different Linux may use different name for this property, - // e.g. on Redhat AS-3 it is "hugetlb_pool". - // Note 2: it's possible there's enough physical memory available but - // they are so fragmented after a long run that they can't - // coalesce into large pages. Try to reserve large pages when - // the system is still "fresh". - if (warn_on_failure) { - jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); - warning("%s", msg); - } - return NULL; - } - - // attach to the region - addr = (char*)shmat(shmid, req_addr, 0); - int err = errno; + // Possible reasons for shmget failure: + // 1. shmmax is too small for Java heap. + // > check shmmax value: cat /proc/sys/kernel/shmmax + // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax + // 2. not enough large page memory. + // > check available large pages: cat /proc/meminfo + // > increase amount of large pages: + // echo new_value > /proc/sys/vm/nr_hugepages + // Note 1: different Linux may use different name for this property, + // e.g. on Redhat AS-3 it is "hugetlb_pool". + // Note 2: it's possible there's enough physical memory available but + // they are so fragmented after a long run that they can't + // coalesce into large pages. Try to reserve large pages when + // the system is still "fresh". + shm_warning_with_errno("Failed to reserve shared memory."); + return NULL; + } + + // Attach to the region. + char* addr = shmat_large_pages(shmid, bytes, alignment, req_addr); // Remove shmid. If shmat() is successful, the actual shared memory segment // will be deleted when it's detached by shmdt() or when the process @@ -3386,14 +3507,6 @@ // segment immediately. shmctl(shmid, IPC_RMID, NULL); - if ((intptr_t)addr == -1) { - if (warn_on_failure) { - jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); - warning("%s", msg); - } - return NULL; - } - return addr; } @@ -3433,22 +3546,22 @@ return addr; } +// Reserve memory using mmap(MAP_HUGETLB). +// - bytes shall be a multiple of alignment. +// - req_addr can be NULL. If not NULL, it must be a multiple of alignment. +// - alignment sets the alignment at which memory shall be allocated. +// It must be a multiple of allocation granularity. +// Returns address of memory or NULL. If req_addr was not NULL, will only return +// req_addr or NULL. char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec) { size_t large_page_size = os::large_page_size(); - assert(bytes >= large_page_size, "Shouldn't allocate large pages for small sizes"); - // Allocate small pages. - - char* start; - if (req_addr != NULL) { - assert(is_ptr_aligned(req_addr, alignment), "Must be"); - assert(is_size_aligned(bytes, alignment), "Must be"); - start = os::reserve_memory(bytes, req_addr); - assert(start == NULL || start == req_addr, "Must be"); - } else { - start = os::reserve_memory_aligned(bytes, alignment); - } + assert(is_ptr_aligned(req_addr, alignment), "Must be"); + assert(is_size_aligned(bytes, alignment), "Must be"); + + // First reserve - but not commit - the address range in small pages. + char* const start = anon_mmap_aligned(bytes, alignment, req_addr); if (start == NULL) { return NULL; @@ -3456,13 +3569,6 @@ assert(is_ptr_aligned(start, alignment), "Must be"); - if (MemTracker::tracking_level() > NMT_minimal) { - // os::reserve_memory_special will record this memory area. - // Need to release it here to prevent overlapping reservations. - Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - tkr.record((address)start, bytes); - } - char* end = start + bytes; // Find the regions of the allocated chunk that can be promoted to large pages. @@ -3482,9 +3588,9 @@ int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; - void* result; + // Commit small-paged leading area. if (start != lp_start) { result = ::mmap(start, lp_start - start, prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, @@ -3495,11 +3601,12 @@ } } + // Commit large-paged area. result = ::mmap(lp_start, lp_bytes, prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_HUGETLB, -1, 0); if (result == MAP_FAILED) { - warn_on_large_pages_failure(req_addr, bytes, errno); + warn_on_large_pages_failure(lp_start, lp_bytes, errno); // If the mmap above fails, the large pages region will be unmapped and we // have regions before and after with small pages. Release these regions. // @@ -3512,6 +3619,7 @@ return NULL; } + // Commit small-paged trailing area. if (lp_end != end) { result = ::mmap(lp_end, end - lp_end, prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, @@ -3528,7 +3636,7 @@ char* os::Linux::reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, char* req_addr, bool exec) { assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages"); assert(is_ptr_aligned(req_addr, alignment), "Must be"); - assert(is_power_of_2(alignment), "Must be"); + assert(is_size_aligned(alignment, os::vm_allocation_granularity()), "Must be"); assert(is_power_of_2(os::large_page_size()), "Must be"); assert(bytes >= os::large_page_size(), "Shouldn't allocate large pages for small sizes"); @@ -6102,47 +6210,100 @@ } } - static void test_reserve_memory_special_huge_tlbfs_mixed(size_t size, size_t alignment) { - if (!UseHugeTLBFS) { - return; - } - - test_log("test_reserve_memory_special_huge_tlbfs_mixed(" SIZE_FORMAT ", " SIZE_FORMAT ")", - size, alignment); - - assert(size >= os::large_page_size(), "Incorrect input to test"); - - char* addr = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false); - - if (addr != NULL) { - small_page_write(addr, size); - - os::Linux::release_memory_special_huge_tlbfs(addr, size); - } - } - - static void test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(size_t size) { - size_t lp = os::large_page_size(); - size_t ag = os::vm_allocation_granularity(); - - for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) { - test_reserve_memory_special_huge_tlbfs_mixed(size, alignment); - } - } - static void test_reserve_memory_special_huge_tlbfs_mixed() { size_t lp = os::large_page_size(); size_t ag = os::vm_allocation_granularity(); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + ag); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + lp / 2); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + ag); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 - ag); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + lp / 2); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10); - test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10 + lp / 2); + // sizes to test + const size_t sizes[] = { + lp, lp + ag, lp + lp / 2, lp * 2, + lp * 2 + ag, lp * 2 - ag, lp * 2 + lp / 2, + lp * 10, lp * 10 + lp / 2 + }; + const int num_sizes = sizeof(sizes) / sizeof(size_t); + + // For each size/alignment combination, we test three scenarios: + // 1) with req_addr == NULL + // 2) with a non-null req_addr at which we expect to successfully allocate + // 3) with a non-null req_addr which contains a pre-existing mapping, at which we + // expect the allocation to either fail or to ignore req_addr + + // Pre-allocate two areas; they shall be as large as the largest allocation + // and aligned to the largest alignment we will be testing. + const size_t mapping_size = sizes[num_sizes - 1] * 2; + char* const mapping1 = (char*) ::mmap(NULL, mapping_size, + PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, + -1, 0); + assert(mapping1 != MAP_FAILED, "should work"); + + char* const mapping2 = (char*) ::mmap(NULL, mapping_size, + PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, + -1, 0); + assert(mapping2 != MAP_FAILED, "should work"); + + // Unmap the first mapping, but leave the second mapping intact: the first + // mapping will serve as a value for a "good" req_addr (case 2). The second + // mapping, still intact, as "bad" req_addr (case 3). + ::munmap(mapping1, mapping_size); + + // Case 1 + test_log("%s, req_addr NULL:", __FUNCTION__); + test_log("size align result"); + + for (int i = 0; i < num_sizes; i++) { + const size_t size = sizes[i]; + for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) { + char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false); + test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " -> " PTR_FORMAT " %s", + size, alignment, p, (p != NULL ? "" : "(failed)")); + if (p != NULL) { + assert(is_ptr_aligned(p, alignment), "must be"); + small_page_write(p, size); + os::Linux::release_memory_special_huge_tlbfs(p, size); + } + } + } + + // Case 2 + test_log("%s, req_addr non-NULL:", __FUNCTION__); + test_log("size align req_addr result"); + + for (int i = 0; i < num_sizes; i++) { + const size_t size = sizes[i]; + for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) { + char* const req_addr = (char*) align_ptr_up(mapping1, alignment); + char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false); + test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s", + size, alignment, req_addr, p, + ((p != NULL ? (p == req_addr ? "(exact match)" : "") : "(failed)"))); + if (p != NULL) { + assert(p == req_addr, "must be"); + small_page_write(p, size); + os::Linux::release_memory_special_huge_tlbfs(p, size); + } + } + } + + // Case 3 + test_log("%s, req_addr non-NULL with preexisting mapping:", __FUNCTION__); + test_log("size align req_addr result"); + + for (int i = 0; i < num_sizes; i++) { + const size_t size = sizes[i]; + for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) { + char* const req_addr = (char*) align_ptr_up(mapping2, alignment); + char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false); + test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s", + size, alignment, req_addr, p, + ((p != NULL ? "" : "(failed)"))); + // as the area around req_addr contains already existing mappings, the API should always + // return NULL (as per contract, it cannot return another address) + assert(p == NULL, "must be"); + } + } + + ::munmap(mapping2, mapping_size); + } static void test_reserve_memory_special_huge_tlbfs() { diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/c1/c1_LIRAssembler.cpp --- a/src/share/vm/c1/c1_LIRAssembler.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/c1/c1_LIRAssembler.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -464,6 +464,7 @@ // emit the static call stub stuff out of line emit_static_call_stub(); + CHECK_BAILOUT(); switch (op->code()) { case lir_static_call: diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -537,6 +537,9 @@ int name_index = cp->name_ref_index_at(index); Symbol* name = cp->symbol_at(name_index); Symbol* sig = cp->symbol_at(sig_index); + guarantee_property(sig->utf8_length() != 0, + "Illegal zero length constant pool entry at %d in class %s", + sig_index, CHECK_(nullHandle)); if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) { verify_legal_method_signature(name, sig, CHECK_(nullHandle)); } else { @@ -560,8 +563,9 @@ verify_legal_field_name(name, CHECK_(nullHandle)); if (_need_verify && _major_version >= JAVA_7_VERSION) { // Signature is verified above, when iterating NameAndType_info. - // Need only to be sure it's the right type. - if (signature->byte_at(0) == JVM_SIGNATURE_FUNC) { + // Need only to be sure it's non-zero length and the right type. + if (signature->utf8_length() == 0 || + signature->byte_at(0) == JVM_SIGNATURE_FUNC) { throwIllegalSignature( "Field", name, signature, CHECK_(nullHandle)); } @@ -572,8 +576,9 @@ verify_legal_method_name(name, CHECK_(nullHandle)); if (_need_verify && _major_version >= JAVA_7_VERSION) { // Signature is verified above, when iterating NameAndType_info. - // Need only to be sure it's the right type. - if (signature->byte_at(0) != JVM_SIGNATURE_FUNC) { + // Need only to be sure it's non-zero length and the right type. + if (signature->utf8_length() == 0 || + signature->byte_at(0) != JVM_SIGNATURE_FUNC) { throwIllegalSignature( "Method", name, signature, CHECK_(nullHandle)); } @@ -584,8 +589,7 @@ // 4509014: If a class method name begins with '<', it must be "". assert(name != NULL, "method name in constant pool is null"); unsigned int name_len = name->utf8_length(); - assert(name_len > 0, "bad method name"); // already verified as legal name - if (name->byte_at(0) == '<') { + if (name_len != 0 && name->byte_at(0) == '<') { if (name != vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad method name at constant pool index %u in class file %s", @@ -940,11 +944,12 @@ runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, CHECK); - cfs->skip_u1(runtime_visible_annotations_length, CHECK); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer(); @@ -1651,6 +1656,11 @@ return index; } +// Safely increment index by val if does not pass limit +#define SAFE_ADD(index, limit, val) \ +if (index >= limit - val) return limit; \ +index += val; + // Skip an annotation value. Return >=limit if there is any problem. int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { // value := switch (tag:u1) { @@ -1661,19 +1671,19 @@ // case @: annotation; // case s: s_con:u2; // } - if ((index += 1) >= limit) return limit; // read tag + SAFE_ADD(index, limit, 1); // read tag u1 tag = buffer[index-1]; switch (tag) { case 'B': case 'C': case 'I': case 'S': case 'Z': case 'D': case 'F': case 'J': case 'c': case 's': - index += 2; // skip con or s_con + SAFE_ADD(index, limit, 2); // skip con or s_con break; case 'e': - index += 4; // skip e_class, e_name + SAFE_ADD(index, limit, 4); // skip e_class, e_name break; case '[': { - if ((index += 2) >= limit) return limit; // read nval + SAFE_ADD(index, limit, 2); // read nval int nval = Bytes::get_Java_u2(buffer+index-2); while (--nval >= 0 && index < limit) { index = skip_annotation_value(buffer, limit, index); @@ -1695,8 +1705,8 @@ ClassFileParser::AnnotationCollector* coll, TRAPS) { // annotations := do(nann:u2) {annotation} - int index = 0; - if ((index += 2) >= limit) return; // read nann + int index = 2; + if (index >= limit) return; // read nann int nann = Bytes::get_Java_u2(buffer+index-2); enum { // initial annotation layout atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' @@ -1715,7 +1725,8 @@ s_size = 9, min_size = 6 // smallest possible size (zero members) }; - while ((--nann) >= 0 && (index-2 + min_size <= limit)) { + // Cannot add min_size to index in case of overflow MAX_INT + while ((--nann) >= 0 && (index-2 <= limit - min_size)) { int index0 = index; index = skip_annotation(buffer, limit, index); u1* abase = buffer + index0; @@ -2326,10 +2337,11 @@ runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK_(nullHandle)); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, &parsed_annotations, CHECK_(nullHandle)); - cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = method_attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer(); @@ -2955,11 +2967,12 @@ runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, CHECK); - cfs->skip_u1(runtime_visible_annotations_length, CHECK); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer(); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/classLoaderData.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -813,6 +813,12 @@ // called on all alive classes. See the comment in ClassLoaderDataGraph::clean_metaspaces. cld->free_deallocate_list(); } + + // In some rare cases items added to the unloading list will not be freed elsewhere. + // To keep it simple, walk the _unloading list also. + for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) { + cld->free_deallocate_list(); + } } // CDS support diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/classLoaderData.inline.hpp --- a/src/share/vm/classfile/classLoaderData.inline.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/classLoaderData.inline.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -40,7 +40,7 @@ inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader, TRAPS) { - assert(loader() != NULL,"Must be a class loader"); + guarantee(loader() != NULL && loader()->is_oop(), "Loader must be oop"); // Gets the class loader data out of the java/lang/ClassLoader object, if non-null // it's already in the loader_data, so no need to add ClassLoaderData* loader_data= java_lang_ClassLoader::loader_data(loader()); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/stackMapFrame.cpp --- a/src/share/vm/classfile/stackMapFrame.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/stackMapFrame.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -155,47 +155,8 @@ return i; } -bool StackMapFrame::has_flag_match_exception( - const StackMapFrame* target) const { - // We allow flags of {UninitThis} to assign to {} if-and-only-if the - // target frame does not depend upon the current type. - // This is slightly too strict, as we need only enforce that the - // slots that were initialized by the (the things that were - // UninitializedThis before initialize_object() converted them) are unused. - // However we didn't save that information so we'll enforce this upon - // anything that might have been initialized. This is a rare situation - // and javac never generates code that would end up here, but some profilers - // (such as NetBeans) might, when adding exception handlers in - // methods to cover the invokespecial instruction. See 7020118. - - assert(max_locals() == target->max_locals() && - stack_size() == target->stack_size(), "StackMap sizes must match"); - - VerificationType top = VerificationType::top_type(); - VerificationType this_type = verifier()->current_type(); - - if (!flag_this_uninit() || target->flags() != 0) { - return false; - } - - for (int i = 0; i < target->locals_size(); ++i) { - if (locals()[i] == this_type && target->locals()[i] != top) { - return false; - } - } - - for (int i = 0; i < target->stack_size(); ++i) { - if (stack()[i] == this_type && target->stack()[i] != top) { - return false; - } - } - - return true; -} - bool StackMapFrame::is_assignable_to( - const StackMapFrame* target, bool is_exception_handler, - ErrorContext* ctx, TRAPS) const { + const StackMapFrame* target, ErrorContext* ctx, TRAPS) const { if (_max_locals != target->max_locals()) { *ctx = ErrorContext::locals_size_mismatch( _offset, (StackMapFrame*)this, (StackMapFrame*)target); @@ -226,8 +187,7 @@ return false; } - bool match_flags = (_flags | target->flags()) == target->flags(); - if (match_flags || is_exception_handler && has_flag_match_exception(target)) { + if ((_flags | target->flags()) == target->flags()) { return true; } else { *ctx = ErrorContext::bad_flags(target->offset(), diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/stackMapFrame.hpp --- a/src/share/vm/classfile/stackMapFrame.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/stackMapFrame.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,8 +167,7 @@ // Return true if this stack map frame is assignable to target. bool is_assignable_to( - const StackMapFrame* target, bool is_exception_handler, - ErrorContext* ctx, TRAPS) const; + const StackMapFrame* target, ErrorContext* ctx, TRAPS) const; inline void set_mark() { #ifdef ASSERT @@ -290,8 +289,6 @@ int is_assignable_to( VerificationType* src, VerificationType* target, int32_t len, TRAPS) const; - bool has_flag_match_exception(const StackMapFrame* target) const; - TypeOrigin stack_top_ctx(); void print_on(outputStream* str) const; diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/stackMapTable.cpp --- a/src/share/vm/classfile/stackMapTable.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/stackMapTable.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,26 +70,25 @@ bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, - bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { + bool match, bool update, ErrorContext* ctx, TRAPS) const { int index = get_index_from_offset(target); - return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); + return match_stackmap(frame, target, index, match, update, ctx, THREAD); } // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. -// handler is true if the frame in stackmap_table is for an exception handler. // -// The values of match and update are: _match__update__handler +// The values of match and update are: _match__update // -// checking a branch target: true false false -// checking an exception handler: true false true +// checking a branch target: true false +// checking an exception handler: true false // linear bytecode verification following an -// unconditional branch: false true false +// unconditional branch: false true // linear bytecode verification not following an -// unconditional branch: true true false +// unconditional branch: true true bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, int32_t frame_index, - bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { + bool match, bool update, ErrorContext* ctx, TRAPS) const { if (frame_index < 0 || frame_index >= _frame_count) { *ctx = ErrorContext::missing_stackmap(frame->offset()); frame->verifier()->verify_error( @@ -102,7 +101,7 @@ if (match) { // Has direct control flow from last instruction, need to match the two // frames. - result = frame->is_assignable_to(stackmap_frame, handler, + result = frame->is_assignable_to(stackmap_frame, ctx, CHECK_VERIFY_(frame->verifier(), result)); } if (update) { @@ -126,7 +125,7 @@ StackMapFrame* frame, int32_t target, TRAPS) const { ErrorContext ctx; bool match = match_stackmap( - frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); + frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { frame->verifier()->verify_error(ctx, "Inconsistent stackmap frames at branch target %d", target); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/stackMapTable.hpp --- a/src/share/vm/classfile/stackMapTable.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/stackMapTable.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,12 +74,12 @@ // specified offset. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, - bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; + bool match, bool update, ErrorContext* ctx, TRAPS) const; // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, int32_t frame_index, - bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; + bool match, bool update, ErrorContext* ctx, TRAPS) const; // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/verifier.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -504,19 +504,13 @@ stack_map_frame* sm_frame = sm_table->entries(); streamIndentor si2(ss); int current_offset = -1; - // Subtract two from StackMapAttribute length because the length includes - // two bytes for number of table entries. - size_t sm_table_space = method->stackmap_data()->length() - 2; + address end_of_sm_table = (address)sm_table + method->stackmap_data()->length(); for (u2 i = 0; i < sm_table->number_of_entries(); ++i) { ss->indent(); - size_t sm_frame_size = sm_frame->size(); - // If the size of the next stackmap exceeds the length of the entire - // stackmap table then print a truncated message and return. - if (sm_frame_size > sm_table_space) { + if (!sm_frame->verify((address)sm_frame, end_of_sm_table)) { sm_frame->print_truncated(ss, current_offset); return; } - sm_table_space -= sm_frame_size; sm_frame->print_on(ss, current_offset); ss->cr(); current_offset += sm_frame->offset_delta(); @@ -1820,7 +1814,7 @@ // If matched, current_frame will be updated by this method. bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, - !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0)); + !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); if (!matches) { // report type error verify_error(ctx, "Instruction type does not match stack map"); @@ -1867,7 +1861,7 @@ } ErrorContext ctx; bool matches = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this)); + new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); if (!matches) { verify_error(ctx, "Stack map does not match the one at " "exception handler %d", handler_pc); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -524,6 +524,7 @@ template(int_StringBuffer_signature, "(I)Ljava/lang/StringBuffer;") \ template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \ template(int_String_signature, "(I)Ljava/lang/String;") \ + template(codesource_permissioncollection_signature, "(Ljava/security/CodeSource;Ljava/security/PermissionCollection;)V") \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/code/compiledIC.hpp --- a/src/share/vm/code/compiledIC.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/code/compiledIC.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -320,7 +320,7 @@ friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site); // Code - static void emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL); + static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = NULL); static int to_interp_stub_size(); static int reloc_to_interp_stub(); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp --- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,9 @@ do { // Drain the overflow stack first, so other threads can steal. while (_refs->pop_overflow(ref)) { - dispatch_reference(ref); + if (!_refs->try_push_to_taskqueue(ref)) { + dispatch_reference(ref); + } } while (_refs->pop_local(ref)) { diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp --- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,10 +133,6 @@ } } -static size_t round_to_K(size_t value) { - return value / K; -} - class RegionTypeCounter VALUE_OBJ_CLASS_SPEC { private: const char* _name; @@ -187,8 +183,10 @@ size_t code_root_elems() const { return _code_root_elems; } void print_rs_mem_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions", - round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name); + out->print_cr(" "SIZE_FORMAT_W(8) "%s (%5.1f%%) by "SIZE_FORMAT" %s regions", + byte_size_in_proper_unit(rs_mem_size()), + proper_unit_for_byte_size(rs_mem_size()), + rs_mem_size_percent_of(total), amount(), _name); } void print_cards_occupied_info_on(outputStream * out, size_t total) { @@ -197,8 +195,10 @@ } void print_code_root_mem_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions", - round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name); + out->print_cr(" "SIZE_FORMAT_W(8) "%s (%5.1f%%) by "SIZE_FORMAT" %s regions", + byte_size_in_proper_unit(code_root_mem_size()), + proper_unit_for_byte_size(code_root_mem_size()), + code_root_mem_size_percent_of(total), amount(), _name); } void print_code_root_elems_info_on(outputStream * out, size_t total) { @@ -280,17 +280,23 @@ RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL }; out->print_cr("\n Current rem set statistics"); - out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K." - " Max = "SIZE_FORMAT"K.", - round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz())); + out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "%s." + " Max = " SIZE_FORMAT "%s.", + byte_size_in_proper_unit(total_rs_mem_sz()), + proper_unit_for_byte_size(total_rs_mem_sz()), + byte_size_in_proper_unit(max_rs_mem_sz()), + proper_unit_for_byte_size(max_rs_mem_sz())); + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_rs_mem_info_on(out, total_rs_mem_sz()); } - out->print_cr(" Static structures = "SIZE_FORMAT"K," - " free_lists = "SIZE_FORMAT"K.", - round_to_K(HeapRegionRemSet::static_mem_size()), - round_to_K(HeapRegionRemSet::fl_mem_size())); + out->print_cr(" Static structures = " SIZE_FORMAT "%s," + " free_lists = " SIZE_FORMAT "%s.", + byte_size_in_proper_unit(HeapRegionRemSet::static_mem_size()), + proper_unit_for_byte_size(HeapRegionRemSet::static_mem_size()), + byte_size_in_proper_unit(HeapRegionRemSet::fl_mem_size()), + proper_unit_for_byte_size(HeapRegionRemSet::fl_mem_size())); out->print_cr(" "SIZE_FORMAT" occupied cards represented.", total_cards_occupied()); @@ -301,17 +307,21 @@ // Largest sized rem set region statistics HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set(); out->print_cr(" Region with largest rem set = "HR_FORMAT", " - "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", + "size = "SIZE_FORMAT "%s, occupied = "SIZE_FORMAT "%s.", HR_FORMAT_PARAMS(max_rs_mem_sz_region()), - round_to_K(rem_set->mem_size()), - round_to_K(rem_set->occupied())); - + byte_size_in_proper_unit(rem_set->mem_size()), + proper_unit_for_byte_size(rem_set->mem_size()), + byte_size_in_proper_unit(rem_set->occupied()), + proper_unit_for_byte_size(rem_set->occupied())); // Strong code root statistics HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); - out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K." - " Max = "SIZE_FORMAT"K.", - round_to_K(total_code_root_mem_sz()), - round_to_K(max_code_root_rem_set->strong_code_roots_mem_size())); + out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "%s." + " Max = " SIZE_FORMAT "%s.", + byte_size_in_proper_unit(total_code_root_mem_sz()), + proper_unit_for_byte_size(total_code_root_mem_sz()), + byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()), + proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size())); + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); } @@ -323,10 +333,12 @@ } out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", " - "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", + "size = "SIZE_FORMAT "%s, num_elems = "SIZE_FORMAT".", HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), - round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()), - round_to_K(max_code_root_rem_set->strong_code_roots_list_length())); + byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()), + proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size()), + max_code_root_rem_set->strong_code_roots_list_length()); + } }; diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp --- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,22 +28,23 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/g1StringDedupTable.hpp" +#include "gc_implementation/shared/concurrentGCThread.hpp" #include "memory/gcLocker.hpp" #include "memory/padded.inline.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/mutexLocker.hpp" // -// Freelist in the deduplication table entry cache. Links table +// List of deduplication table entries. Links table // entries together using their _next fields. // -class G1StringDedupEntryFreeList : public CHeapObj { +class G1StringDedupEntryList : public CHeapObj { private: G1StringDedupEntry* _list; size_t _length; public: - G1StringDedupEntryFreeList() : + G1StringDedupEntryList() : _list(NULL), _length(0) { } @@ -63,6 +64,12 @@ return entry; } + G1StringDedupEntry* remove_all() { + G1StringDedupEntry* list = _list; + _list = NULL; + return list; + } + size_t length() { return _length; } @@ -84,43 +91,53 @@ // class G1StringDedupEntryCache : public CHeapObj { private: - // One freelist per GC worker to allow lock less freeing of - // entries while doing a parallel scan of the table. Using - // PaddedEnd to avoid false sharing. - PaddedEnd* _lists; - size_t _nlists; + // One cache/overflow list per GC worker to allow lock less freeing of + // entries while doing a parallel scan of the table. Using PaddedEnd to + // avoid false sharing. + size_t _nlists; + size_t _max_list_length; + PaddedEnd* _cached; + PaddedEnd* _overflowed; public: - G1StringDedupEntryCache(); + G1StringDedupEntryCache(size_t max_size); ~G1StringDedupEntryCache(); - // Get a table entry from the cache freelist, or allocate a new - // entry if the cache is empty. + // Set max number of table entries to cache. + void set_max_size(size_t max_size); + + // Get a table entry from the cache, or allocate a new entry if the cache is empty. G1StringDedupEntry* alloc(); - // Insert a table entry into the cache freelist. + // Insert a table entry into the cache. void free(G1StringDedupEntry* entry, uint worker_id); // Returns current number of entries in the cache. size_t size(); - // If the cache has grown above the given max size, trim it down - // and deallocate the memory occupied by trimmed of entries. - void trim(size_t max_size); + // Deletes overflowed entries. + void delete_overflowed(); }; -G1StringDedupEntryCache::G1StringDedupEntryCache() { - _nlists = MAX2(ParallelGCThreads, (size_t)1); - _lists = PaddedArray::create_unfreeable((uint)_nlists); +G1StringDedupEntryCache::G1StringDedupEntryCache(size_t max_size) : + _nlists(MAX2(ParallelGCThreads, (size_t)1)), + _max_list_length(0), + _cached(PaddedArray::create_unfreeable((uint)_nlists)), + _overflowed(PaddedArray::create_unfreeable((uint)_nlists)) { + set_max_size(max_size); } G1StringDedupEntryCache::~G1StringDedupEntryCache() { ShouldNotReachHere(); } +void G1StringDedupEntryCache::set_max_size(size_t size) { + _max_list_length = size / _nlists; +} + G1StringDedupEntry* G1StringDedupEntryCache::alloc() { for (size_t i = 0; i < _nlists; i++) { - G1StringDedupEntry* entry = _lists[i].remove(); + G1StringDedupEntry* entry = _cached[i].remove(); if (entry != NULL) { return entry; } @@ -131,31 +148,55 @@ void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) { assert(entry->obj() != NULL, "Double free"); assert(worker_id < _nlists, "Invalid worker id"); + entry->set_obj(NULL); entry->set_hash(0); - _lists[worker_id].add(entry); + + if (_cached[worker_id].length() < _max_list_length) { + // Cache is not full + _cached[worker_id].add(entry); + } else { + // Cache is full, add to overflow list for later deletion + _overflowed[worker_id].add(entry); + } } size_t G1StringDedupEntryCache::size() { size_t size = 0; for (size_t i = 0; i < _nlists; i++) { - size += _lists[i].length(); + size += _cached[i].length(); } return size; } -void G1StringDedupEntryCache::trim(size_t max_size) { - size_t cache_size = 0; +void G1StringDedupEntryCache::delete_overflowed() { + double start = os::elapsedTime(); + uintx count = 0; + for (size_t i = 0; i < _nlists; i++) { - G1StringDedupEntryFreeList* list = &_lists[i]; - cache_size += list->length(); - while (cache_size > max_size) { - G1StringDedupEntry* entry = list->remove(); - assert(entry != NULL, "Should not be null"); - cache_size--; + G1StringDedupEntry* entry; + + { + // The overflow list can be modified during safepoints, therefore + // we temporarily join the suspendible thread set while removing + // all entries from the list. + SuspendibleThreadSetJoiner sts_join; + entry = _overflowed[i].remove_all(); + } + + // Delete all entries + while (entry != NULL) { + G1StringDedupEntry* next = entry->next(); delete entry; + entry = next; + count++; } } + + double end = os::elapsedTime(); + if (PrintStringDeduplicationStatistics) { + gclog_or_tty->print_cr("[GC concurrent-string-deduplication, deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT "]", count, end - start); + } } G1StringDedupTable* G1StringDedupTable::_table = NULL; @@ -192,7 +233,7 @@ void G1StringDedupTable::create() { assert(_table == NULL, "One string deduplication table allowed"); - _entry_cache = new G1StringDedupEntryCache(); + _entry_cache = new G1StringDedupEntryCache((size_t)(_min_size * _max_cache_factor)); _table = new G1StringDedupTable(_min_size); } @@ -375,6 +416,9 @@ // Update statistics _resize_count++; + // Update max cache size + _entry_cache->set_max_size((size_t)(size * _max_cache_factor)); + // Allocate the new table. The new table will be populated by workers // calling unlink_or_oops_do() and finally installed by finish_resize(). return new G1StringDedupTable(size, _table->_hash_seed); @@ -427,7 +471,7 @@ removed += unlink_or_oops_do(cl, table_half + partition_begin, table_half + partition_end, worker_id); } - // Delayed update avoid contention on the table lock + // Delayed update to avoid contention on the table lock if (removed > 0) { MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); _table->_entries -= removed; @@ -545,10 +589,8 @@ } } -void G1StringDedupTable::trim_entry_cache() { - MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); - size_t max_cache_size = (size_t)(_table->_size * _max_cache_factor); - _entry_cache->trim(max_cache_size); +void G1StringDedupTable::clean_entry_cache() { + _entry_cache->delete_overflowed(); } void G1StringDedupTable::print_statistics(outputStream* st) { diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp --- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,8 +218,8 @@ // and deletes the previously active table. static void finish_rehash(G1StringDedupTable* rehashed_table); - // If the table entry cache has grown too large, trim it down according to policy - static void trim_entry_cache(); + // If the table entry cache has grown too large, delete overflowed entries. + static void clean_entry_cache(); static void unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, uint worker_id); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp --- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -100,14 +100,14 @@ } } - G1StringDedupTable::trim_entry_cache(); - stat.mark_done(); // Print statistics total_stat.add(stat); print(gclog_or_tty, stat, total_stat); } + + G1StringDedupTable::clean_entry_cache(); } terminate(); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -593,8 +593,9 @@ /* 0xDC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, -/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer, -/* 0xE8 */ &&opc_invokehandle,&&opc_default, &&opc_default, &&opc_default, +/* 0xE4 */ &&opc_default, &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, +/* 0xE8 */ &&opc_return_register_finalizer, + &&opc_invokehandle, &&opc_default, &&opc_default, /* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xF0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/oops/method.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -111,6 +111,7 @@ // Release Method*. The nmethod will be gone when we get here because // we've walked the code cache. void Method::deallocate_contents(ClassLoaderData* loader_data) { + clear_jmethod_id(loader_data); MetadataFactory::free_metadata(loader_data, constMethod()); set_constMethod(NULL); MetadataFactory::free_metadata(loader_data, method_data()); @@ -1800,13 +1801,24 @@ #endif // ASSERT *m = _free_method; } + void clear_method(Method* m) { + for (JNIMethodBlock* b = this; b != NULL; b = b->_next) { + for (int i = 0; i < number_of_methods; i++) { + if (b->_methods[i] == m) { + b->_methods[i] = NULL; + return; + } + } + } + // not found + } // During class unloading the methods are cleared, which is different // than freed. void clear_all_methods() { for (JNIMethodBlock* b = this; b != NULL; b = b->_next) { for (int i = 0; i< number_of_methods; i++) { - _methods[i] = NULL; + b->_methods[i] = NULL; } } } @@ -1816,7 +1828,7 @@ int count = 0; for (JNIMethodBlock* b = this; b != NULL; b = b->_next) { for (int i = 0; i< number_of_methods; i++) { - if (_methods[i] != _free_method) count++; + if (b->_methods[i] != _free_method) count++; } } return count; @@ -1872,8 +1884,13 @@ bool Method::is_method_id(jmethodID mid) { Method* m = resolve_jmethod_id(mid); - assert(m != NULL, "should be called with non-null method"); + if (m == NULL) { + return false; + } InstanceKlass* ik = m->method_holder(); + if (ik == NULL) { + return false; + } ClassLoaderData* cld = ik->class_loader_data(); if (cld->jmethod_ids() == NULL) return false; return (cld->jmethod_ids()->contains((Method**)mid)); @@ -1881,6 +1898,9 @@ Method* Method::checked_resolve_jmethod_id(jmethodID mid) { if (mid == NULL) return NULL; + if (!Method::is_method_id(mid)) { + return NULL; + } Method* o = resolve_jmethod_id(mid); if (o == NULL || o == JNIMethodBlock::_free_method || !((Metadata*)o)->is_method()) { return NULL; @@ -1899,6 +1919,10 @@ } } +void Method::clear_jmethod_id(ClassLoaderData* loader_data) { + loader_data->jmethod_ids()->clear_method(this); +} + // Called when the class loader is unloaded to make all methods weak. void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { loader_data->jmethod_ids()->clear_all_methods(); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/oops/method.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -772,6 +772,8 @@ // Helper routines for intrinsic_id() and vmIntrinsics::method(). void init_intrinsic_id(); // updates from _none if a match + void clear_jmethod_id(ClassLoaderData* loader_data); + static vmSymbols::SID klass_id_for_intrinsics(Klass* holder); bool jfr_towrite() { diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/opto/compile.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -608,6 +608,10 @@ n->as_MachBranch()->label_set(&fakeL, 0); } n->emit(buf, this->regalloc()); + + // Emitting into the scratch buffer should not fail + assert (!failing(), err_msg_res("Must not have pending failure. Reason is: %s", failure_reason())); + if (is_branch) // Restore label. n->as_MachBranch()->label_set(saveL, save_bnum); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/opto/connode.cpp --- a/src/share/vm/opto/connode.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/opto/connode.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -446,7 +446,9 @@ } uint CastIINode::cmp(const Node &n) const { - return TypeNode::cmp(n) && ((CastIINode&)n)._carry_dependency == _carry_dependency; + return TypeNode::cmp(n) && + ((CastIINode&)n)._carry_dependency == _carry_dependency && + ((CastIINode&)n)._range_check_dependency == _range_check_dependency; } Node *CastIINode::Identity(PhaseTransform *phase) { @@ -523,7 +525,7 @@ } Node *CastIINode::Ideal_DU_postCCP(PhaseCCP *ccp) { - if (_carry_dependency) { + if (_carry_dependency || _range_check_dependency) { return NULL; } return ConstraintCastNode::Ideal_DU_postCCP(ccp); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/opto/output.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1505,6 +1505,13 @@ n->emit(*cb, _regalloc); current_offset = cb->insts_size(); + // Above we only verified that there is enough space in the instruction section. + // However, the instruction may emit stubs that cause code buffer expansion. + // Bail out here if expansion failed due to a lack of code cache space. + if (failing()) { + return; + } + #ifdef ASSERT if (n->size(_regalloc) < (current_offset-instr_offset)) { n->dump(); @@ -1633,11 +1640,14 @@ if (_method) { // Emit the exception handler code. _code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb)); + if (failing()) { + return; // CodeBuffer::expand failed + } // Emit the deopt handler code. _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb)); // Emit the MethodHandle deopt handler code (if required). - if (has_method_handle_invokes()) { + if (has_method_handle_invokes() && !failing()) { // We can use the same code as for the normal deopt handler, we // just need a different entry point address. _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb)); diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/opto/stringopts.cpp --- a/src/share/vm/opto/stringopts.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/opto/stringopts.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1641,16 +1641,11 @@ } kit.store_String_value(kit.control(), result, char_array); - // Do not let stores that initialize this object be reordered with - // a subsequent store that would make this object accessible by - // other threads. - // Record what AllocateNode this StoreStore protects so that - // escape analysis can go from the MemBarStoreStoreNode to the - // AllocateNode and eliminate the MemBarStoreStoreNode if possible - // based on the escape status of the AllocateNode. - AllocateNode* alloc = AllocateNode::Ideal_allocation(result, _gvn); - assert(alloc != NULL, "should be newly allocated"); - kit.insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + // The value field is final. Emit a barrier here to ensure that the effect + // of the initialization is committed to memory before any code publishes + // a reference to the newly constructed object (see Parse::do_exits()). + assert(AllocateNode::Ideal_allocation(result, _gvn) != NULL, "should be newly allocated"); + kit.insert_mem_bar(Op_MemBarRelease, result); } else { result = C->top(); } diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/opto/subnode.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -547,8 +547,12 @@ // All unsigned values are LE -1 and GE 0. if (lo0 == 0 && hi0 == 0) { return TypeInt::CC_LE; // 0 <= bot + } else if ((jint)lo0 == -1 && (jint)hi0 == -1) { + return TypeInt::CC_GE; // -1 >= bot } else if (lo1 == 0 && hi1 == 0) { return TypeInt::CC_GE; // bot >= 0 + } else if ((jint)lo1 == -1 && (jint)hi1 == -1) { + return TypeInt::CC_LE; // bot <= -1 } } else { // We can use ranges of the form [lo..hi] if signs are the same. diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/prims/jniCheck.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -461,16 +461,11 @@ Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) { ASSERT_OOPS_ALLOWED; - // do the fast jmethodID check first + // Do the jmethodID check Method* moop = Method::checked_resolve_jmethod_id(method_id); if (moop == NULL) { ReportJNIFatalError(thr, fatal_wrong_class_or_method); } - // jmethodIDs are supposed to be weak handles in the class loader data, - // but that can be expensive so check it last - else if (!Method::is_method_id(method_id)) { - ReportJNIFatalError(thr, fatal_non_weak_method); - } return moop; } diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/prims/jvm.cpp Mon Feb 06 17:18:57 2017 +0100 @@ -1292,18 +1292,22 @@ // and null permissions - which gives no permissions. oop create_dummy_access_control_context(TRAPS) { InstanceKlass* pd_klass = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass()); - // new ProtectionDomain(null,null); - oop null_protection_domain = pd_klass->allocate_instance(CHECK_NULL); - Handle null_pd(THREAD, null_protection_domain); + Handle obj = pd_klass->allocate_instance_handle(CHECK_NULL); + // Call constructor ProtectionDomain(null, null); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, obj, KlassHandle(THREAD, pd_klass), + vmSymbols::object_initializer_name(), + vmSymbols::codesource_permissioncollection_signature(), + Handle(), Handle(), CHECK_NULL); // new ProtectionDomain[] {pd}; objArrayOop context = oopFactory::new_objArray(pd_klass, 1, CHECK_NULL); - context->obj_at_put(0, null_pd()); + context->obj_at_put(0, obj()); // new AccessControlContext(new ProtectionDomain[] {pd}) objArrayHandle h_context(THREAD, context); - oop result = java_security_AccessControlContext::create(h_context, false, Handle(), CHECK_NULL); - return result; + oop acc = java_security_AccessControlContext::create(h_context, false, Handle(), CHECK_NULL); + return acc; } JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)) diff -r 9a740aa0d87b -r 9b69cec6d01b src/share/vm/utilities/taskqueue.hpp --- a/src/share/vm/utilities/taskqueue.hpp Sat Feb 04 15:24:10 2017 +0100 +++ b/src/share/vm/utilities/taskqueue.hpp Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -453,6 +453,9 @@ // Push task t onto the queue or onto the overflow stack. Return true. inline bool push(E t); + // Try to push task t onto the queue only. Returns true if successful, false otherwise. + inline bool try_push_to_taskqueue(E t); + // Attempt to pop from the overflow stack; return true if anything was popped. inline bool pop_overflow(E& t); @@ -486,6 +489,10 @@ return true; } +template +bool OverflowTaskQueue::try_push_to_taskqueue(E t) { + return taskqueue_t::push(t); +} class TaskQueueSetSuper { protected: static int randomParkAndMiller(int* seed0); diff -r 9a740aa0d87b -r 9b69cec6d01b test/compiler/jsr292/VMAnonymousClasses.java --- a/test/compiler/jsr292/VMAnonymousClasses.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/compiler/jsr292/VMAnonymousClasses.java Mon Feb 06 17:18:57 2017 +0100 @@ -24,7 +24,7 @@ /** * @test * @bug 8058828 - * @run main/bootclasspath -Xbatch VMAnonymousClasses + * @run main/bootclasspath/othervm -Xbatch VMAnonymousClasses */ import jdk.internal.org.objectweb.asm.ClassWriter; diff -r 9a740aa0d87b -r 9b69cec6d01b test/compiler/native/TestDirtyInt.sh --- a/test/compiler/native/TestDirtyInt.sh Sat Feb 04 15:24:10 2017 +0100 +++ b/test/compiler/native/TestDirtyInt.sh Mon Feb 06 17:18:57 2017 +0100 @@ -30,20 +30,19 @@ ## @run shell/timeout=30 TestDirtyInt.sh ## -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" +if [ -z "${TESTSRC}" ]; then + TESTSRC="${PWD}" + echo "TESTSRC not set. Using "${TESTSRC}" as default" fi echo "TESTSRC=${TESTSRC}" ## Adding common setup Variables for running shell tests. . ${TESTSRC}/../../test_env.sh # set platform-dependent variables -if [ $VM_OS == "linux" -a $VM_CPU == "sparcv9" ]; then +if [ "$VM_OS" = "linux" -a "$VM_CPU" = "sparcv9" ]; then echo "Testing on linux-sparc" gcc_cmd=`which gcc` - if [ "x$gcc_cmd" == "x" ]; then + if [ -z "$gcc_cmd" ]; then echo "WARNING: gcc not found. Cannot execute test." 2>&1 exit 0; fi @@ -68,10 +67,9 @@ -Djava.library.path=${TESTSRC}${FS} TestDirtyInt" echo "$cmd" -eval $cmd +eval $cmd -if [ $? = 0 ] -then +if [ $? = 0 ]; then echo "Test Passed" exit 0 fi diff -r 9a740aa0d87b -r 9b69cec6d01b test/compiler/stringopts/TestStringObjectInitialization.java --- a/test/compiler/stringopts/TestStringObjectInitialization.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/compiler/stringopts/TestStringObjectInitialization.java Mon Feb 06 17:18:57 2017 +0100 @@ -27,6 +27,7 @@ /* * @test * @bug 8159244 + * @requires vm.gc == "Parallel" | vm.gc == "null" * @summary Verifies that no partially initialized String object escapes from * C2's String concat optimization in a highly concurrent setting. * This test triggers the bug in about 1 out of 10 runs. diff -r 9a740aa0d87b -r 9b69cec6d01b test/runtime/classFileParserBug/BadNameAndType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/BadNameAndType.java Mon Feb 06 17:18:57 2017 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8042660 + * @summary Constant pool NameAndType entries must point to non-zero length Utf8 strings + * @compile emptySigUtf8.jcod + * @compile emptyNameUtf8.jcod + * @run main/othervm -Xverify:all BadNameAndType + */ + +// Test that a constant pool NameAndType descriptor_index and/or name_index +// that points to a zero length Utf8 string causes a ClassFormatError. +public class BadNameAndType { + public static void main(String args[]) throws Throwable { + + System.out.println("Regression test for bug 8042660"); + + // Test descriptor_index pointing to zero-length string. + try { + Class newClass = Class.forName("emptySigUtf8"); + throw new RuntimeException("Expected ClassFormatError exception not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadNameAndType passed test case emptySigUtf8"); + } + + // Test name_index pointing to zero-length string. + try { + Class newClass = Class.forName("emptyNameUtf8"); + throw new RuntimeException("Expected ClassFormatError exception not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadNameAndType passed test case emptyNameUtf8"); + } + } +} diff -r 9a740aa0d87b -r 9b69cec6d01b test/runtime/classFileParserBug/emptyNameUtf8.jcod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/emptyNameUtf8.jcod Mon Feb 06 17:18:57 2017 +0100 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// This class has an illegal NameAndType at constant pool #4. It's illegal because +// the Utf8 that it points to at #27 is a zero length string which is not a valid +// name. Loading this class should cause a ClassFormatError exception. +class emptyNameUtf8 { + 0xCAFEBABE; + 0; // minor version + 52; // version + [29] { // Constant Pool + ; // first element is empty + Method #6 #15; // #1 at 0x0A + Field #16 #17; // #2 at 0x0F + String #18; // #3 at 0x14 + NameAndType #27 #28; // #4 at 0x9F + class #21; // #5 at 0x1C + class #22; // #6 at 0x1F + Utf8 ""; // #7 at 0x22 + Utf8 "()V"; // #8 at 0x2B + Utf8 "Code"; // #9 at 0x2E + Utf8 "LineNumberTable"; // #10 at 0x35 + Utf8 "main"; // #11 at 0x47 + Utf8 "([Ljava/lang/String;)V"; // #12 at 0x4E + Utf8 "SourceFile"; // #13 at 0x67 + Utf8 "emptyNameUtf8.java"; // #14 at 0x74 + NameAndType #7 #8; // #15 at 0x81 + class #23; // #16 at 0x86 + NameAndType #24 #25; // #17 at 0x89 + Utf8 "Hello World"; // #18 at 0x8E + class #26; // #19 at 0x9C + Method #19 #4; // #20 at 0x17 + Utf8 "emptyNameUtf8"; // #21 at 0xA4 + Utf8 "java/lang/Object"; // #22 at 0xAC + Utf8 "java/lang/System"; // #23 at 0xBF + Utf8 "out"; // #24 at 0xD2 + Utf8 "Ljava/io/PrintStream;"; // #25 at 0xD8 + Utf8 "java/io/PrintStream"; // #26 at 0xF0 + Utf8 ""; // #27 at 0x0106 + Utf8 "()V"; // #28 at 0x0110 + } // Constant Pool + + 0x0021; // access + #5;// this_cpx + #6;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [2] { // methods + { // Member at 0x0134 + 0x0001; // access + #7; // name_cpx + #8; // sig_cpx + [1] { // Attributes + Attr(#9, 29) { // Code at 0x013C + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB70001B1; + }; + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#10, 6) { // LineNumberTable at 0x0153 + [1] { // LineNumberTable + 0 2; // at 0x015F + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x015F + 0x0009; // access + #11; // name_cpx + #12; // sig_cpx + [1] { // Attributes + Attr(#9, 37) { // Code at 0x0167 + 2; // max_stack + 1; // max_locals + Bytes[9]{ + 0xB200021203B60004; + 0xB1; + }; + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#10, 10) { // LineNumberTable at 0x0182 + [2] { // LineNumberTable + 0 4; // at 0x018E + 8 5; // at 0x0192 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [1] { // Attributes + Attr(#13, 2) { // SourceFile at 0x0194 + #14; + } // end SourceFile + } // Attributes +} // end class emptyNameUtf8 diff -r 9a740aa0d87b -r 9b69cec6d01b test/runtime/classFileParserBug/emptySigUtf8.jcod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/emptySigUtf8.jcod Mon Feb 06 17:18:57 2017 +0100 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// This class has an illegal NameAndType at constant pool #4. It's illegal because +// the type that it points to at #28 is a zero length Utf8 string which is not a +// valid signature. Loading this class should cause a ClassFormatError exception. +class emptySigUtf8 { + 0xCAFEBABE; + 0; // minor version + 52; // version + [29] { // Constant Pool + ; // first element is empty + Method #6 #15; // #1 at 0x0A + Field #16 #17; // #2 at 0x0F + String #18; // #3 at 0x14 + NameAndType #27 #28; // #4 at 0x9F + class #21; // #5 at 0x1C + class #22; // #6 at 0x1F + Utf8 ""; // #7 at 0x22 + Utf8 "()V"; // #8 at 0x2B + Utf8 "Code"; // #9 at 0x2E + Utf8 "LineNumberTable"; // #10 at 0x35 + Utf8 "main"; // #11 at 0x47 + Utf8 "([Ljava/lang/String;)V"; // #12 at 0x4E + Utf8 "SourceFile"; // #13 at 0x67 + Utf8 "emptySigUtf8.java"; // #14 at 0x74 + NameAndType #7 #8; // #15 at 0x81 + class #23; // #16 at 0x86 + NameAndType #24 #25; // #17 at 0x89 + Utf8 "Hello World"; // #18 at 0x8E + class #26; // #19 at 0x9C + Method #19 #4; // #20 at 0x17 + Utf8 "emptySigUtf8"; // #21 at 0xA4 + Utf8 "java/lang/Object"; // #22 at 0xAC + Utf8 "java/lang/System"; // #23 at 0xBF + Utf8 "out"; // #24 at 0xD2 + Utf8 "Ljava/io/PrintStream;"; // #25 at 0xD8 + Utf8 "java/io/PrintStream"; // #26 at 0xF0 + Utf8 "hi"; // #27 at 0x0106 + Utf8 ""; // #28 at 0x0110 + } // Constant Pool + + 0x0021; // access + #5;// this_cpx + #6;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [2] { // methods + { // Member at 0x0134 + 0x0001; // access + #7; // name_cpx + #8; // sig_cpx + [1] { // Attributes + Attr(#9, 29) { // Code at 0x013C + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB70001B1; + }; + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#10, 6) { // LineNumberTable at 0x0153 + [1] { // LineNumberTable + 0 2; // at 0x015F + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x015F + 0x0009; // access + #11; // name_cpx + #12; // sig_cpx + [1] { // Attributes + Attr(#9, 37) { // Code at 0x0167 + 2; // max_stack + 1; // max_locals + Bytes[9]{ + 0xB200021203B60004; + 0xB1; + }; + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#10, 10) { // LineNumberTable at 0x0182 + [2] { // LineNumberTable + 0 4; // at 0x018E + 8 5; // at 0x0192 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [1] { // Attributes + Attr(#13, 2) { // SourceFile at 0x0194 + #14; + } // end SourceFile + } // Attributes +} // end class emptySigUtf8 diff -r 9a740aa0d87b -r 9b69cec6d01b test/runtime/handlerInTry/LoadHandlerInTry.java --- a/test/runtime/handlerInTry/LoadHandlerInTry.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/runtime/handlerInTry/LoadHandlerInTry.java Mon Feb 06 17:18:57 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @bug 8075118 - * @summary Allow a ctor to call super() from a switch bytecode. + * @summary JVM stuck in infinite loop during verification * @compile HandlerInTry.jasm * @compile IsolatedHandlerInTry.jasm * @run main/othervm -Xverify:all LoadHandlerInTry @@ -70,9 +70,10 @@ System.out.println("Regression test for bug 8075118"); try { Class newClass = Class.forName("HandlerInTry"); - } catch (Exception e) { - System.out.println("Failed: Exception was thrown: " + e.toString()); - throw e; + throw new RuntimeException( + "Failed to throw VerifyError for HandlerInTry"); + } catch (java.lang.VerifyError e) { + System.out.println("Passed: VerifyError exception was thrown"); } try { diff -r 9a740aa0d87b -r 9b69cec6d01b test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java --- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Mon Feb 06 17:18:57 2017 +0100 @@ -24,6 +24,8 @@ package com.oracle.java.testlibrary; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -69,6 +71,58 @@ } /** + * Verify that the stdout contents of output buffer is empty + * + * @throws RuntimeException + * If stdout was not empty + */ + public void stdoutShouldBeEmpty() { + if (!getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was not empty"); + } + } + + /** + * Verify that the stderr contents of output buffer is empty + * + * @throws RuntimeException + * If stderr was not empty + */ + public void stderrShouldBeEmpty() { + if (!getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + } + + /** + * Verify that the stdout contents of output buffer is not empty + * + * @throws RuntimeException + * If stdout was empty + */ + public void stdoutShouldNotBeEmpty() { + if (getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was empty"); + } + } + + /** + * Verify that the stderr contents of output buffer is not empty + * + * @throws RuntimeException + * If stderr was empty + */ + public void stderrShouldNotBeEmpty() { + if (getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was empty"); + } + } + + /** * Verify that the stdout and stderr contents of output buffer contains the string * * @param expectedString String that buffer should contain @@ -365,4 +419,18 @@ public int getExitValue() { return exitValue; } + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by newlines. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)")); + } } diff -r 9a740aa0d87b -r 9b69cec6d01b test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java --- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Mon Feb 06 17:18:57 2017 +0100 @@ -187,23 +187,36 @@ return executeProcess(pb); } - /** - * Executes a process, waits for it to finish and returns the process output. - * @param pb The ProcessBuilder to execute. - * @return The output from the process. - */ - public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable { - OutputAnalyzer output = null; - try { - output = new OutputAnalyzer(pb.start()); - return output; - } catch (Throwable t) { - System.out.println("executeProcess() failed: " + t); - throw t; - } finally { - System.out.println(getProcessLog(pb, output)); + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = pb.start(); + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } } - } /** * Executes a process, waits for it to finish and returns the process output. diff -r 9a740aa0d87b -r 9b69cec6d01b test/testlibrary_tests/whitebox/vm_flags/UintxTest.java --- a/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Mon Feb 06 17:18:57 2017 +0100 @@ -34,7 +34,7 @@ import com.oracle.java.testlibrary.Platform; public class UintxTest { - private static final String FLAG_NAME = "TypeProfileLevel"; + private static final String FLAG_NAME = "VerifyGCStartAt"; private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 1L << 32L}; private static final Long[] EXPECTED_64 = TESTS; diff -r 9a740aa0d87b -r 9b69cec6d01b test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java --- a/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Sat Feb 04 15:24:10 2017 +0100 +++ b/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Mon Feb 06 17:18:57 2017 +0100 @@ -55,9 +55,7 @@ } private T getValue() { - T t = get.apply(flagName); - System.out.println("T = " + t); - return t; + return get.apply(flagName); } protected static void runTest(String existentFlag, T[] tests,