# HG changeset patch # User lana # Date 1439500523 25200 # Node ID 7bf24ea31a4d28b8e49fa2403fc6d9ae5463e524 # Parent bb7b9089c6b1d0f158035fa572adbb5cfdc94a4d# Parent 1f724ee1697273f332e0107ced15d12da869c088 Merge diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/aarch64.ad --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Aug 13 14:15:23 2015 -0700 @@ -2389,9 +2389,11 @@ // Note that the code buffer's insts_mark is always relative to insts. // 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 + 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(); __ far_jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); @@ -2405,9 +2407,11 @@ // Note that the code buffer's insts_mark is always relative to insts. // 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 + 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(); __ adr(lr, __ pc()); @@ -3657,24 +3661,37 @@ MacroAssembler _masm(&cbuf); address addr = (address)$meth$$method; + address call; if (!_method) { // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap. - __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf); + call = __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf); } else if (_optimized_virtual) { - __ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf); + call = __ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf); } else { - __ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf); + call = __ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf); + } + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; } 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; + } } %} enc_class aarch64_enc_java_dynamic_call(method meth) %{ MacroAssembler _masm(&cbuf); - __ ic_call((address)$meth$$method); + address call = __ ic_call((address)$meth$$method); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } %} enc_class aarch64_enc_call_epilog() %{ @@ -3695,7 +3712,11 @@ address entry = (address)$meth$$method; CodeBlob *cb = CodeCache::find_blob(entry); if (cb) { - __ trampoline_call(Address(entry, relocInfo::runtime_call_type)); + address call = __ trampoline_call(Address(entry, relocInfo::runtime_call_type)); + if (call == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } else { int gpcnt; int fpcnt; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -327,9 +327,16 @@ ce->align_call(lir_static_call); ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } Address resolve(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); - __ trampoline_call(resolve); + address call = __ trampoline_call(resolve); + if (call == NULL) { + ce->bailout("trampoline stub overflow"); + return; + } ce->add_call_info_here(info()); #ifndef PRODUCT diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1996,13 +1996,21 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { - __ trampoline_call(Address(op->addr(), rtype)); + address call = __ trampoline_call(Address(op->addr(), rtype)); + if (call == NULL) { + bailout("trampoline stub overflow"); + return; + } add_call_info(code_offset(), op->info()); } void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { - __ ic_call(op->addr()); + address call = __ ic_call(op->addr()); + if (call == NULL) { + bailout("trampoline stub overflow"); + return; + } add_call_info(code_offset(), op->info()); } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -26,6 +26,9 @@ #ifndef CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP #define CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP +// ArrayCopyStub needs access to bailout +friend class ArrayCopyStub; + private: int array_element_size(BasicType type) const; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -51,7 +51,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 @@ -63,10 +63,11 @@ // 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); - + address base = __ start_a_stub(to_interp_stub_size()); 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. @@ -76,6 +77,7 @@ assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big"); __ end_a_stub(); + return base; } #undef __ diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -664,7 +664,7 @@ // Maybe emit a call via a trampoline. If the code cache is small // trampolines won't be emitted. -void MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) { +address MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) { assert(entry.rspec().type() == relocInfo::runtime_call_type || entry.rspec().type() == relocInfo::opt_virtual_call_type || entry.rspec().type() == relocInfo::static_call_type @@ -672,7 +672,10 @@ unsigned int start_offset = offset(); if (far_branches() && !Compile::current()->in_scratch_emit_size()) { - emit_trampoline_stub(offset(), entry.target()); + address stub = emit_trampoline_stub(start_offset, entry.target()); + if (stub == NULL) { + return NULL; // CodeCache is full + } } if (cbuf) cbuf->set_insts_mark(); @@ -682,6 +685,8 @@ } else { bl(pc()); } + // just need to return a non-null address + return pc(); } @@ -696,13 +701,11 @@ // load the call target from the constant pool // branch (LR still points to the call site above) -void MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, +address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, address dest) { address stub = start_a_stub(Compile::MAX_stubs_size/2); if (stub == NULL) { - start_a_stub(Compile::MAX_stubs_size/2); - Compile::current()->env()->record_out_of_memory_failure(); - return; + return NULL; // CodeBuffer::expand failed } // Create a trampoline stub relocation which relates this trampoline stub @@ -729,15 +732,16 @@ assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline"); end_a_stub(); + return stub; } -void MacroAssembler::ic_call(address entry) { +address MacroAssembler::ic_call(address entry) { RelocationHolder rh = virtual_call_Relocation::spec(pc()); // address const_ptr = long_constant((jlong)Universe::non_oop_word()); // unsigned long offset; // ldr_constant(rscratch2, const_ptr); movptr(rscratch2, (uintptr_t)Universe::non_oop_word()); - trampoline_call(Address(entry, rh)); + return trampoline_call(Address(entry, rh)); } // Implementation of call_VM versions diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -539,7 +539,7 @@ static int patch_oop(address insn_addr, address o); - void emit_trampoline_stub(int insts_call_instruction_offset, address target); + address emit_trampoline_stub(int insts_call_instruction_offset, address target); // The following 4 methods return the offset of the appropriate move instruction @@ -942,7 +942,7 @@ // Calls - void trampoline_call(Address entry, CodeBuffer *cbuf = NULL); + address trampoline_call(Address entry, CodeBuffer *cbuf = NULL); static bool far_branches() { return ReservedCodeCacheSize > branch_range; @@ -962,7 +962,7 @@ } // Emit the CompiledIC call idiom - void ic_call(address entry); + address ic_call(address entry); public: diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -94,7 +94,7 @@ const int IC_pos_in_java_to_interp_stub = 8; #define __ _masm. -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { #ifdef COMPILER2 // Get the mark within main instrs section which is set to the address of the call. address call_addr = cbuf.insts_mark(); @@ -106,8 +106,7 @@ // Start the stub. address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); if (stub == NULL) { - Compile::current()->env()->record_out_of_memory_failure(); - return; + return NULL; // CodeCache is full } // For java_to_interp stubs we use R11_scratch1 as scratch register @@ -149,6 +148,7 @@ // End the stub. __ end_a_stub(); + return stub; #else ShouldNotReachHere(); #endif diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -2187,7 +2187,7 @@ } void InterpreterMacroAssembler::increment_invocation_counter(Register Rcounters, Register iv_be_count, Register Rtmp_r0) { - assert(UseCompiler, "incrementing must be useful"); + assert(UseCompiler || LogTouchedMethods, "incrementing must be useful"); Register invocation_count = iv_be_count; Register backedge_count = Rtmp_r0; int delta = InvocationCounter::count_increment; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Thu Aug 13 14:15:23 2015 -0700 @@ -1082,7 +1082,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; } @@ -1160,7 +1160,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); } @@ -3397,7 +3397,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); } @@ -3410,7 +3410,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; + } } %} @@ -3455,7 +3459,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. diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -432,6 +432,9 @@ __ mov(length()->as_register(), O4); ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } __ call(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); __ delayed()->nop(); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -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 diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -2314,7 +2314,7 @@ } void InterpreterMacroAssembler::increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 ) { - assert(UseCompiler, "incrementing must be useful"); + assert(UseCompiler || LogTouchedMethods, "incrementing must be useful"); assert_different_registers(Rcounters, Rtmp, Rtmp2); Address inv_counter(Rcounters, MethodCounters::invocation_counter_offset() + diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Thu Aug 13 14:15:23 2015 -0700 @@ -1773,9 +1773,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(); @@ -1796,9 +1798,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); @@ -2599,7 +2603,12 @@ emit_call_reloc(cbuf, $meth$$method, relocInfo::static_call_type); } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + // Stub does not fit into scratch buffer if TraceJumps is enabled + if (stub == NULL && !(TraceJumps && Compile::current()->in_scratch_emit_size())) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -503,6 +503,9 @@ ce->align_call(lir_static_call); ce->emit_static_call_stub(); + if (ce->compilation()->bailed_out()) { + return; // CodeCache is full + } AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); __ call(resolve); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/x86/vm/compiledIC_x86.cpp --- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -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 __ diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/x86/vm/x86.ad --- a/hotspot/src/cpu/x86/vm/x86.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/x86.ad Thu Aug 13 14:15:23 2015 -0700 @@ -1594,7 +1594,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"); @@ -1609,7 +1612,10 @@ // That's why we must use the macroassembler to generate a handler. MacroAssembler _masm(&cbuf); address base = __ start_a_stub(size_deopt_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return 0; // CodeBuffer::expand failed + } int offset = __ offset(); #ifdef _LP64 diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Thu Aug 13 14:15:23 2015 -0700 @@ -1907,7 +1907,11 @@ static_call_Relocation::spec(), RELOC_IMM32 ); } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Thu Aug 13 14:15:23 2015 -0700 @@ -2137,7 +2137,11 @@ } if (_method) { // Emit stub for static call. - CompiledStaticCall::emit_to_interp_stub(cbuf); + address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); + if (stub == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } } %} diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/cpu/zero/vm/compiledIC_zero.cpp --- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -60,8 +60,9 @@ // ---------------------------------------------------------------------------- -void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { ShouldNotReachHere(); // Only needed for COMPILER2. + return NULL; } int CompiledStaticCall::to_interp_stub_size() { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -971,34 +971,32 @@ guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???"); // calculate stack size if it's not specified by caller - if (os::Aix::supports_variable_stack_size()) { - if (stack_size == 0) { - stack_size = os::Aix::default_stack_size(thr_type); - - switch (thr_type) { - case os::java_thread: - // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss. - assert(JavaThread::stack_size_at_create() > 0, "this should be set"); - stack_size = JavaThread::stack_size_at_create(); + if (stack_size == 0) { + stack_size = os::Aix::default_stack_size(thr_type); + + switch (thr_type) { + case os::java_thread: + // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss. + assert(JavaThread::stack_size_at_create() > 0, "this should be set"); + stack_size = JavaThread::stack_size_at_create(); + break; + case os::compiler_thread: + if (CompilerThreadStackSize > 0) { + stack_size = (size_t)(CompilerThreadStackSize * K); break; - case os::compiler_thread: - if (CompilerThreadStackSize > 0) { - stack_size = (size_t)(CompilerThreadStackSize * K); - break; - } // else fall through: - // use VMThreadStackSize if CompilerThreadStackSize is not defined - case os::vm_thread: - case os::pgc_thread: - case os::cgc_thread: - case os::watcher_thread: - if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); - break; - } + } // else fall through: + // use VMThreadStackSize if CompilerThreadStackSize is not defined + case os::vm_thread: + case os::pgc_thread: + case os::cgc_thread: + case os::watcher_thread: + if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); + break; } - - stack_size = MAX2(stack_size, os::Aix::min_stack_allowed); - pthread_attr_setstacksize(&attr, stack_size); - } //else let thread_create() pick the default value (96 K on AIX) + } + + stack_size = MAX2(stack_size, os::Aix::min_stack_allowed); + pthread_attr_setstacksize(&attr, stack_size); pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/aix/vm/os_aix.hpp --- a/hotspot/src/os/aix/vm/os_aix.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -131,8 +131,6 @@ static void initialize_libo4(); static void initialize_libperfstat(); - static bool supports_variable_stack_size(); - public: static void init_thread_fpu_state(); static pthread_t main_thread(void) { return _main_thread; } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -739,40 +739,35 @@ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - // stack size - if (os::Bsd::supports_variable_stack_size()) { - // calculate stack size if it's not specified by caller - if (stack_size == 0) { - stack_size = os::Bsd::default_stack_size(thr_type); - - switch (thr_type) { - case os::java_thread: - // Java threads use ThreadStackSize which default value can be - // changed with the flag -Xss - assert(JavaThread::stack_size_at_create() > 0, "this should be set"); - stack_size = JavaThread::stack_size_at_create(); + // calculate stack size if it's not specified by caller + if (stack_size == 0) { + stack_size = os::Bsd::default_stack_size(thr_type); + + switch (thr_type) { + case os::java_thread: + // Java threads use ThreadStackSize which default value can be + // changed with the flag -Xss + assert(JavaThread::stack_size_at_create() > 0, "this should be set"); + stack_size = JavaThread::stack_size_at_create(); + break; + case os::compiler_thread: + if (CompilerThreadStackSize > 0) { + stack_size = (size_t)(CompilerThreadStackSize * K); break; - case os::compiler_thread: - if (CompilerThreadStackSize > 0) { - stack_size = (size_t)(CompilerThreadStackSize * K); - break; - } // else fall through: - // use VMThreadStackSize if CompilerThreadStackSize is not defined - case os::vm_thread: - case os::pgc_thread: - case os::cgc_thread: - case os::watcher_thread: - if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); - break; - } + } // else fall through: + // use VMThreadStackSize if CompilerThreadStackSize is not defined + case os::vm_thread: + case os::pgc_thread: + case os::cgc_thread: + case os::watcher_thread: + if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); + break; } - - stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed); - pthread_attr_setstacksize(&attr, stack_size); - } else { - // let pthread_create() pick the default value. } + stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed); + pthread_attr_setstacksize(&attr, stack_size); + ThreadState state; { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/bsd/vm/os_bsd.hpp --- a/hotspot/src/os/bsd/vm/os_bsd.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -75,8 +75,6 @@ static julong physical_memory() { return _physical_memory; } static void initialize_system_info(); - static bool supports_variable_stack_size(); - static void rebuild_cpu_to_node_map(); static GrowableArray* cpu_to_node() { return _cpu_to_node; } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -653,8 +653,7 @@ OSThread* osthread = thread->osthread(); Monitor* sync = osthread->startThread_lock(); - // thread_id is kernel thread id (similar to Solaris LWP id) - osthread->set_thread_id(os::Linux::gettid()); + osthread->set_thread_id(os::current_thread_id()); if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); @@ -712,38 +711,34 @@ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // stack size - if (os::Linux::supports_variable_stack_size()) { - // calculate stack size if it's not specified by caller - if (stack_size == 0) { - stack_size = os::Linux::default_stack_size(thr_type); - - switch (thr_type) { - case os::java_thread: - // Java threads use ThreadStackSize which default value can be - // changed with the flag -Xss - assert(JavaThread::stack_size_at_create() > 0, "this should be set"); - stack_size = JavaThread::stack_size_at_create(); + // calculate stack size if it's not specified by caller + if (stack_size == 0) { + stack_size = os::Linux::default_stack_size(thr_type); + + switch (thr_type) { + case os::java_thread: + // Java threads use ThreadStackSize which default value can be + // changed with the flag -Xss + assert(JavaThread::stack_size_at_create() > 0, "this should be set"); + stack_size = JavaThread::stack_size_at_create(); + break; + case os::compiler_thread: + if (CompilerThreadStackSize > 0) { + stack_size = (size_t)(CompilerThreadStackSize * K); break; - case os::compiler_thread: - if (CompilerThreadStackSize > 0) { - stack_size = (size_t)(CompilerThreadStackSize * K); - break; - } // else fall through: - // use VMThreadStackSize if CompilerThreadStackSize is not defined - case os::vm_thread: - case os::pgc_thread: - case os::cgc_thread: - case os::watcher_thread: - if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); - break; - } + } // else fall through: + // use VMThreadStackSize if CompilerThreadStackSize is not defined + case os::vm_thread: + case os::pgc_thread: + case os::cgc_thread: + case os::watcher_thread: + if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); + break; } - - stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); - pthread_attr_setstacksize(&attr, stack_size); - } else { - // let pthread_create() pick the default value. - } + } + + stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); + pthread_attr_setstacksize(&attr, stack_size); // glibc guard page pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type)); @@ -1424,7 +1419,8 @@ return n; } -intx os::current_thread_id() { return (intx)pthread_self(); } +// thread_id is kernel thread id (similar to Solaris LWP id) +intx os::current_thread_id() { return os::Linux::gettid(); } int os::current_process_id() { return ::getpid(); } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os/linux/vm/os_linux.hpp --- a/hotspot/src/os/linux/vm/os_linux.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -83,8 +83,6 @@ static void set_glibc_version(const char *s) { _glibc_version = s; } static void set_libpthread_version(const char *s) { _libpthread_version = s; } - static bool supports_variable_stack_size(); - static void rebuild_cpu_to_node_map(); static GrowableArray* cpu_to_node() { return _cpu_to_node; } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2014 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -489,10 +489,6 @@ size_t os::Aix::min_stack_allowed = 128*K; -// Aix is always in floating stack mode. The stack size for a new -// thread can be set via pthread_attr_setstacksize(). -bool os::Aix::supports_variable_stack_size() { return true; } - // return default stack size for thr_type size_t os::Aix::default_stack_size(os::ThreadType thr_type) { // default stack size (compiler thread needs larger stack) diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -780,9 +780,6 @@ #ifdef AMD64 size_t os::Bsd::min_stack_allowed = 64 * K; - -// amd64: pthread on amd64 is always in floating stack mode -bool os::Bsd::supports_variable_stack_size() { return true; } #else size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K; @@ -790,7 +787,6 @@ #define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;}) #endif -bool os::Bsd::supports_variable_stack_size() { return true; } #endif // AMD64 // return default stack size for thr_type diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -290,10 +290,6 @@ size_t os::Bsd::min_stack_allowed = 64 * K; -bool os::Bsd::supports_variable_stack_size() { - return true; -} - size_t os::Bsd::default_stack_size(os::ThreadType thr_type) { #ifdef _LP64 size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp --- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -496,9 +496,6 @@ size_t os::Linux::min_stack_allowed = 64 * K; -// aarch64: pthread on aarch64 is always in floating stack mode -bool os::Linux::supports_variable_stack_size() { return true; } - // return default stack size for thr_type size_t os::Linux::default_stack_size(os::ThreadType thr_type) { // default stack size (compiler thread needs larger stack) diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -467,8 +467,6 @@ size_t os::Linux::min_stack_allowed = 128*K; -bool os::Linux::supports_variable_stack_size() { return true; } - // return default stack size for thr_type size_t os::Linux::default_stack_size(os::ThreadType thr_type) { // default stack size (compiler thread needs larger stack) diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -733,9 +733,6 @@ size_t os::Linux::min_stack_allowed = 128 * K; -// pthread on Ubuntu is always in floating stack mode -bool os::Linux::supports_variable_stack_size() { return true; } - // return default stack size for thr_type size_t os::Linux::default_stack_size(os::ThreadType thr_type) { // default stack size (compiler thread needs larger stack) diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -623,11 +623,6 @@ size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K; #endif // AMD64 -// Test if pthread library can support variable thread stack size. -bool os::Linux::supports_variable_stack_size() { - return true; -} - // return default stack size for thr_type size_t os::Linux::default_stack_size(os::ThreadType thr_type) { // default stack size (compiler thread needs larger stack) diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -305,10 +305,6 @@ size_t os::Linux::min_stack_allowed = 64 * K; -bool os::Linux::supports_variable_stack_size() { - return true; -} - size_t os::Linux::default_stack_size(os::ThreadType thr_type) { #ifdef _LP64 size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/c1/c1_Compiler.cpp --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -239,25 +239,6 @@ return true; } -bool Compiler::is_intrinsic_disabled_by_flag(methodHandle method) { - vmIntrinsics::ID id = method->intrinsic_id(); - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - - if (vmIntrinsics::is_disabled_by_flags(id)) { - return true; - } - - if (!InlineNatives && id != vmIntrinsics::_Reference_get) { - return true; - } - - if (!InlineClassNatives && id == vmIntrinsics::_getClass) { - return true; - } - - return false; -} - void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) { BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); assert(buffer_blob != NULL, "Must exist"); @@ -275,7 +256,3 @@ void Compiler::print_timers() { Compilation::print_timers(); } - -bool Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) { - return is_intrinsic_supported(method) && !is_intrinsic_disabled_by_flag(method); -} diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/c1/c1_Compiler.hpp --- a/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -55,18 +55,9 @@ // Print compilation timers and statistics virtual void print_timers(); - // Check the availability of an intrinsic for 'method' given a compilation context. - // The compilation context is needed to support per-method usage of the - // DisableIntrinsic flag. However, as C1 ignores the DisableIntrinsic flag, it - // ignores the compilation context. - virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context); - // Check if the C1 compiler supports an intrinsic for 'method'. virtual bool is_intrinsic_supported(methodHandle method); - // Processing of command-line flags specific to the C1 compiler. - virtual bool is_intrinsic_disabled_by_flag(methodHandle method); - // Size of the code buffer static int code_buffer_size(); }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -3491,8 +3491,16 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { // For calling is_intrinsic_available we need to transition to // the '_thread_in_vm' state because is_intrinsic_available() - // does not accesses critical VM-internal data. - if (!_compilation->compiler()->is_intrinsic_available(callee->get_Method(), NULL)) { + // accesses critical VM-internal data. + bool is_available = false; + { + VM_ENTRY_MARK; + methodHandle mh(THREAD, callee->get_Method()); + methodHandle ct(THREAD, method()->get_Method()); + is_available = _compilation->compiler()->is_intrinsic_available(mh, ct); + } + + if (!is_available) { if (!InlineNatives) { // Return false and also set message that the inlining of // intrinsics has been disabled in general. diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -443,6 +443,7 @@ // emit the static call stub stuff out of line emit_static_call_stub(); + CHECK_BAILOUT(); switch (op->code()) { case lir_static_call: diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/classfile/imageDecompressor.cpp --- a/hotspot/src/share/vm/classfile/imageDecompressor.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/classfile/imageDecompressor.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -22,8 +22,8 @@ * */ +#include "precompiled.hpp" #include "runtime/thread.inline.hpp" -#include "precompiled.hpp" #include "classfile/imageDecompressor.hpp" #include "runtime/thread.hpp" #include "utilities/bytes.hpp" diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/classfile/imageDecompressor.hpp --- a/hotspot/src/share/vm/classfile/imageDecompressor.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/classfile/imageDecompressor.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -26,7 +26,6 @@ #define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP #include "runtime/thread.inline.hpp" -#include "precompiled.hpp" #include "classfile/classLoader.hpp" #include "classfile/imageFile.hpp" #include "classfile/symbolTable.hpp" diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/classfile/vmSymbols.cpp --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -417,8 +417,59 @@ } } -bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { +bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) { + vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); + + // Check if the intrinsic corresponding to 'method' has been disabled on + // the command line by using the DisableIntrinsic flag (either globally + // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp + // for details). + // Usually, the compilation context is the caller of the method 'method'. + // The only case when for a non-recursive method 'method' the compilation context + // is not the caller of the 'method' (but it is the method itself) is + // java.lang.ref.Referene::get. + // For java.lang.ref.Reference::get, the intrinsic version is used + // instead of the compiled version so that the value in the referent + // field can be registered by the G1 pre-barrier code. The intrinsified + // version of Reference::get also adds a memory barrier to prevent + // commoning reads from the referent field across safepoint since GC + // can change the referent field's value. See Compile::Compile() + // in src/share/vm/opto/compile.cpp or + // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp + // for more details. + ccstr disable_intr = NULL; + if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) || + (!compilation_context.is_null() && + CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) && + strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL) + ) { + return true; + } + + // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in + // the following switch statement. + if (!InlineNatives) { + switch (id) { + case vmIntrinsics::_indexOf: + case vmIntrinsics::_compareTo: + case vmIntrinsics::_equals: + case vmIntrinsics::_equalsC: + case vmIntrinsics::_getAndAddInt: + case vmIntrinsics::_getAndAddLong: + case vmIntrinsics::_getAndSetInt: + case vmIntrinsics::_getAndSetLong: + case vmIntrinsics::_getAndSetObject: + case vmIntrinsics::_loadFence: + case vmIntrinsics::_storeFence: + case vmIntrinsics::_fullFence: + case vmIntrinsics::_Reference_get: + break; + default: + return true; + } + } + switch (id) { case vmIntrinsics::_isInstance: case vmIntrinsics::_isAssignableFrom: @@ -430,6 +481,7 @@ case vmIntrinsics::_Class_cast: case vmIntrinsics::_getLength: case vmIntrinsics::_newArray: + case vmIntrinsics::_getClass: if (!InlineClassNatives) return true; break; case vmIntrinsics::_currentThread: @@ -522,6 +574,12 @@ case vmIntrinsics::_getAndSetInt: case vmIntrinsics::_getAndSetLong: case vmIntrinsics::_getAndSetObject: + case vmIntrinsics::_loadFence: + case vmIntrinsics::_storeFence: + case vmIntrinsics::_fullFence: + case vmIntrinsics::_compareAndSwapObject: + case vmIntrinsics::_compareAndSwapLong: + case vmIntrinsics::_compareAndSwapInt: if (!InlineUnsafeOps) return true; break; case vmIntrinsics::_getShortUnaligned: @@ -584,8 +642,8 @@ if (!InlineObjectCopy || !InlineArrayCopy) return true; break; case vmIntrinsics::_compareTo: - if (!SpecialStringCompareTo) return true; - break; + if (!SpecialStringCompareTo) return true; + break; case vmIntrinsics::_indexOf: if (!SpecialStringIndexOf) return true; break; @@ -602,8 +660,8 @@ if (!InlineReflectionGetCallerClass) return true; break; case vmIntrinsics::_multiplyToLen: - if (!UseMultiplyToLenIntrinsic) return true; - break; + if (!UseMultiplyToLenIntrinsic) return true; + break; case vmIntrinsics::_squareToLen: if (!UseSquareToLenIntrinsic) return true; break; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -568,6 +568,11 @@ template(java_lang_management_ThreadInfo_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V") \ template(java_lang_management_ThreadInfo_with_locks_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V") \ template(long_long_long_long_void_signature, "(JJJJ)V") \ + template(finalizer_histogram_klass, "java/lang/ref/FinalizerHistogram") \ + template(void_finalizer_histogram_entry_array_signature, "()[Ljava/lang/ref/FinalizerHistogram$Entry;") \ + template(get_finalizer_histogram_name, "getFinalizerHistogram") \ + template(finalizer_histogram_entry_name_field, "className") \ + template(finalizer_histogram_entry_count_field, "instanceCount") \ \ template(java_lang_management_MemoryPoolMXBean, "java/lang/management/MemoryPoolMXBean") \ template(java_lang_management_MemoryManagerMXBean, "java/lang/management/MemoryManagerMXBean") \ @@ -1384,10 +1389,9 @@ // 'method' requires predicated logic. static int predicates_needed(vmIntrinsics::ID id); - // Returns true if an intrinsic is disabled by command-line flags and - // false otherwise. Implements functionality common to the C1 - // and the C2 compiler. - static bool is_disabled_by_flags(vmIntrinsics::ID id); + // Returns true if a compiler intrinsic is disabled by command-line flags + // and false otherwise. + static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context); }; #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/code/compiledIC.hpp --- a/hotspot/src/share/vm/code/compiledIC.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/code/compiledIC.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -306,7 +306,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(); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/compiler/abstractCompiler.hpp --- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -75,8 +75,8 @@ // // The second parameter, 'compilation_context', is needed to implement functionality // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can - // be used to prohibit the C2 compiler (but not the C1 compiler) to use an intrinsic. - // There are three ways to disable an intrinsic using the DisableIntrinsic flag: + // be used to prohibit the compilers to use an intrinsic. There are three ways to + // disable an intrinsic using the DisableIntrinsic flag: // // (1) -XX:DisableIntrinsic=_hashCode,_getClass // Disables intrinsification of _hashCode and _getClass globally @@ -96,7 +96,8 @@ // compilation context is aClass::aMethod and java.lang.ref.Reference::get, // respectively. virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) { - return false; + return is_intrinsic_supported(method) && + !vmIntrinsics::is_disabled_by_flags(method, compilation_context); } // Determines if an intrinsic is supported by the compiler, that is, @@ -111,13 +112,6 @@ return false; } - // Implements compiler-specific processing of command-line flags. - // Processing of command-line flags common to all compilers is implemented - // in vmIntrinsicss::is_disabled_by_flag. - virtual bool is_intrinsic_disabled_by_flag(methodHandle method) { - return false; - } - // Compiler type queries. bool is_c1() { return _type == c1; } bool is_c2() { return _type == c2; } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/arraycopynode.cpp --- a/hotspot/src/share/vm/opto/arraycopynode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/arraycopynode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -79,10 +79,15 @@ #ifndef PRODUCT const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"}; + void ArrayCopyNode::dump_spec(outputStream *st) const { CallNode::dump_spec(st); st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : ""); } + +void ArrayCopyNode::dump_compact_spec(outputStream* st) const { + st->print("%s%s", _kind_names[_kind], _alloc_tightly_coupled ? ",tight" : ""); +} #endif intptr_t ArrayCopyNode::get_length_if_constant(PhaseGVN *phase) const { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/arraycopynode.hpp --- a/hotspot/src/share/vm/opto/arraycopynode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/arraycopynode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -164,6 +164,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream* st) const; #endif }; #endif // SHARE_VM_OPTO_ARRAYCOPYNODE_HPP diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/c2_globals.hpp --- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/c2_globals.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -623,9 +623,6 @@ diagnostic(bool, PrintIntrinsics, false, \ "prints attempted and successful inlining of intrinsics") \ \ - diagnostic(ccstrlist, DisableIntrinsic, "", \ - "do not expand intrinsics whose (internal) names appear here") \ - \ develop(bool, StressReflectiveCode, false, \ "Use inexact types at allocations, etc., to test reflection") \ \ diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/c2compiler.cpp --- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/c2compiler.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -157,14 +157,6 @@ Compile::print_timers(); } -bool C2Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) { - // Assume a non-virtual dispatch. A virtual dispatch is - // possible for only a limited set of available intrinsics whereas - // a non-virtual dispatch is possible for all available intrinsics. - return is_intrinsic_supported(method, false) && - !is_intrinsic_disabled_by_flag(method, compilation_context); -} - bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) { vmIntrinsics::ID id = method->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -436,78 +428,6 @@ return true; } -bool C2Compiler::is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context) { - vmIntrinsics::ID id = method->intrinsic_id(); - assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); - - if (vmIntrinsics::is_disabled_by_flags(method->intrinsic_id())) { - return true; - } - - // Check if the intrinsic corresponding to 'method' has been disabled on - // the command line by using the DisableIntrinsic flag (either globally - // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp - // for details). - // Usually, the compilation context is the caller of the method 'method'. - // The only case when for a non-recursive method 'method' the compilation context - // is not the caller of the 'method' (but it is the method itself) is - // java.lang.ref.Referene::get. - // For java.lang.ref.Reference::get, the intrinsic version is used - // instead of the C2-compiled version so that the value in the referent - // field can be registered by the G1 pre-barrier code. The intrinsified - // version of Reference::get also adds a memory barrier to prevent - // commoning reads from the referent field across safepoint since GC - // can change the referent field's value. See Compile::Compile() - // in src/share/vm/opto/compile.cpp for more details. - ccstr disable_intr = NULL; - if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) || - (!compilation_context.is_null() && - CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) && - strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL) - ) { - return true; - } - - // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in - // the following switch statement. - if (!InlineNatives) { - switch (id) { - case vmIntrinsics::_indexOf: - case vmIntrinsics::_compareTo: - case vmIntrinsics::_equals: - case vmIntrinsics::_equalsC: - case vmIntrinsics::_getAndAddInt: - case vmIntrinsics::_getAndAddLong: - case vmIntrinsics::_getAndSetInt: - case vmIntrinsics::_getAndSetLong: - case vmIntrinsics::_getAndSetObject: - case vmIntrinsics::_loadFence: - case vmIntrinsics::_storeFence: - case vmIntrinsics::_fullFence: - case vmIntrinsics::_Reference_get: - break; - default: - return true; - } - } - - if (!InlineUnsafeOps) { - switch (id) { - case vmIntrinsics::_loadFence: - case vmIntrinsics::_storeFence: - case vmIntrinsics::_fullFence: - case vmIntrinsics::_compareAndSwapObject: - case vmIntrinsics::_compareAndSwapLong: - case vmIntrinsics::_compareAndSwapInt: - return true; - default: - return false; - } - } - - return false; -} - int C2Compiler::initial_code_buffer_size() { assert(SegmentedCodeCache, "Should be only used with a segmented code cache"); return Compile::MAX_inst_size + Compile::MAX_locs_size + initial_const_capacity; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/c2compiler.hpp --- a/hotspot/src/share/vm/opto/c2compiler.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/c2compiler.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -51,11 +51,11 @@ // Print compilation timers and statistics void print_timers(); - // Check the availability of an intrinsic for 'method' given a compilation context. - virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context); - // Return true if the intrinsification of a method supported by the compiler - // assuming a non-virtual dispatch. Return false otherwise. + // assuming a non-virtual dispatch. (A virtual dispatch is + // possible for only a limited set of available intrinsics whereas + // a non-virtual dispatch is possible for all available intrinsics.) + // Return false otherwise. virtual bool is_intrinsic_supported(methodHandle method) { return is_intrinsic_supported(method, false); } @@ -64,13 +64,6 @@ // the dispatch mode specified by the 'is_virtual' parameter. virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual); - // Processing of command-line flags specific to the C2 compiler. - virtual bool is_intrinsic_disabled_by_flag(methodHandle method) { - return is_intrinsic_disabled_by_flag(method, NULL); - } - - virtual bool is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context); - // Initial size of the code buffer (may be increased at runtime) static int initial_code_buffer_size(); }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -52,6 +52,7 @@ const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; } #ifndef PRODUCT void StartNode::dump_spec(outputStream *st) const { st->print(" #"); _domain->dump_on(st);} +void StartNode::dump_compact_spec(outputStream *st) const { /* empty */ } #endif //------------------------------Ideal------------------------------------------ @@ -121,6 +122,23 @@ if( !Verbose && !WizardMode ) bottom_type()->dump_on(st); } } + +void ParmNode::dump_compact_spec(outputStream *st) const { + if (_con < TypeFunc::Parms) { + st->print("%s", names[_con]); + } else { + st->print("%d:", _con-TypeFunc::Parms); + // unconditionally dump bottom_type + bottom_type()->dump_on(st); + } +} + +// For a ParmNode, all immediate inputs and outputs are considered relevant +// both in compact and standard representation. +void ParmNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); +} #endif uint ParmNode::ideal_reg() const { @@ -948,6 +966,14 @@ if( _method ) _method->print_short_name(st); CallNode::dump_spec(st); } + +void CallJavaNode::dump_compact_spec(outputStream* st) const { + if (_method) { + _method->print_short_name(st); + } else { + st->print(""); + } +} #endif //============================================================================= @@ -995,6 +1021,16 @@ } CallJavaNode::dump_spec(st); } + +void CallStaticJavaNode::dump_compact_spec(outputStream* st) const { + if (_method) { + _method->print_short_name(st); + } else if (_name) { + st->print("%s", _name); + } else { + st->print(""); + } +} #endif //============================================================================= @@ -1130,6 +1166,19 @@ st->print(" SafePoint "); _replaced_nodes.dump(st); } + +// The related nodes of a SafepointNode are all data inputs, excluding the +// control boundary, as well as all outputs till level 2 (to include projection +// nodes and targets). In compact mode, just include inputs till level 1 and +// outputs as before. +void SafePointNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif const RegMask &SafePointNode::in_RegMask(uint idx) const { @@ -1676,6 +1725,27 @@ _counter->set_tag(NamedCounter::EliminatedLockCounter); } } + +const char* AbstractLockNode::_kind_names[] = {"Regular", "NonEscObj", "Coarsened", "Nested"}; + +void AbstractLockNode::dump_spec(outputStream* st) const { + st->print("%s ", _kind_names[_kind]); + CallNode::dump_spec(st); +} + +void AbstractLockNode::dump_compact_spec(outputStream* st) const { + st->print("%s", _kind_names[_kind]); +} + +// The related set of lock nodes includes the control boundary. +void AbstractLockNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, true); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif //============================================================================= diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/callnode.hpp --- a/hotspot/src/share/vm/opto/callnode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/callnode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -84,6 +84,7 @@ virtual uint ideal_reg() const { return 0; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; #endif }; @@ -110,6 +111,8 @@ virtual uint ideal_reg() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -476,6 +479,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -675,6 +679,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; #endif }; @@ -730,6 +735,7 @@ virtual int Opcode() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; #endif }; @@ -951,6 +957,7 @@ } _kind; #ifndef PRODUCT NamedCounter* _counter; + static const char* _kind_names[Nested+1]; #endif protected: @@ -1005,6 +1012,9 @@ #ifndef PRODUCT void create_lock_counter(JVMState* s); NamedCounter* counter() const { return _counter; } + virtual void dump_spec(outputStream* st) const; + virtual void dump_compact_spec(outputStream* st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/cfgnode.cpp --- a/hotspot/src/share/vm/opto/cfgnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/cfgnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -2023,6 +2023,14 @@ } #ifndef PRODUCT +void PhiNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + // For a PhiNode, the set of related nodes includes all inputs till level 2, + // and all outputs till level 1. In compact mode, inputs till level 1 are + // collected. + this->collect_nodes(in_rel, compact ? 1 : 2, false, false); + this->collect_nodes(out_rel, -1, false, false); +} + void PhiNode::dump_spec(outputStream *st) const { TypeNode::dump_spec(st); if (is_tripcount()) { @@ -2047,11 +2055,33 @@ return RegMask::Empty; } +#ifndef PRODUCT +//-----------------------------related----------------------------------------- +// The related nodes of a GotoNode are all inputs at level 1, as well as the +// outputs at level 1. This is regardless of compact mode. +void GotoNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); +} +#endif + + //============================================================================= const RegMask &JumpNode::out_RegMask() const { return RegMask::Empty; } +#ifndef PRODUCT +//-----------------------------related----------------------------------------- +// The related nodes of a JumpNode are all inputs at level 1, as well as the +// outputs at level 2 (to include actual jump targets beyond projection nodes). +// This is regardless of compact mode. +void JumpNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -2, false, false); +} +#endif + //============================================================================= const RegMask &JProjNode::out_RegMask() const { return RegMask::Empty; @@ -2105,7 +2135,18 @@ #ifndef PRODUCT void JumpProjNode::dump_spec(outputStream *st) const { ProjNode::dump_spec(st); - st->print("@bci %d ",_dest_bci); + st->print("@bci %d ",_dest_bci); +} + +void JumpProjNode::dump_compact_spec(outputStream *st) const { + ProjNode::dump_compact_spec(st); + st->print("(%d)%d@%d", _switch_val, _proj_no, _dest_bci); +} + +void JumpProjNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + // The related nodes of a JumpProjNode are its inputs and outputs at level 1. + this->collect_nodes(in_rel, 1, false, false); + this->collect_nodes(out_rel, -1, false, false); } #endif diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/cfgnode.hpp --- a/hotspot/src/share/vm/opto/cfgnode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/cfgnode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -204,6 +204,7 @@ virtual const RegMask &out_RegMask() const; virtual const RegMask &in_RegMask(uint) const; #ifndef PRODUCT + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; virtual void dump_spec(outputStream *st) const; #endif #ifdef ASSERT @@ -229,6 +230,10 @@ virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); virtual const RegMask &out_RegMask() const; + +#ifndef PRODUCT + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; //------------------------------CProjNode-------------------------------------- @@ -382,6 +387,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; @@ -393,6 +399,11 @@ protected: // Type of If input when this branch is always taken virtual bool always_taken(const TypeTuple* t) const = 0; + +#ifndef PRODUCT +public: + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; class IfTrueNode : public IfProjNode { @@ -455,6 +466,9 @@ virtual int Opcode() const; virtual const RegMask& out_RegMask() const; virtual const Node* is_block_proj() const { return this; } +#ifndef PRODUCT + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; class JumpProjNode : public JProjNode { @@ -479,6 +493,8 @@ uint proj_no() const { return _proj_no; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/compile.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -594,6 +594,10 @@ n->as_MachBranch()->label_set(&fakeL, 0); } n->emit(buf, this->regalloc()); + + // Emitting into the scratch buffer should not fail + assert (!failing(), err_msg_res("Must not have pending failure. Reason is: %s", failure_reason())); + if (is_branch) // Restore label. n->as_MachBranch()->label_set(saveL, save_bnum); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/ifnode.cpp --- a/hotspot/src/share/vm/opto/ifnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/ifnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, 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 @@ -1601,11 +1601,41 @@ return this; } +#ifndef PRODUCT +//-------------------------------related--------------------------------------- +// An IfProjNode's related node set consists of its input (an IfNode) including +// the IfNode's condition, plus all of its outputs at level 1. In compact mode, +// the restrictions for IfNode apply (see IfNode::rel). +void IfProjNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + Node* ifNode = this->in(0); + in_rel->append(ifNode); + if (compact) { + ifNode->collect_nodes(in_rel, 3, false, true); + } else { + ifNode->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -1, false, false); +} + //------------------------------dump_spec-------------------------------------- -#ifndef PRODUCT void IfNode::dump_spec(outputStream *st) const { st->print("P=%f, C=%f",_prob,_fcnt); } + +//-------------------------------related--------------------------------------- +// For an IfNode, the set of related output nodes is just the output nodes till +// depth 2, i.e, the IfTrue/IfFalse projection nodes plus the nodes they refer. +// The related input nodes contain no control nodes, but all data nodes +// pertaining to the condition. In compact mode, the input nodes are collected +// up to a depth of 3. +void IfNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 3, false, true); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} #endif //------------------------------idealize_test---------------------------------- diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -327,7 +327,7 @@ methodHandle mh(THREAD, m->get_Method()); methodHandle ct(THREAD, method()->get_Method()); is_available = compiler->is_intrinsic_supported(mh, is_virtual) && - !compiler->is_intrinsic_disabled_by_flag(mh, ct); + !vmIntrinsics::is_disabled_by_flags(mh, ct); } if (is_available) { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/movenode.cpp --- a/hotspot/src/share/vm/opto/movenode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/movenode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -396,3 +396,17 @@ return TypeLong::make( v.get_jlong() ); } +#ifndef PRODUCT +//----------------------------BinaryNode--------------------------------------- +// The set of related nodes for a BinaryNode is all data inputs and all outputs +// till level 2 (i.e., one beyond the associated CMoveNode). In compact mode, +// it's the inputs till level 1 and the outputs till level 2. +void BinaryNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, true); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -2, false, false); +} +#endif diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/movenode.hpp --- a/hotspot/src/share/vm/opto/movenode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/movenode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -145,6 +145,10 @@ BinaryNode( Node *n1, Node *n2 ) : Node(0,n1,n2) { } virtual int Opcode() const; virtual uint ideal_reg() const { return 0; } + +#ifndef PRODUCT + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/multnode.cpp --- a/hotspot/src/share/vm/opto/multnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/multnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -118,6 +118,20 @@ bool ProjNode::pinned() const { return in(0)->pinned(); } #ifndef PRODUCT void ProjNode::dump_spec(outputStream *st) const { st->print("#%d",_con); if(_is_io_use) st->print(" (i_o_use)");} + +void ProjNode::dump_compact_spec(outputStream *st) const { + for (DUIterator i = this->outs(); this->has_out(i); i++) { + Node* o = this->out(i); + if (NotANode(o)) { + st->print("[?]"); + } else if (o == NULL) { + st->print("[_]"); + } else { + st->print("[%d]", o->_idx); + } + } + st->print("#%d", _con); +} #endif //----------------------------check_con---------------------------------------- diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/multnode.hpp --- a/hotspot/src/share/vm/opto/multnode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/multnode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -87,6 +87,7 @@ #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; #endif // Return uncommon trap call node if proj is for "proj->[region->..]call_uct" diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/node.cpp --- a/hotspot/src/share/vm/opto/node.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/node.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1489,16 +1489,6 @@ #ifndef PRODUCT -//----------------------------NotANode---------------------------------------- -// Used in debugging code to avoid walking across dead or uninitialized edges. -static inline bool NotANode(const Node* n) { - if (n == NULL) return true; - if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. - if (*(address*)n == badAddress) return true; // kill by Node::destruct - return false; -} - - //------------------------------find------------------------------------------ // Find a neighbor of this Node with the given _idx // If idx is negative, find its absolute value, following both _in and _out. @@ -1636,11 +1626,11 @@ //------------------------------dump------------------------------------------ // Dump a Node -void Node::dump(const char* suffix, outputStream *st) const { +void Node::dump(const char* suffix, bool mark, outputStream *st) const { Compile* C = Compile::current(); bool is_new = C->node_arena()->contains(this); C->_in_dump_cnt++; - st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name()); + st->print("%c%d%s\t%s\t=== ", is_new ? ' ' : 'o', _idx, mark ? " >" : "", Name()); // Dump the required and precedence inputs dump_req(st); @@ -1760,42 +1750,60 @@ st->print("]] "); } -//------------------------------dump_nodes------------------------------------- -static void dump_nodes(const Node* start, int d, bool only_ctrl) { - Node* s = (Node*)start; // remove const - if (NotANode(s)) return; - - uint depth = (uint)ABS(d); - int direction = d; - Compile* C = Compile::current(); - GrowableArray nstack(C->unique()); - - nstack.append(s); +//----------------------------collect_nodes_i---------------------------------- +// Collects nodes from an Ideal graph, starting from a given start node and +// moving in a given direction until a certain depth (distance from the start +// node) is reached. Duplicates are ignored. +// Arguments: +// nstack: the nodes are collected into this array. +// start: the node at which to start collecting. +// direction: if this is a positive number, collect input nodes; if it is +// a negative number, collect output nodes. +// depth: collect nodes up to this distance from the start node. +// include_start: whether to include the start node in the result collection. +// only_ctrl: whether to regard control edges only during traversal. +// only_data: whether to regard data edges only during traversal. +static void collect_nodes_i(GrowableArray *nstack, const Node* start, int direction, uint depth, bool include_start, bool only_ctrl, bool only_data) { + Node* s = (Node*) start; // remove const + nstack->append(s); int begin = 0; int end = 0; for(uint i = 0; i < depth; i++) { - end = nstack.length(); + end = nstack->length(); for(int j = begin; j < end; j++) { - Node* tp = nstack.at(j); + Node* tp = nstack->at(j); uint limit = direction > 0 ? tp->len() : tp->outcnt(); for(uint k = 0; k < limit; k++) { Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k); if (NotANode(n)) continue; // do not recurse through top or the root (would reach unrelated stuff) - if (n->is_Root() || n->is_top()) continue; + if (n->is_Root() || n->is_top()) continue; if (only_ctrl && !n->is_CFG()) continue; + if (only_data && n->is_CFG()) continue; - bool on_stack = nstack.contains(n); + bool on_stack = nstack->contains(n); if (!on_stack) { - nstack.append(n); + nstack->append(n); } } } begin = end; } - end = nstack.length(); - if (direction > 0) { + if (!include_start) { + nstack->remove(s); + } +} + +//------------------------------dump_nodes------------------------------------- +static void dump_nodes(const Node* start, int d, bool only_ctrl) { + if (NotANode(start)) return; + + GrowableArray nstack(Compile::current()->unique()); + collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false); + + int end = nstack.length(); + if (d > 0) { for(int j = end-1; j >= 0; j--) { nstack.at(j)->dump(); } @@ -1817,6 +1825,221 @@ dump_nodes(this, d, true); } +//-----------------------------dump_compact------------------------------------ +void Node::dump_comp() const { + this->dump_comp("\n"); +} + +//-----------------------------dump_compact------------------------------------ +// Dump a Node in compact representation, i.e., just print its name and index. +// Nodes can specify additional specifics to print in compact representation by +// implementing dump_compact_spec. +void Node::dump_comp(const char* suffix, outputStream *st) const { + Compile* C = Compile::current(); + C->_in_dump_cnt++; + st->print("%s(%d)", Name(), _idx); + this->dump_compact_spec(st); + if (suffix) { + st->print("%s", suffix); + } + C->_in_dump_cnt--; +} + +//----------------------------dump_related------------------------------------- +// Dump a Node's related nodes - the notion of "related" depends on the Node at +// hand and is determined by the implementation of the virtual method rel. +void Node::dump_related() const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + this->related(&in_rel, &out_rel, false); + for (int i = in_rel.length() - 1; i >= 0; i--) { + in_rel.at(i)->dump(); + } + this->dump("\n", true); + for (int i = 0; i < out_rel.length(); i++) { + out_rel.at(i)->dump(); + } +} + +//----------------------------dump_related------------------------------------- +// Dump a Node's related nodes up to a given depth (distance from the start +// node). +// Arguments: +// d_in: depth for input nodes. +// d_out: depth for output nodes (note: this also is a positive number). +void Node::dump_related(uint d_in, uint d_out) const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + + // call collect_nodes_i directly + collect_nodes_i(&in_rel, this, 1, d_in, false, false, false); + collect_nodes_i(&out_rel, this, -1, d_out, false, false, false); + + for (int i = in_rel.length() - 1; i >= 0; i--) { + in_rel.at(i)->dump(); + } + this->dump("\n", true); + for (int i = 0; i < out_rel.length(); i++) { + out_rel.at(i)->dump(); + } +} + +//------------------------dump_related_compact--------------------------------- +// Dump a Node's related nodes in compact representation. The notion of +// "related" depends on the Node at hand and is determined by the implementation +// of the virtual method rel. +void Node::dump_related_compact() const { + Compile* C = Compile::current(); + GrowableArray in_rel(C->unique()); + GrowableArray out_rel(C->unique()); + this->related(&in_rel, &out_rel, true); + int n_in = in_rel.length(); + int n_out = out_rel.length(); + + this->dump_comp(n_in == 0 ? "\n" : " "); + for (int i = 0; i < n_in; i++) { + in_rel.at(i)->dump_comp(i == n_in - 1 ? "\n" : " "); + } + for (int i = 0; i < n_out; i++) { + out_rel.at(i)->dump_comp(i == n_out - 1 ? "\n" : " "); + } +} + +//------------------------------related---------------------------------------- +// Collect a Node's related nodes. The default behaviour just collects the +// inputs and outputs at depth 1, including both control and data flow edges, +// regardless of whether the presentation is compact or not. For data nodes, +// the default is to collect all data inputs (till level 1 if compact), and +// outputs till level 1. +void Node::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (this->is_CFG()) { + collect_nodes_i(in_rel, this, 1, 1, false, false, false); + collect_nodes_i(out_rel, this, -1, 1, false, false, false); + } else { + if (compact) { + this->collect_nodes(in_rel, 1, false, true); + } else { + this->collect_nodes_in_all_data(in_rel, false); + } + this->collect_nodes(out_rel, -1, false, false); + } +} + +//---------------------------collect_nodes------------------------------------- +// An entry point to the low-level node collection facility, to start from a +// given node in the graph. The start node is by default not included in the +// result. +// Arguments: +// ns: collect the nodes into this data structure. +// d: the depth (distance from start node) to which nodes should be +// collected. A value >0 indicates input nodes, a value <0, output +// nodes. +// ctrl: include only control nodes. +// data: include only data nodes. +void Node::collect_nodes(GrowableArray *ns, int d, bool ctrl, bool data) const { + if (ctrl && data) { + // ignore nonsensical combination + return; + } + collect_nodes_i(ns, this, d, (uint) ABS(d), false, ctrl, data); +} + +//--------------------------collect_nodes_in----------------------------------- +static void collect_nodes_in(Node* start, GrowableArray *ns, bool primary_is_data, bool collect_secondary) { + // The maximum depth is determined using a BFS that visits all primary (data + // or control) inputs and increments the depth at each level. + uint d_in = 0; + GrowableArray nodes(Compile::current()->unique()); + nodes.push(start); + int nodes_at_current_level = 1; + int n_idx = 0; + while (nodes_at_current_level > 0) { + // Add all primary inputs reachable from the current level to the list, and + // increase the depth if there were any. + int nodes_at_next_level = 0; + bool nodes_added = false; + while (nodes_at_current_level > 0) { + nodes_at_current_level--; + Node* current = nodes.at(n_idx++); + for (uint i = 0; i < current->len(); i++) { + Node* n = current->in(i); + if (NotANode(n)) { + continue; + } + if ((primary_is_data && n->is_CFG()) || (!primary_is_data && !n->is_CFG())) { + continue; + } + if (!nodes.contains(n)) { + nodes.push(n); + nodes_added = true; + nodes_at_next_level++; + } + } + } + if (nodes_added) { + d_in++; + } + nodes_at_current_level = nodes_at_next_level; + } + start->collect_nodes(ns, d_in, !primary_is_data, primary_is_data); + if (collect_secondary) { + // Now, iterate over the secondary nodes in ns and add the respective + // boundary reachable from them. + GrowableArray sns(Compile::current()->unique()); + for (GrowableArrayIterator it = ns->begin(); it != ns->end(); ++it) { + Node* n = *it; + n->collect_nodes(&sns, 1, primary_is_data, !primary_is_data); + for (GrowableArrayIterator d = sns.begin(); d != sns.end(); ++d) { + ns->append_if_missing(*d); + } + sns.clear(); + } + } +} + +//---------------------collect_nodes_in_all_data------------------------------- +// Collect the entire data input graph. Include the control boundary if +// requested. +// Arguments: +// ns: collect the nodes into this data structure. +// ctrl: if true, include the control boundary. +void Node::collect_nodes_in_all_data(GrowableArray *ns, bool ctrl) const { + collect_nodes_in((Node*) this, ns, true, ctrl); +} + +//--------------------------collect_nodes_in_all_ctrl-------------------------- +// Collect the entire control input graph. Include the data boundary if +// requested. +// ns: collect the nodes into this data structure. +// data: if true, include the control boundary. +void Node::collect_nodes_in_all_ctrl(GrowableArray *ns, bool data) const { + collect_nodes_in((Node*) this, ns, false, data); +} + +//------------------collect_nodes_out_all_ctrl_boundary------------------------ +// Collect the entire output graph until hitting control node boundaries, and +// include those. +void Node::collect_nodes_out_all_ctrl_boundary(GrowableArray *ns) const { + // Perform a BFS and stop at control nodes. + GrowableArray nodes(Compile::current()->unique()); + nodes.push((Node*) this); + while (nodes.length() > 0) { + Node* current = nodes.pop(); + if (NotANode(current)) { + continue; + } + ns->append_if_missing(current); + if (!current->is_CFG()) { + for (DUIterator i = current->outs(); current->has_out(i); i++) { + nodes.push(current->out(i)); + } + } + } + ns->remove((Node*) this); +} + // VERIFICATION CODE // For each input edge to a node (ie - for each Use-Def edge), verify that // there is a corresponding Def-Use edge. @@ -2173,6 +2396,11 @@ st->print(" #"); _type->dump_on(st); } } + +void TypeNode::dump_compact_spec(outputStream *st) const { + st->print("#"); + _type->dump_on(st); +} #endif uint TypeNode::hash() const { return Node::hash() + _type->hash(); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/node.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -1038,13 +1038,35 @@ Node* find(int idx) const; // Search the graph for the given idx. Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. void dump() const { dump("\n"); } // Print this node. - void dump(const char* suffix, outputStream *st = tty) const;// Print this node. + void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node. void dump(int depth) const; // Print this node, recursively to depth d void dump_ctrl(int depth) const; // Print control nodes, to depth d - virtual void dump_req(outputStream *st = tty) const; // Print required-edge info - virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info - virtual void dump_out(outputStream *st = tty) const; // Print the output edge info - virtual void dump_spec(outputStream *st) const {}; // Print per-node info + void dump_comp() const; // Print this node in compact representation. + // Print this node in compact representation. + void dump_comp(const char* suffix, outputStream *st = tty) const; + virtual void dump_req(outputStream *st = tty) const; // Print required-edge info + virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info + virtual void dump_out(outputStream *st = tty) const; // Print the output edge info + virtual void dump_spec(outputStream *st) const {}; // Print per-node info + // Print compact per-node info + virtual void dump_compact_spec(outputStream *st) const { dump_spec(st); } + void dump_related() const; // Print related nodes (depends on node at hand). + // Print related nodes up to given depths for input and output nodes. + void dump_related(uint d_in, uint d_out) const; + void dump_related_compact() const; // Print related nodes in compact representation. + // Collect related nodes. + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; + // Collect nodes starting from this node, explicitly including/excluding control and data links. + void collect_nodes(GrowableArray *ns, int d, bool ctrl, bool data) const; + + // Node collectors, to be used in implementations of Node::rel(). + // Collect the entire data input graph. Include control inputs if requested. + void collect_nodes_in_all_data(GrowableArray *ns, bool ctrl) const; + // Collect the entire control input graph. Include data inputs if requested. + void collect_nodes_in_all_ctrl(GrowableArray *ns, bool data) const; + // Collect the entire output graph until hitting and including control nodes. + void collect_nodes_out_all_ctrl_boundary(GrowableArray *ns) const; + void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges void verify() const; // Check Def-Use info for my subgraph static void verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space); @@ -1091,6 +1113,20 @@ #endif }; + +#ifndef PRODUCT + +// Used in debugging code to avoid walking across dead or uninitialized edges. +inline bool NotANode(const Node* n) { + if (n == NULL) return true; + if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. + if (*(address*)n == badAddress) return true; // kill by Node::destruct + return false; +} + +#endif + + //----------------------------------------------------------------------------- // Iterators over DU info, and associated Node functions. @@ -1618,6 +1654,7 @@ virtual uint ideal_reg() const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void dump_compact_spec(outputStream *st) const; #endif }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/output.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1504,6 +1504,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(); @@ -1632,11 +1639,14 @@ if (_method) { // Emit the exception handler code. _code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb)); + if (failing()) { + return; // CodeBuffer::expand failed + } // Emit the deopt handler code. _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb)); // Emit the MethodHandle deopt handler code (if required). - if (has_method_handle_invokes()) { + if (has_method_handle_invokes() && !failing()) { // We can use the same code as for the normal deopt handler, we // just need a different entry point address. _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb)); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/rootnode.cpp --- a/hotspot/src/share/vm/opto/rootnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/rootnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -88,3 +88,18 @@ const RegMask &HaltNode::out_RegMask() const { return RegMask::Empty; } + +#ifndef PRODUCT +//-----------------------------related----------------------------------------- +// Include all control inputs in the related set, and also the input data +// boundary. In compact mode, include all inputs till level 2. Also include +// all outputs at level 1. +void HaltNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 2, false, false); + } else { + this->collect_nodes_in_all_ctrl(in_rel, true); + } + this->collect_nodes(out_rel, -1, false, false); +} +#endif diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/rootnode.hpp --- a/hotspot/src/share/vm/opto/rootnode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/rootnode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -64,6 +64,10 @@ virtual const RegMask &out_RegMask() const; virtual uint ideal_reg() const { return NotAMachineReg; } virtual uint match_edge(uint idx) const { return 0; } + +#ifndef PRODUCT + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; #endif // SHARE_VM_OPTO_ROOTNODE_HPP diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/subnode.cpp --- a/hotspot/src/share/vm/opto/subnode.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/subnode.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -498,6 +498,37 @@ return this; } +#ifndef PRODUCT +//----------------------------related------------------------------------------ +// Related nodes of comparison nodes include all data inputs (until hitting a +// control boundary) as well as all outputs until and including control nodes +// as well as their projections. In compact mode, data inputs till depth 1 and +// all outputs till depth 1 are considered. +void CmpNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 1, false, true); + this->collect_nodes(out_rel, -1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + this->collect_nodes_out_all_ctrl_boundary(out_rel); + // Now, find all control nodes in out_rel, and include their projections + // and projection targets (if any) in the result. + GrowableArray proj(Compile::current()->unique()); + for (GrowableArrayIterator it = out_rel->begin(); it != out_rel->end(); ++it) { + Node* n = *it; + if (n->is_CFG() && !n->is_Proj()) { + // Assume projections and projection targets are found at levels 1 and 2. + n->collect_nodes(&proj, -2, false, false); + for (GrowableArrayIterator p = proj.begin(); p != proj.end(); ++p) { + out_rel->append_if_missing(*p); + } + proj.clear(); + } + } + } +} +#endif + //============================================================================= //------------------------------cmp-------------------------------------------- // Simplify a CmpI (compare 2 integers) node, based on local information. @@ -1396,17 +1427,31 @@ return _test.cc2logical( phase->type( in(1) ) ); } +#ifndef PRODUCT //------------------------------dump_spec-------------------------------------- // Dump special per-node info -#ifndef PRODUCT void BoolNode::dump_spec(outputStream *st) const { st->print("["); _test.dump_on(st); st->print("]"); } + +//-------------------------------related--------------------------------------- +// A BoolNode's related nodes are all of its data inputs, and all of its +// outputs until control nodes are hit, which are included. In compact +// representation, inputs till level 3 and immediate outputs are included. +void BoolNode::related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const { + if (compact) { + this->collect_nodes(in_rel, 3, false, true); + this->collect_nodes(out_rel, -1, false, false); + } else { + this->collect_nodes_in_all_data(in_rel, false); + this->collect_nodes_out_all_ctrl_boundary(out_rel); + } +} #endif -//------------------------------is_counted_loop_exit_test-------------------------------------- +//----------------------is_counted_loop_exit_test------------------------------ // Returns true if node is used by a counted loop node. bool BoolNode::is_counted_loop_exit_test() { for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/opto/subnode.hpp --- a/hotspot/src/share/vm/opto/subnode.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/opto/subnode.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -60,7 +60,6 @@ // Supplied function to return the additive identity type. // This is returned whenever the subtracts inputs are the same. virtual const Type *add_id() const = 0; - }; @@ -140,6 +139,13 @@ const Type *add_id() const { return TypeInt::ZERO; } const Type *bottom_type() const { return TypeInt::CC; } virtual uint ideal_reg() const { return Op_RegFlags; } + +#ifndef PRODUCT + // CmpNode and subclasses include all data inputs (until hitting a control + // boundary) in their related node set, as well as all outputs until and + // including eventual control nodes and their projections. + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; +#endif }; //------------------------------CmpINode--------------------------------------- @@ -311,6 +317,7 @@ bool is_counted_loop_exit_test(); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; + virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -70,7 +70,10 @@ #endif // The default CICompilerCount's value is CI_COMPILER_COUNT. - assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number"); + // With a client VM, -XX:+TieredCompilation causes TieredCompilation + // to be true here (the option is validated later) and + // min_number_of_compiler_threads to exceed CI_COMPILER_COUNT. + min_number_of_compiler_threads = MIN2(min_number_of_compiler_threads, CI_COMPILER_COUNT); if (*value < (intx)min_number_of_compiler_threads) { if (verbose == true) { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -848,6 +848,9 @@ product(bool, UseCRC32CIntrinsics, false, \ "use intrinsics for java.util.zip.CRC32C") \ \ + diagnostic(ccstrlist, DisableIntrinsic, "", \ + "do not expand intrinsics whose (internal) names appear here") \ + \ develop(bool, TraceCallFixup, false, \ "Trace all call fixups") \ \ @@ -3913,7 +3916,7 @@ product(bool, PerfDisableSharedMem, false, \ "Store performance data in standard memory") \ \ - product(intx, PerfDataMemorySize, 32*K, \ + product(intx, PerfDataMemorySize, 64*K, \ "Size of performance data memory region. Will be rounded " \ "up to a multiple of the native os page size.") \ \ diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/services/diagnosticCommand.cpp --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Aug 13 14:15:23 2015 -0700 @@ -37,6 +37,7 @@ #include "services/management.hpp" #include "services/writeableFlags.hpp" #include "utilities/macros.hpp" +#include "oops/objArrayOop.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -57,6 +58,8 @@ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); @@ -333,6 +336,60 @@ vmSymbols::void_method_signature(), CHECK); } +void HeapInfoDCmd::execute(DCmdSource source, TRAPS) { + Universe::heap()->print_on(output()); +} + +void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) { + ResourceMark rm; + + + Klass* k = SystemDictionary::resolve_or_null( + vmSymbols::finalizer_histogram_klass(), THREAD); + assert(k != NULL, "FinalizerHistogram class is not accessible"); + + instanceKlassHandle klass(THREAD, k); + JavaValue result(T_ARRAY); + + // We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method + // and expect it to return array of FinalizerHistogramEntry as Object[] + + JavaCalls::call_static(&result, klass, + vmSymbols::get_finalizer_histogram_name(), + vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK); + + objArrayOop result_oop = (objArrayOop) result.get_jobject(); + if (result_oop->length() == 0) { + output()->print_cr("No instances waiting for finalization found"); + return; + } + + oop foop = result_oop->obj_at(0); + InstanceKlass* ik = InstanceKlass::cast(foop->klass()); + + fieldDescriptor count_fd, name_fd; + + Klass* count_res = ik->find_field( + vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd); + + Klass* name_res = ik->find_field( + vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd); + + assert(count_res != NULL && name_res != NULL, "Unexpected layout of FinalizerHistogramEntry"); + + output()->print_cr("Unreachable instances waiting for finalization"); + output()->print_cr("#instances class name"); + output()->print_cr("-----------------------"); + + for (int i = 0; i < result_oop->length(); ++i) { + oop element_oop = result_oop->obj_at(i); + oop str_oop = element_oop->obj_field(name_fd.offset()); + char *name = java_lang_String::as_utf8_string(str_oop); + int count = element_oop->int_field(count_fd.offset()); + output()->print_cr("%10d %s", count, name); + } +} + #if INCLUDE_SERVICES // Heap dumping/inspection supported HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/src/share/vm/services/diagnosticCommand.hpp --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Aug 13 14:15:23 2015 -0700 @@ -241,6 +241,46 @@ virtual void execute(DCmdSource source, TRAPS); }; +class HeapInfoDCmd : public DCmd { +public: + HeapInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } + static const char* name() { return "GC.heap_info"; } + static const char* description() { + return "Provide generic Java heap information."; + } + static const char* impact() { + return "Medium"; + } + static int num_arguments() { return 0; } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + + virtual void execute(DCmdSource source, TRAPS); +}; + +class FinalizerInfoDCmd : public DCmd { +public: + FinalizerInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { } + static const char* name() { return "GC.finalizer_info"; } + static const char* description() { + return "Provide information about Java finalization queue."; + } + static const char* impact() { + return "Medium"; + } + static int num_arguments() { return 0; } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + + virtual void execute(DCmdSource source, TRAPS); +}; + #if INCLUDE_SERVICES // Heap dumping supported // See also: dump_heap in attachListener.cpp class HeapDumpDCmd : public DCmdWithParser { diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/compiler/arguments/CheckCICompilerCount.java --- a/hotspot/test/compiler/arguments/CheckCICompilerCount.java Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java Thu Aug 13 14:15:23 2015 -0700 @@ -26,6 +26,7 @@ /* * @test CheckCheckCICompilerCount * @bug 8130858 + * @bug 8132525 * @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not * @library /testlibrary * @modules java.base/sun.misc @@ -36,12 +37,28 @@ public class CheckCICompilerCount { private static final String[][] NON_TIERED_ARGUMENTS = { { + "-server", "-XX:-TieredCompilation", "-XX:+PrintFlagsFinal", "-XX:CICompilerCount=0", "-version" }, { + "-server", + "-XX:-TieredCompilation", + "-XX:+PrintFlagsFinal", + "-XX:CICompilerCount=1", + "-version" + }, + { + "-client", + "-XX:-TieredCompilation", + "-XX:+PrintFlagsFinal", + "-XX:CICompilerCount=0", + "-version" + }, + { + "-client", "-XX:-TieredCompilation", "-XX:+PrintFlagsFinal", "-XX:CICompilerCount=1", @@ -56,22 +73,47 @@ }, { "intx CICompilerCount := 1 {product}" + }, + { + "CICompilerCount=0 must be at least 1", + "Improperly specified VM option 'CICompilerCount=0'" + }, + { + "intx CICompilerCount := 1 {product}" } }; private static final int[] NON_TIERED_EXIT = { 1, + 0, + 1, 0 }; private static final String[][] TIERED_ARGUMENTS = { { + "-server", "-XX:+TieredCompilation", "-XX:+PrintFlagsFinal", "-XX:CICompilerCount=1", "-version" }, { + "-server", + "-XX:+TieredCompilation", + "-XX:+PrintFlagsFinal", + "-XX:CICompilerCount=2", + "-version" + }, + { + "-client", + "-XX:+TieredCompilation", + "-XX:+PrintFlagsFinal", + "-XX:CICompilerCount=1", + "-version" + }, + { + "-client", "-XX:+TieredCompilation", "-XX:+PrintFlagsFinal", "-XX:CICompilerCount=2", @@ -86,11 +128,20 @@ }, { "intx CICompilerCount := 2 {product}" + }, + { + "CICompilerCount=1 must be at least 2", + "Improperly specified VM option 'CICompilerCount=1'" + }, + { + "intx CICompilerCount := 2 {product}" } }; private static final int[] TIERED_EXIT = { 1, + 0, + 1, 0 }; diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/runtime/CommandLine/PrintTouchedMethods.java --- a/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java Thu Aug 13 14:15:23 2015 -0700 @@ -87,6 +87,24 @@ output.shouldNotContain("TestLogTouchedMethods.methodB:()V"); output.shouldHaveExitValue(0); + String[] javaArgs4 = {"-XX:+UnlockDiagnosticVMOptions", "-Xint", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "-XX:-TieredCompilation", "TestLogTouchedMethods"}; + pb = ProcessTools.createJavaProcessBuilder(javaArgs4); + output = new OutputAnalyzer(pb.start()); + lines = output.asLines(); + + if (lines.size() < 1) { + throw new Exception("Empty output"); + } + + first = lines.get(0); + if (!first.equals("# Method::print_touched_methods version 1")) { + throw new Exception("First line mismatch"); + } + + output.shouldContain("TestLogTouchedMethods.methodA:()V"); + output.shouldNotContain("TestLogTouchedMethods.methodB:()V"); + output.shouldHaveExitValue(0); + // Test jcmd PrintTouchedMethods VM.print_touched_methods String pid = Integer.toString(ProcessTools.getProcessId()); pb = new ProcessBuilder(); diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/serviceability/dcmd/gc/FinalizerInfoTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/gc/FinalizerInfoTest.java Thu Aug 13 14:15:23 2015 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, 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 org.testng.annotations.Test; +import org.testng.Assert; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.PidJcmdExecutor; + +/* + * @test + * @summary + * @library /testlibrary + * @build jdk.test.lib.* + * @build jdk.test.lib.dcmd.* + * @run testng FinalizerInfoTest + */ +public class FinalizerInfoTest { + static ReentrantLock lock = new ReentrantLock(); + static volatile int wasInitialized = 0; + static volatile int wasTrapped = 0; + static final String cmd = "GC.finalizer_info"; + static final int objectsCount = 1000; + + class MyObject { + public MyObject() { + // Make sure object allocation/deallocation is not optimized out + wasInitialized += 1; + } + + protected void finalize() { + // Trap the object in a finalization queue + wasTrapped += 1; + lock.lock(); + } + } + + public void run(CommandExecutor executor) { + try { + lock.lock(); + for(int i = 0; i < objectsCount; ++i) { + new MyObject(); + } + System.out.println("Objects initialized: " + objectsCount); + System.gc(); + + while(wasTrapped < 1) { + // Waiting for gc thread. + } + + OutputAnalyzer output = executor.execute(cmd); + output.shouldContain("MyObject"); + } finally { + lock.unlock(); + } + } + + @Test + public void pid() { + run(new PidJcmdExecutor()); + } +} diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/serviceability/dcmd/gc/HeapInfoTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/gc/HeapInfoTest.java Thu Aug 13 14:15:23 2015 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, 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 org.testng.annotations.Test; +import org.testng.Assert; + +import java.io.IOException; + +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.PidJcmdExecutor; +import jdk.test.lib.OutputAnalyzer; + + +/* + * @test + * @summary Test of diagnostic command GC.heap_info + * @library /testlibrary + * @build jdk.test.lib.* + * @build jdk.test.lib.dcmd.* + * @run testng HeapInfoTest + */ +public class HeapInfoTest { + public void run(CommandExecutor executor) { + String cmd = "GC.heap_info"; + OutputAnalyzer output = executor.execute(cmd); + output.shouldContain("Metaspace"); + } + + @Test + public void pid() { + run(new PidJcmdExecutor()); + } +} + diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java --- a/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java Thu Aug 13 14:15:23 2015 -0700 @@ -21,15 +21,13 @@ * questions. */ -import org.testng.annotations.Test; -import org.testng.Assert; - +import java.util.concurrent.Phaser; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.TimeoutException; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; +import jdk.test.lib.Utils; /* * @test @@ -41,62 +39,71 @@ * jdk.jvmstat/sun.jvmstat.monitor * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* - * @run testng RunFinalizationTest + * @run main/othervm RunFinalizationTest */ public class RunFinalizationTest { - static ReentrantLock lock = new ReentrantLock(); - static Condition cond = lock.newCondition(); + private static final long TIMEOUT = Utils.adjustTimeout(15000); // 15s + private static final Phaser ph = new Phaser(3); static volatile boolean wasFinalized = false; static volatile boolean wasInitialized = false; - class MyObject { + static class MyObject { public MyObject() { /* Make sure object allocation/deallocation is not optimized out */ wasInitialized = true; } protected void finalize() { - lock.lock(); - wasFinalized = true; - cond.signalAll(); - lock.unlock(); + if (!Thread.currentThread().getName().equals("Finalizer")) { + wasFinalized = true; + ph.arrive(); + } else { + ph.arriveAndAwaitAdvance(); + } } } public static MyObject o; - public void run(CommandExecutor executor) { - lock.lock(); + private static void run(CommandExecutor executor) { o = new MyObject(); o = null; System.gc(); executor.execute("GC.run_finalization"); - int waited = 0; - int waitTime = 15; - - try { - System.out.println("Waiting for signal from finalizer"); + System.out.println("Waiting for signal from finalizer"); - while (!cond.await(waitTime, TimeUnit.SECONDS)) { - waited += waitTime; - System.out.println(String.format("Waited %d seconds", waited)); + long targetTime = System.currentTimeMillis() + TIMEOUT; + while (System.currentTimeMillis() < targetTime) { + try { + ph.awaitAdvanceInterruptibly(ph.arrive(), 200, TimeUnit.MILLISECONDS); + System.out.println("Received signal"); + break; + } catch (InterruptedException e) { + fail("Test error: Interrupted while waiting for signal from finalizer", e); + } catch (TimeoutException e) { + System.out.println("Haven't received signal in 200ms. Retrying ..."); } - - System.out.println("Received signal"); - } catch (InterruptedException e) { - Assert.fail("Test error: Interrupted while waiting for signal from finalizer", e); - } finally { - lock.unlock(); } if (!wasFinalized) { - Assert.fail("Test failure: Object was not finalized"); + fail("Test failure: Object was not finalized"); } } - @Test - public void jmx() { - run(new JMXExecutor()); + public static void main(String ... args) { + MyObject o = new MyObject(); + o = null; + Runtime.getRuntime().addShutdownHook(new Thread(()->{ + run(new JMXExecutor()); + })); + } + + private static void fail(String msg, Exception e) { + throw new Error(msg, e); + } + + private static void fail(String msg) { + throw new Error(msg); } } diff -r bb7b9089c6b1 -r 7bf24ea31a4d hotspot/test/testlibrary/jdk/test/lib/Utils.java --- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Aug 13 12:20:05 2015 -0700 +++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Thu Aug 13 14:15:23 2015 -0700 @@ -314,9 +314,8 @@ */ public static String fileAsString(String filename) throws IOException { Path filePath = Paths.get(filename); - return Files.exists(filePath) - ? Files.lines(filePath).collect(Collectors.joining(NEW_LINE)) - : null; + if (!Files.exists(filePath)) return null; + return new String(Files.readAllBytes(filePath)); } /**