Mercurial > people > andrew > aarch32 > hotspot
changeset 9026:8c5c7b0f9394 jdk8u112-b16-aarch32-161109
Merge
author | snazarki |
---|---|
date | Tue, 08 Nov 2016 17:14:36 +0300 |
parents | 1de174b764f9 (current diff) e134dc1879b7 (diff) |
children | a9b89cd22711 |
files | .hgtags src/cpu/aarch32/vm/compiledIC_aarch32.cpp src/os/linux/vm/os_linux.cpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/classfile/verifier.cpp src/share/vm/code/compiledIC.hpp src/share/vm/opto/compile.cpp src/share/vm/prims/jniCheck.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/java.cpp src/share/vm/runtime/sharedRuntime.cpp |
diffstat | 58 files changed, 1460 insertions(+), 306 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Nov 03 13:12:50 2016 +0300 +++ b/.hgtags Tue Nov 08 17:14:36 2016 +0300 @@ -864,6 +864,9 @@ f3e1e734e2d29101a9537ddeb71ecad413fcd352 jdk8u92-b13 24a09407d71bb2cc4848bfa21660c890b4d722b1 jdk8u92-b14 445941ba41c0e3829fe02140690b144281ac2141 jdk8u92-b31 +f958bebdee267695e37aadd27753ac8b1e1823c8 jdk8u92-b32 +d1bb0e79ff79d21068388d9c62ca01e3c072fd0d jdk8u92-b33 +d0388be32561e4bd00c1a79adbe301cfdd6ba9f2 jdk8u92-b34 b374548dcb4834eb8731a06b52faddd0f10bd45d jdk8u81-b00 ead07188d11107e877e8e4ad215ff6cb238a8a92 jdk8u101-b01 34429bad9986677f4991c80aeb22665842881cba jdk8u101-b02 @@ -895,3 +898,35 @@ f6daf04c0f48dab5420ad63d21da82a7fa4e3ad7 jdk8u102-b13 ac59b80e21bba8cae248c82a991ad13da7c59160 jdk8u102-b14-aarch32-160812 186d445bec0454592848cd1bfff6c8f599363354 jdk8u-core-final +ac29c9c1193aef5d480b200ed94c5d579243c17b jdk8u102-b14 +96e1c72fc617d3c6c125bcfc9182f77fc6aa38e6 jdk8u102-b31 +ceecf88e5c2c09bfabf5926581e6d0b0f65f5148 jdk8u111-b00 +e73d79ce00e4a0451e464c7a73d9c911d01e169a jdk8u111-b01 +d584a614818562e1187e1a15c202aec01491caeb jdk8u111-b02 +a3ede966ecfe6009fe4a58fbd6903c470a059ad3 jdk8u111-b03 +65029655928a834018a6793253c9b2699044af92 jdk8u111-b04 +e4525db272634b980738003eff99ac1588bb79d3 jdk8u111-b05 +019b22dd8128840ecdcd1bfebcf4447e28e45068 jdk8u111-b06 +3f337aaf090769653ee0a746fbe661d09055a883 jdk8u111-b07 +e180e364a40364a059a20c74b97ab4e928e2b676 jdk8u111-b08 +c48b303692bb86c42e928da6dec815e901a24c5b jdk8u111-b09 +96973081eb8a132ca3bfee9249ad99c185b6b130 jdk8u111-b10 +603804f2132ff188a9f3d1c31cca63b47220e2e2 jdk8u111-b11 +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
--- a/LICENSE Thu Nov 03 13:12:50 2016 +0300 +++ b/LICENSE Tue Nov 08 17:14:36 2016 +0300 @@ -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.
--- a/src/cpu/aarch32/vm/compiledIC_aarch32.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/aarch32/vm/compiledIC_aarch32.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -52,7 +52,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { // Stub is fixed up when the corresponding call is converted from // calling compiled code to calling interpreted code. // mov rmethod, 0 @@ -67,7 +67,7 @@ address base = __ start_a_stub(to_interp_stub_size()*2); int offset = __ offset(); - if (base == NULL) return; // CodeBuffer::expand failed + if (base == NULL) return NULL; // CodeBuffer::expand failed // static stub relocation stores the instruction address of the call __ relocate(static_stub_Relocation::spec(mark)); // static stub relocation also tags the Method* in the code-stream. @@ -77,6 +77,7 @@ assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big"); __ end_a_stub(); + return base; } #undef __
--- a/src/cpu/ppc/vm/compiledIC_ppc.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/ppc/vm/compiledIC_ppc.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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
--- a/src/cpu/ppc/vm/ppc.ad Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/ppc/vm/ppc.ad Tue Nov 08 17:14:36 2016 +0300 @@ -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);
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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();
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -2168,6 +2168,27 @@ __ delayed()->nop(); } + // If the compiler was not able to prove that exact type of the source or the destination + // of the arraycopy is an array type, check at runtime if the source or the destination is + // an instance type. + if (flags & LIR_OpArrayCopy::type_check) { + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) { + __ load_klass(dst, tmp); + __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2); + __ cmp(tmp2, Klass::_lh_neutral_value); + __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry()); + __ delayed()->nop(); + } + + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) { + __ load_klass(src, tmp); + __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2); + __ cmp(tmp2, Klass::_lh_neutral_value); + __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry()); + __ delayed()->nop(); + } + } + if (flags & LIR_OpArrayCopy::src_pos_positive_check) { // test src_pos register __ cmp_zero_and_br(Assembler::less, src_pos, *stub->entry());
--- a/src/cpu/sparc/vm/compiledIC_sparc.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/sparc/vm/compiledIC_sparc.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -53,7 +53,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { #ifdef COMPILER2 // Stub is fixed up when the corresponding call is converted from calling // compiled code to calling interpreted code. @@ -64,9 +64,10 @@ MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(to_interp_stub_size()*2); - if (base == NULL) return; // CodeBuffer::expand failed. + 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)); @@ -81,6 +82,7 @@ // Update current stubs pointer and restore code_end. __ end_a_stub(); + return base; #else ShouldNotReachHere(); #endif
--- a/src/cpu/sparc/vm/sparc.ad Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/sparc/vm/sparc.ad Tue Nov 08 17:14:36 2016 +0300 @@ -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; + } } %}
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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);
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -3275,6 +3275,23 @@ __ jcc(Assembler::zero, *stub->entry()); } + // If the compiler was not able to prove that exact type of the source or the destination + // of the arraycopy is an array type, check at runtime if the source or the destination is + // an instance type. + if (flags & LIR_OpArrayCopy::type_check) { + if (!(flags & LIR_OpArrayCopy::dst_objarray)) { + __ load_klass(tmp, dst); + __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value); + __ jcc(Assembler::greaterEqual, *stub->entry()); + } + + if (!(flags & LIR_OpArrayCopy::src_objarray)) { + __ load_klass(tmp, src); + __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value); + __ jcc(Assembler::greaterEqual, *stub->entry()); + } + } + // check if negative if (flags & LIR_OpArrayCopy::src_pos_positive_check) { __ testl(src_pos, src_pos);
--- a/src/cpu/x86/vm/compiledIC_x86.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/compiledIC_x86.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -50,7 +50,7 @@ // ---------------------------------------------------------------------------- #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { // Stub is fixed up when the corresponding call is converted from // calling compiled code to calling interpreted code. // movq rbx, 0 @@ -62,9 +62,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()*2); - if (base == NULL) return; // CodeBuffer::expand failed. + 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. @@ -74,6 +75,7 @@ // Update current stubs pointer and restore insts_end. __ end_a_stub(); + return base; } #undef __
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -3202,7 +3202,24 @@ jmp(done); } else { // Stack: X Y - Label x_negative, y_odd; + Label x_negative, y_not_2; + + static double two = 2.0; + ExternalAddress two_addr((address)&two); + + // constant maybe too far on 64 bit + lea(tmp2, two_addr); + fld_d(Address(tmp2, 0)); // Stack: 2 X Y + fcmp(tmp, 2, true, false); // Stack: X Y + jcc(Assembler::parity, y_not_2); + jcc(Assembler::notEqual, y_not_2); + + fxch(); fpop(); // Stack: X + fmul(0); // Stack: X*X + + jmp(done); + + bind(y_not_2); fldz(); // Stack: 0 X Y fcmp(tmp, 1, true, false); // Stack: X Y
--- a/src/cpu/x86/vm/x86.ad Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/x86.ad Tue Nov 08 17:14:36 2016 +0300 @@ -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
--- a/src/cpu/x86/vm/x86_32.ad Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/x86_32.ad Tue Nov 08 17:14:36 2016 +0300 @@ -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; + } } %}
--- a/src/cpu/x86/vm/x86_64.ad Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/x86/vm/x86_64.ad Tue Nov 08 17:14:36 2016 +0300 @@ -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; + } } %}
--- a/src/cpu/zero/vm/compiledIC_zero.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/zero/vm/compiledIC_zero.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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() {
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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); }
--- a/src/os/linux/vm/os_linux.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/os/linux/vm/os_linux.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -3059,6 +3059,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. @@ -3343,54 +3385,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 @@ -3398,14 +3519,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; } @@ -3445,22 +3558,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; @@ -3468,13 +3581,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. @@ -3494,9 +3600,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, @@ -3507,11 +3613,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. // @@ -3524,6 +3631,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, @@ -3540,7 +3648,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"); @@ -6118,47 +6226,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() {
--- a/src/share/vm/c1/c1_LIRAssembler.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/c1/c1_LIRAssembler.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -468,6 +468,7 @@ // emit the static call stub stuff out of line emit_static_call_stub(); + CHECK_BAILOUT(); switch (op->code()) { case lir_static_call:
--- a/src/share/vm/classfile/classFileParser.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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 "<init>". 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", @@ -3969,6 +3973,11 @@ // Make sure this is the end of class file stream guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); + if (_class_name == vmSymbols::java_lang_Object()) { + check_property(_local_interfaces == Universe::the_empty_klass_array(), + "java.lang.Object cannot implement an interface in class file %s", + CHECK_(nullHandle)); + } // We check super class after class file is parsed and format is checked if (super_class_index > 0 && super_klass.is_null()) { Symbol* sk = cp->klass_name_at(super_class_index);
--- a/src/share/vm/classfile/classLoaderData.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/classLoaderData.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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
--- a/src/share/vm/classfile/classLoaderData.inline.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/classLoaderData.inline.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -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());
--- a/src/share/vm/classfile/stackMapTableFormat.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/stackMapTableFormat.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -203,6 +203,7 @@ inline bool verify(address start, address end) const; inline void print_on(outputStream* st, int current_offset) const; + inline void print_truncated(outputStream* st, int current_offset) const; // Create as_xxx and is_xxx methods for the subtypes #define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \ @@ -263,6 +264,10 @@ void print_on(outputStream* st, int current_offset = -1) const { st->print("same_frame(@%d)", offset_delta() + current_offset); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + print_on(st, current_offset); + } }; class same_frame_extended : public stack_map_frame { @@ -309,6 +314,10 @@ void print_on(outputStream* st, int current_offset = -1) const { st->print("same_frame_extended(@%d)", offset_delta() + current_offset); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + print_on(st, current_offset); + } }; class same_locals_1_stack_item_frame : public stack_map_frame { @@ -381,6 +390,11 @@ types()->print_on(st); st->print(")"); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + st->print("same_locals_1_stack_item_frame(@%d), output truncated, Stackmap exceeds table size.", + offset_delta() + current_offset); + } }; class same_locals_1_stack_item_extended : public stack_map_frame { @@ -446,6 +460,11 @@ types()->print_on(st); st->print(")"); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + st->print("same_locals_1_stack_item_extended(@%d), output truncated, Stackmap exceeds table size.", + offset_delta() + current_offset); + } }; class chop_frame : public stack_map_frame { @@ -511,6 +530,10 @@ void print_on(outputStream* st, int current_offset = -1) const { st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops()); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + print_on(st, current_offset); + } }; class append_frame : public stack_map_frame { @@ -619,6 +642,11 @@ } st->print(")"); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + st->print("append_frame(@%d), output truncated, Stackmap exceeds table size.", + offset_delta() + current_offset); + } }; class full_frame : public stack_map_frame { @@ -784,6 +812,11 @@ } st->print("})"); } + + void print_truncated(outputStream* st, int current_offset = -1) const { + st->print("full_frame(@%d), output truncated, Stackmap exceeds table size.", + offset_delta() + current_offset); + } }; #define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \ @@ -841,6 +874,10 @@ FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs)); } +void stack_map_frame::print_truncated(outputStream* st, int offs = -1) const { + FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_truncated, (st, offs)); +} + #undef VIRTUAL_DISPATCH #undef VOID_VIRTUAL_DISPATCH
--- a/src/share/vm/classfile/verifier.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/verifier.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -507,8 +507,19 @@ 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; 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) { + 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();
--- a/src/share/vm/classfile/vmSymbols.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, 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 @@ -517,6 +517,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) \ \
--- a/src/share/vm/code/compiledIC.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/code/compiledIC.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -323,7 +323,7 @@ friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site); // Code - static void emit_to_interp_stub(CodeBuffer &cbuf); + static address emit_to_interp_stub(CodeBuffer &cbuf); static int to_interp_stub_size(); static int reloc_to_interp_stub();
--- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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()); + } };
--- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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<mtGC> { +class G1StringDedupEntryList : public CHeapObj<mtGC> { 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<mtGC> { 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<G1StringDedupEntryFreeList>* _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<G1StringDedupEntryList>* _cached; + PaddedEnd<G1StringDedupEntryList>* _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<G1StringDedupEntryFreeList, mtGC>::create_unfreeable((uint)_nlists); +G1StringDedupEntryCache::G1StringDedupEntryCache(size_t max_size) : + _nlists(MAX2(ParallelGCThreads, (size_t)1)), + _max_list_length(0), + _cached(PaddedArray<G1StringDedupEntryList, mtGC>::create_unfreeable((uint)_nlists)), + _overflowed(PaddedArray<G1StringDedupEntryList, mtGC>::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) {
--- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -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);
--- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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();
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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,
--- a/src/share/vm/oops/method.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/oops/method.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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();
--- a/src/share/vm/oops/method.hpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/oops/method.hpp Tue Nov 08 17:14:36 2016 +0300 @@ -768,6 +768,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() { return _jfr_towrite; }
--- a/src/share/vm/opto/compile.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/opto/compile.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -610,6 +610,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);
--- a/src/share/vm/opto/connode.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/opto/connode.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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);
--- a/src/share/vm/opto/output.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/opto/output.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -1502,6 +1502,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(); @@ -1630,11 +1637,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));
--- a/src/share/vm/opto/stringopts.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/opto/stringopts.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -1640,6 +1640,12 @@ kit.store_String_length(kit.control(), result, length); } kit.store_String_value(kit.control(), result, char_array); + + // 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(); }
--- a/src/share/vm/opto/subnode.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/opto/subnode.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -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.
--- a/src/share/vm/prims/jniCheck.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/prims/jniCheck.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -464,16 +464,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; }
--- a/src/share/vm/prims/jvm.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/prims/jvm.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, 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 @@ -1290,18 +1290,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)) @@ -2626,7 +2630,6 @@ switch (cp->tag_at(cp_index).value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: - case JVM_CONSTANT_NameAndType: // for invokedynamic return cp->uncached_name_ref_at(cp_index)->as_utf8(); default: fatal("JVM_GetCPMethodNameUTF: illegal constant"); @@ -2644,7 +2647,6 @@ switch (cp->tag_at(cp_index).value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: - case JVM_CONSTANT_NameAndType: // for invokedynamic return cp->uncached_signature_ref_at(cp_index)->as_utf8(); default: fatal("JVM_GetCPMethodSignatureUTF: illegal constant"); @@ -2870,7 +2872,18 @@ int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { // see bug 4399518, 4417214 if ((intptr_t)count <= 0) return -1; - return vsnprintf(str, count, fmt, args); + + int result = vsnprintf(str, count, fmt, args); + // Note: on truncation vsnprintf(3) on Unix returns number of + // characters which would have been written had the buffer been large + // enough; on Windows, it returns -1. We handle both cases here and + // always return -1, and perform null termination. + if ((result > 0 && (size_t)result >= count) || result == -1) { + str[count - 1] = '\0'; + result = -1; + } + + return result; } ATTRIBUTE_PRINTF(3, 0)
--- a/src/share/vm/runtime/arguments.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/runtime/arguments.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -560,8 +560,9 @@ (os::file_name_strcmp(ext, ".jar") == 0 || os::file_name_strcmp(ext, ".zip") == 0); if (isJarOrZip) { - char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal); - sprintf(jarpath, "%s%s%s", directory, dir_sep, name); + size_t length = directory_len + 2 + strlen(name); + char* jarpath = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(jarpath, length, "%s%s%s", directory, dir_sep, name); path = add_to_path(path, jarpath, false); FREE_C_HEAP_ARRAY(char, jarpath, mtInternal); } @@ -704,9 +705,10 @@ } else if (new_len == 0) { value = old_value; } else { - char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal); + size_t length = old_len + 1 + new_len + 1; + char* buf = NEW_C_HEAP_ARRAY(char, length, mtInternal); // each new setting adds another LINE to the switch: - sprintf(buf, "%s\n%s", old_value, new_value); + jio_snprintf(buf, length, "%s\n%s", old_value, new_value); value = buf; free_this_too = buf; } @@ -813,15 +815,17 @@ if (args == NULL || count == 0) { return NULL; } - size_t length = strlen(args[0]) + 1; // add 1 for the null terminator - for (int i = 1; i < count; i++) { - length += strlen(args[i]) + 1; // add 1 for a space + size_t length = 0; + for (int i = 0; i < count; i++) { + length += strlen(args[i]) + 1; // add 1 for a space or NULL terminating character } char* s = NEW_RESOURCE_ARRAY(char, length); - strcpy(s, args[0]); - for (int j = 1; j < count; j++) { - strcat(s, " "); - strcat(s, args[j]); + char* dst = s; + for (int j = 0; j < count; j++) { + size_t offset = strlen(args[j]) + 1; // add 1 for a space or NULL terminating character + jio_snprintf(dst, length, "%s ", args[j]); // jio_snprintf will replace the last space character with NULL character + dst += offset; + length -= offset; } return (const char*) s; } @@ -1889,7 +1893,7 @@ // Feed the cache size setting into the JDK char buffer[1024]; - sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax); + jio_snprintf(buffer, 1024, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax); add_property(buffer); } if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) { @@ -2764,7 +2768,9 @@ char *options = NULL; if(pos != NULL) { - options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(pos + 1) + 1, mtInternal), pos + 1); + size_t length = strlen(pos + 1) + 1; + options = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(options, length, "%s", pos + 1); } #if !INCLUDE_JVMTI if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) { @@ -2783,7 +2789,9 @@ return JNI_ERR; #else if(tail != NULL) { - char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail); + size_t length = strlen(tail) + 1; + char *options = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(options, length, "%s", tail); add_init_agent("instrument", options, false); } #endif // !INCLUDE_JVMTI @@ -3621,8 +3629,7 @@ } } else { char buffer[256]; - strcpy(buffer, "java.awt.headless="); - strcat(buffer, envbuffer); + jio_snprintf(buffer, 256, "java.awt.headless=%s", envbuffer); if (!add_property(buffer)) { return JNI_ENOMEM; } @@ -3721,6 +3728,14 @@ void Arguments::set_shared_spaces_flags() { if (DumpSharedSpaces) { + if (FailOverToOldVerifier) { + // Don't fall back to the old verifier on verification failure. If a + // class fails verification with the split verifier, it might fail the + // CDS runtime verifier constraint check. In that case, we don't want + // to share the class. We only archive classes that pass the split verifier. + FLAG_SET_DEFAULT(FailOverToOldVerifier, false); + } + if (RequireSharedSpaces) { warning("cannot dump shared archive while using shared archive"); }
--- a/src/share/vm/runtime/deoptimization.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -1886,8 +1886,6 @@ trap_reason_name(reason), recomp_flag ? " recompiled" : ""); } - if (len >= buflen) - buf[buflen-1] = '\0'; return buf; } @@ -1957,8 +1955,6 @@ len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'", reason, action, unloaded_class_index); } - if (len >= buflen) - buf[buflen-1] = '\0'; return buf; }
--- a/src/share/vm/runtime/java.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/runtime/java.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, 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 @@ -776,25 +776,36 @@ } void JDK_Version::to_string(char* buffer, size_t buflen) const { + assert(buffer && buflen > 0, "call with useful buffer"); size_t index = 0; if (!is_valid()) { jio_snprintf(buffer, buflen, "%s", "(uninitialized)"); } else if (is_partially_initialized()) { jio_snprintf(buffer, buflen, "%s", "(uninitialized) pre-1.6.0"); } else { - index += jio_snprintf( + int rc = jio_snprintf( &buffer[index], buflen - index, "%d.%d", _major, _minor); + if (rc == -1) return; + index += rc; if (_micro > 0) { - index += jio_snprintf(&buffer[index], buflen - index, ".%d", _micro); + rc = jio_snprintf(&buffer[index], buflen - index, ".%d", _micro); + if (rc == -1) return; + index += rc; } if (_update > 0) { - index += jio_snprintf(&buffer[index], buflen - index, "_%02d", _update); + rc = jio_snprintf(&buffer[index], buflen - index, "_%02d", _update); + if (rc == -1) return; + index += rc; } if (_special > 0) { - index += jio_snprintf(&buffer[index], buflen - index, "%c", _special); + rc = jio_snprintf(&buffer[index], buflen - index, "%c", _special); + if (rc == -1) return; + index += rc; } if (_build > 0) { - index += jio_snprintf(&buffer[index], buflen - index, "-b%02d", _build); + rc = jio_snprintf(&buffer[index], buflen - index, "-b%02d", _build); + if (rc == -1) return; + index += rc; } } }
--- a/src/share/vm/runtime/sharedRuntime.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -2834,8 +2834,6 @@ char *s = sig->as_C_string(); int len = (int)strlen(s); s++; len--; // Skip opening paren - char *t = s+len; - while( *(--t) != ')' ) ; // Find close paren BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, 256 ); VMRegPair *regs = NEW_RESOURCE_ARRAY( VMRegPair, 256 ); @@ -2844,7 +2842,7 @@ sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature } - while( s < t ) { + while( *s != ')' ) { // Find closing right paren switch( *s++ ) { // Switch on signature character case 'B': sig_bt[cnt++] = T_BYTE; break; case 'C': sig_bt[cnt++] = T_CHAR; break;
--- a/src/share/vm/runtime/signature.cpp Thu Nov 03 13:12:50 2016 +0300 +++ b/src/share/vm/runtime/signature.cpp Tue Nov 08 17:14:36 2016 +0300 @@ -225,7 +225,49 @@ _index = 0; expect('('); Symbol* sig = _signature; - while (sig->byte_at(_index) != ')') _index++; + // Need to skip over each type in the signature's argument list until a + // closing ')' is found., then get the return type. We cannot just scan + // for the first ')' because ')' is a legal character in a type name. + while (sig->byte_at(_index) != ')') { + switch(sig->byte_at(_index)) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 'V': + { + _index++; + } + break; + case 'L': + { + while (sig->byte_at(_index++) != ';') ; + } + break; + case '[': + { + int begin = ++_index; + skip_optional_size(); + while (sig->byte_at(_index) == '[') { + _index++; + skip_optional_size(); + } + if (sig->byte_at(_index) == 'L') { + while (sig->byte_at(_index++) != ';') ; + } else { + _index++; + } + } + break; + default: + ShouldNotReachHere(); + break; + } + } expect(')'); // Parse return type _parameter_index = -1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/c1/TestArrayCopyToFromObject.java Tue Nov 08 17:14:36 2016 +0300 @@ -0,0 +1,64 @@ +/* + * 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 8160591 + * @summary C1-generated code for System.arraycopy() does not throw an ArrayStoreException if 'dst' is no a "proper" array (i.e., it is java.lang.Object) + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:-UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:+UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject + */ +public class TestArrayCopyToFromObject { + + public void test(Object aArray[]) { + Object a = new Object(); + + try { + System.arraycopy(aArray, 0, a, 0, 1); + throw new RuntimeException ("FAILED: Expected ArrayStoreException " + + "(due to destination not being an array) " + + "was not thrown"); + } catch (ArrayStoreException e) { + System.out.println("PASSED: Expected ArrayStoreException was thrown"); + } + + try { + System.arraycopy(a, 0, aArray, 0, 1); + throw new RuntimeException ("FAILED: Expected ArrayStoreException " + + "(due to source not being an array) " + + "was not thrown"); + } catch (ArrayStoreException e) { + System.out.println("PASSED: Expected ArrayStoreException was thrown"); + } + + } + + public static void main(String args[]) { + System.out.println("TestArrayCopyToFromObject"); + Object aArray[] = new Object[10]; + for (int i = 0; i < 10; i++) { + aArray[i] = new Object(); + } + new TestArrayCopyToFromObject().test(aArray); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/floatingpoint/TestPow2.java Tue Nov 08 17:14:36 2016 +0300 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 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 8063086 + * @summary X^2 special case for C2 yields different result than interpreter + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @build TestPow2 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestPow2 + * + */ + +import java.lang.reflect.*; +import sun.hotspot.WhiteBox; + +public class TestPow2 { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static final double base = 5350.456329377186; + private static final double exp = 2.0; + + static double m() { + return Math.pow(base, exp); + } + + static public void main(String[] args) throws NoSuchMethodException { + Method test_method = TestPow2.class.getDeclaredMethod("m"); + + double interpreter_result = m(); + + // Compile with C1 if possible + WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); + + double c1_result = m(); + + WHITE_BOX.deoptimizeMethod(test_method); + + // Compile it with C2 if possible + WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + + double c2_result = m(); + + if (interpreter_result != c1_result || interpreter_result != c2_result || + c1_result != c2_result) { + System.out.println("interpreter = " + interpreter_result + " c1 = " + c1_result + " c2 = " + c2_result); + throw new RuntimeException("Test Failed"); + } + } +}
--- a/test/compiler/jsr292/VMAnonymousClasses.java Thu Nov 03 13:12:50 2016 +0300 +++ b/test/compiler/jsr292/VMAnonymousClasses.java Tue Nov 08 17:14:36 2016 +0300 @@ -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;
--- a/test/compiler/native/TestDirtyInt.sh Thu Nov 03 13:12:50 2016 +0300 +++ b/test/compiler/native/TestDirtyInt.sh Tue Nov 08 17:14:36 2016 +0300 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/stringopts/TestStringObjectInitialization.java Tue Nov 08 17:14:36 2016 +0300 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.util.Arrays; + +/* + * @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. + * @compile -XDstringConcat=inline TestStringObjectInitialization.java + * @run main/othervm/timeout=300 -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-CompactStrings + * -XX:-UseG1GC -XX:+UseParallelGC TestStringObjectInitialization + */ +public class TestStringObjectInitialization { + + String myString; + + public static void main(String[] args) throws Exception { + TestStringObjectInitialization t = new TestStringObjectInitialization(); + // Create some threads that concurrently update 'myString' + for (int i = 0; i < 100; ++i) { + (new Thread(new Runner(t))).start(); + } + Thread last = new Thread(new Runner(t)); + last.start(); + last.join(); + } + + private void add(String message) { + // String escapes to other threads here + myString += message; + } + + public void run(String s, String[] sArray) { + // Trigger C2's string concatenation optimization + add(s + Arrays.toString(sArray) + " const "); + } +} + +class Runner implements Runnable { + private TestStringObjectInitialization test; + + public Runner(TestStringObjectInitialization t) { + test = t; + } + + public void run(){ + String[] array = {"a", "b", "c"}; + for (int i = 0; i < 10000; ++i) { + test.run("a", array); + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/BadNameAndType.java Tue Nov 08 17:14:36 2016 +0300 @@ -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"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/emptyNameUtf8.jcod Tue Nov 08 17:14:36 2016 +0300 @@ -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 "<init>"; // #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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/classFileParserBug/emptySigUtf8.jcod Tue Nov 08 17:14:36 2016 +0300 @@ -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 "<init>"; // #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
--- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Thu Nov 03 13:12:50 2016 +0300 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Tue Nov 08 17:14:36 2016 +0300 @@ -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<String> asLines() { + return asLines(getOutput()); + } + + private List<String> asLines(String buffer) { + return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)")); + } }
--- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Thu Nov 03 13:12:50 2016 +0300 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Nov 08 17:14:36 2016 +0300 @@ -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.
--- a/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Thu Nov 03 13:12:50 2016 +0300 +++ b/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Tue Nov 08 17:14:36 2016 +0300 @@ -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;
--- a/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Thu Nov 03 13:12:50 2016 +0300 +++ b/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Tue Nov 08 17:14:36 2016 +0300 @@ -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 <T> void runTest(String existentFlag, T[] tests,