Merge
This commit is contained in:
commit
73d4205d35
@ -319,3 +319,4 @@ c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
|
||||
57f3134853ecdd4a3ee2d4d26f22ba981d653d79 jdk9-b74
|
||||
8fd6eeb878606e39c908f12535f34ebbfd225a4a jdk9-b75
|
||||
d82072b699b880a1f647a5e2d7c0f86cec958941 jdk9-b76
|
||||
7972dc8f2a47f0c4cd8f02fa5662af41f028aa14 jdk9-b77
|
||||
|
@ -479,3 +479,4 @@ e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73
|
||||
fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74
|
||||
2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
|
||||
0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
|
||||
e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77
|
||||
|
@ -2389,9 +2389,11 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf)
|
||||
// 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 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf)
|
||||
// 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 @@ encode %{
|
||||
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 @@ encode %{
|
||||
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;
|
||||
|
@ -327,9 +327,16 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
|
||||
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
|
||||
|
@ -1996,13 +1996,21 @@ void LIR_Assembler::align_call(LIR_Code code) { }
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -51,7 +51,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
// 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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
|
||||
assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big");
|
||||
__ end_a_stub();
|
||||
return base;
|
||||
}
|
||||
#undef __
|
||||
|
||||
|
@ -664,7 +664,7 @@ void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, in
|
||||
// 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 @@ void MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
|
||||
|
||||
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 @@ void MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
|
||||
} else {
|
||||
bl(pc());
|
||||
}
|
||||
// just need to return a non-null address
|
||||
return pc();
|
||||
}
|
||||
|
||||
|
||||
@ -696,13 +701,11 @@ void MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
|
||||
// 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 @@ void MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
||||
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
|
||||
|
@ -539,7 +539,7 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
|
||||
// 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 @@ public:
|
||||
}
|
||||
|
||||
// Emit the CompiledIC call idiom
|
||||
void ic_call(address entry);
|
||||
address ic_call(address entry);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -94,7 +94,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
|
||||
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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
// 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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
|
||||
// End the stub.
|
||||
__ end_a_stub();
|
||||
return stub;
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
|
@ -2187,7 +2187,7 @@ void InterpreterMacroAssembler::get_method_counters(Register method,
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1082,7 +1082,7 @@ void CallStubImpl::emit_trampoline_stub(MacroAssembler &_masm, int destination_t
|
||||
// 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 @@ EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address en
|
||||
|
||||
// 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 @@ encode %{
|
||||
|
||||
// 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 @@ encode %{
|
||||
__ 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 @@ encode %{
|
||||
|
||||
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.
|
||||
|
@ -432,6 +432,9 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
|
||||
__ 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();
|
||||
|
@ -53,7 +53,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
|
||||
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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
|
||||
// Update current stubs pointer and restore code_end.
|
||||
__ end_a_stub();
|
||||
return base;
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
|
@ -2314,7 +2314,7 @@ void InterpreterMacroAssembler::get_method_counters(Register method,
|
||||
}
|
||||
|
||||
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() +
|
||||
|
@ -1773,9 +1773,11 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
|
||||
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 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
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 @@ encode %{
|
||||
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;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
|
@ -503,6 +503,9 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
|
||||
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);
|
||||
|
@ -50,7 +50,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
// 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 @@ void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
|
||||
// Update current stubs pointer and restore insts_end.
|
||||
__ end_a_stub();
|
||||
return base;
|
||||
}
|
||||
#undef __
|
||||
|
||||
|
@ -1594,7 +1594,10 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
|
||||
// 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 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
// 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
|
||||
|
@ -1907,7 +1907,11 @@ encode %{
|
||||
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;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
|
@ -2137,7 +2137,11 @@ encode %{
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
|
@ -60,8 +60,9 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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() {
|
||||
|
@ -971,34 +971,32 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
|
||||
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);
|
||||
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();
|
||||
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);
|
||||
|
@ -131,8 +131,6 @@ class Aix {
|
||||
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; }
|
||||
|
@ -739,40 +739,35 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
|
||||
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);
|
||||
// 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();
|
||||
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;
|
||||
|
||||
{
|
||||
|
@ -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 @@ class Bsd {
|
||||
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<int>* cpu_to_node() { return _cpu_to_node; }
|
||||
|
||||
|
@ -653,8 +653,7 @@ static void *java_start(Thread *thread) {
|
||||
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,39 +711,35 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
||||
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);
|
||||
// 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();
|
||||
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 @@ size_t os::lasterror(char *buf, size_t len) {
|
||||
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();
|
||||
}
|
||||
|
@ -83,8 +83,6 @@ class Linux {
|
||||
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<int>* cpu_to_node() { return _cpu_to_node; }
|
||||
|
||||
|
@ -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 @@ void os::Aix::init_thread_fpu_state(void) {
|
||||
|
||||
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)
|
||||
|
@ -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 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
#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 @@ size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
|
||||
#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
|
||||
|
@ -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 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
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);
|
||||
|
@ -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 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
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)
|
||||
|
@ -467,8 +467,6 @@ void os::Linux::set_fpu_control_word(int fpu_control) {
|
||||
|
||||
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)
|
||||
|
@ -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 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
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)
|
||||
|
@ -623,11 +623,6 @@ size_t os::Linux::min_stack_allowed = 64 * K;
|
||||
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)
|
||||
|
@ -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 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
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);
|
||||
|
@ -239,25 +239,6 @@ bool Compiler::is_intrinsic_supported(methodHandle method) {
|
||||
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::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
||||
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);
|
||||
}
|
||||
|
@ -55,18 +55,9 @@ class Compiler: public AbstractCompiler {
|
||||
// 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();
|
||||
};
|
||||
|
@ -3491,8 +3491,16 @@ void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) {
|
||||
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.
|
||||
|
@ -443,6 +443,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) {
|
||||
|
||||
// emit the static call stub stuff out of line
|
||||
emit_static_call_stub();
|
||||
CHECK_BAILOUT();
|
||||
|
||||
switch (op->code()) {
|
||||
case lir_static_call:
|
||||
|
@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "precompiled.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "classfile/imageDecompressor.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "utilities/bytes.hpp"
|
||||
|
@ -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"
|
||||
|
@ -417,8 +417,59 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
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 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
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 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
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 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
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;
|
||||
|
@ -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 @@ public:
|
||||
// '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
|
||||
|
@ -306,7 +306,7 @@ class CompiledStaticCall: public NativeCall {
|
||||
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();
|
||||
|
||||
|
@ -75,8 +75,8 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
//
|
||||
// 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 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
// 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 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
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; }
|
||||
|
@ -79,10 +79,15 @@ void ArrayCopyNode::connect_outputs(GraphKit* kit) {
|
||||
|
||||
#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 {
|
||||
|
@ -164,6 +164,7 @@ public:
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void dump_compact_spec(outputStream* st) const;
|
||||
#endif
|
||||
};
|
||||
#endif // SHARE_VM_OPTO_ARRAYCOPYNODE_HPP
|
||||
|
@ -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") \
|
||||
\
|
||||
|
@ -157,14 +157,6 @@ void C2Compiler::print_timers() {
|
||||
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 @@ bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
|
||||
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;
|
||||
|
@ -51,11 +51,11 @@ public:
|
||||
// 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 @@ public:
|
||||
// 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();
|
||||
};
|
||||
|
@ -52,6 +52,7 @@ const Type *StartNode::bottom_type() const { return _domain; }
|
||||
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 @@ void ParmNode::dump_spec(outputStream *st) const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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 @@ void CallJavaNode::dump_spec(outputStream *st) const {
|
||||
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 @@ void CallStaticJavaNode::dump_spec(outputStream *st) const {
|
||||
}
|
||||
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 @@ void SafePointNode::dump_spec(outputStream *st) const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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 @@ void AbstractLockNode::set_eliminated_lock_counter() {
|
||||
_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<Node*> *in_rel, GrowableArray<Node*> *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
|
||||
|
||||
//=============================================================================
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
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 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -476,6 +479,7 @@ public:
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -675,6 +679,7 @@ public:
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void dump_compact_spec(outputStream *st) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -730,6 +735,7 @@ public:
|
||||
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 @@ private:
|
||||
} _kind;
|
||||
#ifndef PRODUCT
|
||||
NamedCounter* _counter;
|
||||
static const char* _kind_names[Nested+1];
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -1005,6 +1012,9 @@ public:
|
||||
#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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -2023,6 +2023,14 @@ const RegMask &PhiNode::out_RegMask() const {
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PhiNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *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 @@ const RegMask &GotoNode::out_RegMask() const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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<Node*> *in_rel, GrowableArray<Node*> *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 @@ uint JumpProjNode::cmp( const Node &n ) const {
|
||||
#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<Node*> *in_rel, GrowableArray<Node*> *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
|
||||
|
||||
|
@ -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 @@ public:
|
||||
virtual const RegMask &out_RegMask() const;
|
||||
virtual const RegMask &in_RegMask(uint) const;
|
||||
#ifndef PRODUCT
|
||||
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
#endif
|
||||
#ifdef ASSERT
|
||||
@ -229,6 +230,10 @@ public:
|
||||
virtual const Type *Value( PhaseTransform *phase ) const;
|
||||
virtual Node *Identity( PhaseTransform *phase );
|
||||
virtual const RegMask &out_RegMask() const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//------------------------------CProjNode--------------------------------------
|
||||
@ -382,6 +387,7 @@ public:
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void related(GrowableArray <Node *> *in_rel, GrowableArray <Node *> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -393,6 +399,11 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class IfTrueNode : public IfProjNode {
|
||||
@ -455,6 +466,9 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class JumpProjNode : public JProjNode {
|
||||
@ -479,6 +493,8 @@ class JumpProjNode : public JProjNode {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -594,6 +594,10 @@ uint Compile::scratch_emit_size(const Node* n) {
|
||||
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);
|
||||
|
||||
|
@ -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 @@ Node *IfProjNode::Identity(PhaseTransform *phase) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//------------------------------dump_spec--------------------------------------
|
||||
#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<Node*> *in_rel, GrowableArray<Node*> *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--------------------------------------
|
||||
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 <Node *> *in_rel, GrowableArray <Node *> *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----------------------------------
|
||||
|
@ -327,7 +327,7 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||
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) {
|
||||
|
@ -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 @@ const Type *MoveD2LNode::Value( PhaseTransform *phase ) const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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
|
||||
|
@ -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 @@ class BinaryNode : public Node {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 @@ const TypePtr *ProjNode::adr_type() const {
|
||||
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----------------------------------------
|
||||
|
@ -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 @@ public:
|
||||
|
||||
#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"
|
||||
|
@ -1489,16 +1489,6 @@ jfloat Node::getf() const {
|
||||
|
||||
#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 @@ void Node::set_debug_orig(Node* orig) {
|
||||
|
||||
//------------------------------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 @@ void Node::dump_out(outputStream *st) const {
|
||||
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 <Node *> 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<Node*> *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 <Node *> 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 @@ void Node::dump_ctrl(int d) const {
|
||||
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 <Node *> in_rel(C->unique());
|
||||
GrowableArray <Node *> 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 <Node *> in_rel(C->unique());
|
||||
GrowableArray <Node *> 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 <Node *> in_rel(C->unique());
|
||||
GrowableArray <Node *> 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<Node*> *in_rel, GrowableArray<Node*> *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<Node*> *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<Node*> *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<Node*> 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<Node*> sns(Compile::current()->unique());
|
||||
for (GrowableArrayIterator<Node*> it = ns->begin(); it != ns->end(); ++it) {
|
||||
Node* n = *it;
|
||||
n->collect_nodes(&sns, 1, primary_is_data, !primary_is_data);
|
||||
for (GrowableArrayIterator<Node*> 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<Node*> *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<Node*> *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<Node*> *ns) const {
|
||||
// Perform a BFS and stop at control nodes.
|
||||
GrowableArray<Node*> 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 @@ void TypeNode::dump_spec(outputStream *st) const {
|
||||
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();
|
||||
|
@ -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 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
// Collect nodes starting from this node, explicitly including/excluding control and data links.
|
||||
void collect_nodes(GrowableArray<Node*> *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<Node*> *ns, bool ctrl) const;
|
||||
// Collect the entire control input graph. Include data inputs if requested.
|
||||
void collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const;
|
||||
// Collect the entire output graph until hitting and including control nodes.
|
||||
void collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *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 @@ public:
|
||||
#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 @@ public:
|
||||
virtual uint ideal_reg() const;
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void dump_compact_spec(outputStream *st) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1504,6 +1504,13 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
|
||||
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 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
|
||||
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));
|
||||
|
@ -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 Type *HaltNode::Value( PhaseTransform *phase ) const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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
|
||||
|
@ -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 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_OPTO_ROOTNODE_HPP
|
||||
|
@ -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 @@ Node *CmpNode::Identity( PhaseTransform *phase ) {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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<Node*> proj(Compile::current()->unique());
|
||||
for (GrowableArrayIterator<Node*> 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<Node*> 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 @@ const Type *BoolNode::Value( PhaseTransform *phase ) const {
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *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++ ) {
|
||||
|
@ -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 @@ public:
|
||||
// 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 @@ public:
|
||||
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<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
//------------------------------CmpINode---------------------------------------
|
||||
@ -311,6 +317,7 @@ public:
|
||||
bool is_counted_loop_exit_test();
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -70,7 +70,10 @@ Flag::Error CICompilerCountConstraintFunc(bool verbose, intx* value) {
|
||||
#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) {
|
||||
|
@ -848,6 +848,9 @@ public:
|
||||
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 @@ public:
|
||||
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.") \
|
||||
\
|
||||
|
@ -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 @@ void DCmdRegistrant::register_dcmds(){
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export, true, false));
|
||||
#if INCLUDE_SERVICES // Heap dumping/inspection supported
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
|
||||
@ -333,6 +336,60 @@ void RunFinalizationDCmd::execute(DCmdSource source, TRAPS) {
|
||||
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),
|
||||
|
@ -241,6 +241,46 @@ public:
|
||||
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 {
|
||||
|
@ -26,6 +26,7 @@ import jdk.test.lib.*;
|
||||
/*
|
||||
* @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 @@ import jdk.test.lib.*;
|
||||
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",
|
||||
@ -50,6 +67,13 @@ public class CheckCICompilerCount {
|
||||
};
|
||||
|
||||
private static final String[][] NON_TIERED_EXPECTED_OUTPUTS = {
|
||||
{
|
||||
"CICompilerCount=0 must be at least 1",
|
||||
"Improperly specified VM option 'CICompilerCount=0'"
|
||||
},
|
||||
{
|
||||
"intx CICompilerCount := 1 {product}"
|
||||
},
|
||||
{
|
||||
"CICompilerCount=0 must be at least 1",
|
||||
"Improperly specified VM option 'CICompilerCount=0'"
|
||||
@ -60,18 +84,36 @@ public class CheckCICompilerCount {
|
||||
};
|
||||
|
||||
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",
|
||||
@ -80,6 +122,13 @@ public class CheckCICompilerCount {
|
||||
};
|
||||
|
||||
private static final String[][] TIERED_EXPECTED_OUTPUTS = {
|
||||
{
|
||||
"CICompilerCount=1 must be at least 2",
|
||||
"Improperly specified VM option 'CICompilerCount=1'"
|
||||
},
|
||||
{
|
||||
"intx CICompilerCount := 2 {product}"
|
||||
},
|
||||
{
|
||||
"CICompilerCount=1 must be at least 2",
|
||||
"Improperly specified VM option 'CICompilerCount=1'"
|
||||
@ -90,6 +139,8 @@ public class CheckCICompilerCount {
|
||||
};
|
||||
|
||||
private static final int[] TIERED_EXIT = {
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0
|
||||
};
|
||||
|
@ -87,6 +87,24 @@ public class PrintTouchedMethods {
|
||||
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();
|
||||
|
87
hotspot/test/serviceability/dcmd/gc/FinalizerInfoTest.java
Normal file
87
hotspot/test/serviceability/dcmd/gc/FinalizerInfoTest.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
54
hotspot/test/serviceability/dcmd/gc/HeapInfoTest.java
Normal file
54
hotspot/test/serviceability/dcmd/gc/HeapInfoTest.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ import jdk.test.lib.dcmd.JMXExecutor;
|
||||
* 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;
|
||||
System.out.println("Waiting for signal from finalizer");
|
||||
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -314,9 +314,8 @@ public final class Utils {
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,3 +319,4 @@ f376824d4940f45719d91838f3f6249f873440db jdk9-b72
|
||||
6dd82d2e4a104f4d204b2890f33ef11ec3e3f8d0 jdk9-b74
|
||||
4dd09cb5f7c2a2a23a9958ea7a602dd74d5709b2 jdk9-b75
|
||||
4526c0da8fb362eebd7e88f4d44e86858cf9b80b jdk9-b76
|
||||
7fd081100f48828431e7c1bff65c906ee759069b jdk9-b77
|
||||
|
@ -26,5 +26,5 @@
|
||||
include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupLauncher,jjs, \
|
||||
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.nashorn.tools.Shell"$(COMMA) }'))
|
||||
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.nashorn.tools.jjs.Main"$(COMMA) }'))
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#
|
||||
|
||||
BUILD_LIBNIO_SRC := \
|
||||
$(JDK_TOPDIR)/src/java.base/share/native/libnio \
|
||||
$(JDK_TOPDIR)/src/java.base/share/native/libnio/ch \
|
||||
$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio \
|
||||
$(sort $(wildcard \
|
||||
|
@ -123,9 +123,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJSOUND, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
$(LIBJSOUND_CFLAGS), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBJSOUND_CFLAGS), \
|
||||
DISABLED_WARNINGS_clang := implicit-function-declaration \
|
||||
deprecated-writable-strings, \
|
||||
WARNINGS_AS_ERRORS_clang := false, \
|
||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjsound/mapfile-vers, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
@ -171,7 +168,6 @@ ifneq ($(filter jsoundalsa, $(EXTRA_SOUND_JNI_LIBS)), )
|
||||
-DUSE_PORTS=TRUE \
|
||||
-DUSE_PLATFORM_MIDI_OUT=TRUE \
|
||||
-DUSE_PLATFORM_MIDI_IN=TRUE, \
|
||||
DISABLED_WARNINGS_gcc := parentheses, \
|
||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjsoundalsa/mapfile-vers, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
JNI_OnLoad;
|
||||
Java_java_nio_MappedByteBuffer_force0;
|
||||
Java_java_nio_MappedByteBuffer_isLoaded0;
|
||||
Java_java_nio_MappedByteBuffer_load0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2001, 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
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
JNI_OnLoad;
|
||||
Java_java_nio_MappedByteBuffer_force0;
|
||||
Java_java_nio_MappedByteBuffer_isLoaded0;
|
||||
Java_java_nio_MappedByteBuffer_load0;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
JNI_OnLoad;
|
||||
Java_java_nio_MappedByteBuffer_force0;
|
||||
Java_java_nio_MappedByteBuffer_isLoaded0;
|
||||
Java_java_nio_MappedByteBuffer_load0;
|
||||
|
@ -31,22 +31,19 @@ import java.util.Hashtable;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* This class is for runtime permissions. A RuntimePermission
|
||||
* contains a name (also referred to as a "target name") but
|
||||
* no actions list; you either have the named permission
|
||||
* or you don't.
|
||||
*
|
||||
* <P>
|
||||
* This class is for runtime permissions. A {@code RuntimePermission}
|
||||
* contains a name (also referred to as a "target name") but no actions
|
||||
* list; you either have the named permission or you don't.
|
||||
* <p>
|
||||
* The target name is the name of the runtime permission (see below). The
|
||||
* naming convention follows the hierarchical property naming convention.
|
||||
* Also, an asterisk
|
||||
* may appear at the end of the name, following a ".", or by itself, to
|
||||
* signify a wildcard match. For example: "loadLibrary.*" and "*" signify a
|
||||
* wildcard match, while "*loadLibrary" and "a*b" do not.
|
||||
* <P>
|
||||
* The following table lists all the possible RuntimePermission target names,
|
||||
* and for each provides a description of what the permission allows
|
||||
* and a discussion of the risks of granting code the permission.
|
||||
* Also, an asterisk may appear at the end of the name, following a ".",
|
||||
* or by itself, to signify a wildcard match. For example: "loadLibrary.*"
|
||||
* and "*" signify a wildcard match, while "*loadLibrary" and "a*b" do not.
|
||||
* <p>
|
||||
* The following table lists the standard {@code RuntimePermission}
|
||||
* target names, and for each provides a description of what the permission
|
||||
* allows and a discussion of the risks of granting code the permission.
|
||||
*
|
||||
* <table border=1 cellpadding=5 summary="permission target name,
|
||||
* what the target allows,and associated risks">
|
||||
@ -353,6 +350,10 @@ import java.util.StringTokenizer;
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* @implNote
|
||||
* Implementations may define additional target names, but should use naming
|
||||
* conventions such as reverse domain name notation to avoid name clashes.
|
||||
*
|
||||
* @see java.security.BasicPermission
|
||||
* @see java.security.Permission
|
||||
* @see java.security.Permissions
|
||||
|
@ -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
|
||||
@ -83,6 +83,10 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
|
||||
add();
|
||||
}
|
||||
|
||||
static ReferenceQueue<Object> getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
/* Invoked by VM */
|
||||
static void register(Object finalizee) {
|
||||
new Finalizer(finalizee);
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* This FinalizerHistogram class is for GC.finalizer_info diagnostic command support.
|
||||
* It is invoked by the VM.
|
||||
*/
|
||||
|
||||
final class FinalizerHistogram {
|
||||
|
||||
private static final class Entry {
|
||||
private int instanceCount;
|
||||
private final String className;
|
||||
|
||||
int getInstanceCount() {
|
||||
return instanceCount;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
instanceCount += 1;
|
||||
}
|
||||
|
||||
Entry(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
}
|
||||
|
||||
// Method below is called by VM and VM expect certain
|
||||
// entry class layout.
|
||||
|
||||
static Entry[] getFinalizerHistogram() {
|
||||
Map<String, Entry> countMap = new HashMap<>();
|
||||
ReferenceQueue<Object> queue = Finalizer.getQueue();
|
||||
queue.forEach(r -> {
|
||||
Object referent = r.get();
|
||||
if (referent != null) {
|
||||
countMap.computeIfAbsent(
|
||||
referent.getClass().getName(), Entry::new).increment();
|
||||
/* Clear stack slot containing this variable, to decrease
|
||||
the chances of false retention with a conservative GC */
|
||||
referent = null;
|
||||
}
|
||||
});
|
||||
|
||||
Entry fhe[] = countMap.values().toArray(new Entry[countMap.size()]);
|
||||
Arrays.sort(fhe,
|
||||
Comparator.comparingInt(Entry::getInstanceCount).reversed());
|
||||
return fhe;
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -101,7 +101,7 @@ public abstract class Reference<T> {
|
||||
* Inactive: this
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Reference next;
|
||||
volatile Reference next;
|
||||
|
||||
/* When active: next element in a discovered reference list maintained by GC (or this if last)
|
||||
* pending: next element in the pending list (or null if last)
|
||||
|
@ -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
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Reference queues, to which registered reference objects are appended by the
|
||||
* garbage collector after the appropriate reachability changes are detected.
|
||||
@ -75,13 +77,12 @@ public class ReferenceQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Reference<? extends T> reallyPoll() { /* Must hold lock */
|
||||
Reference<? extends T> r = head;
|
||||
if (r != null) {
|
||||
head = (r.next == r) ?
|
||||
null :
|
||||
r.next; // Unchecked due to the next field having a raw type in Reference
|
||||
@SuppressWarnings("unchecked")
|
||||
Reference<? extends T> rn = r.next;
|
||||
head = (rn == r) ? null : rn;
|
||||
r.queue = NULL;
|
||||
r.next = r;
|
||||
queueLength--;
|
||||
@ -164,4 +165,32 @@ public class ReferenceQueue<T> {
|
||||
return remove(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate queue and invoke given action with each Reference.
|
||||
* Suitable for diagnostic purposes.
|
||||
* WARNING: any use of this method should make sure to not
|
||||
* retain the referents of iterated references (in case of
|
||||
* FinalReference(s)) so that their life is not prolonged more
|
||||
* than necessary.
|
||||
*/
|
||||
void forEach(Consumer<? super Reference<? extends T>> action) {
|
||||
for (Reference<? extends T> r = head; r != null;) {
|
||||
action.accept(r);
|
||||
@SuppressWarnings("unchecked")
|
||||
Reference<? extends T> rn = r.next;
|
||||
if (rn == r) {
|
||||
if (r.queue == ENQUEUED) {
|
||||
// still enqueued -> we reached end of chain
|
||||
r = null;
|
||||
} else {
|
||||
// already dequeued: r.queue == NULL; ->
|
||||
// restart from head when overtaken by queue poller(s)
|
||||
r = head;
|
||||
}
|
||||
} else {
|
||||
// next in chain
|
||||
r = rn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +96,10 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
* capacity values:
|
||||
*
|
||||
* <blockquote>
|
||||
* <tt>0</tt> <tt><=</tt>
|
||||
* <i>mark</i> <tt><=</tt>
|
||||
* <i>position</i> <tt><=</tt>
|
||||
* <i>limit</i> <tt><=</tt>
|
||||
* {@code 0} {@code <=}
|
||||
* <i>mark</i> {@code <=}
|
||||
* <i>position</i> {@code <=}
|
||||
* <i>limit</i> {@code <=}
|
||||
* <i>capacity</i>
|
||||
* </blockquote>
|
||||
*
|
||||
@ -229,7 +229,7 @@ public abstract class Buffer {
|
||||
* The new buffer's capacity, in $type$s
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the <tt>capacity</tt> is a negative integer
|
||||
* If the {@code capacity} is a negative integer
|
||||
*/
|
||||
static IllegalArgumentException createCapacityException(int capacity) {
|
||||
assert capacity < 0 : "capacity expected to be negative";
|
||||
@ -266,7 +266,7 @@ public abstract class Buffer {
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the preconditions on <tt>newPosition</tt> do not hold
|
||||
* If the preconditions on {@code newPosition} do not hold
|
||||
*/
|
||||
public Buffer position(int newPosition) {
|
||||
if (newPosition > limit | newPosition < 0)
|
||||
@ -319,7 +319,7 @@ public abstract class Buffer {
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the preconditions on <tt>newLimit</tt> do not hold
|
||||
* If the preconditions on {@code newLimit} do not hold
|
||||
*/
|
||||
public Buffer limit(int newLimit) {
|
||||
if (newLimit > capacity | newLimit < 0)
|
||||
@ -468,7 +468,7 @@ public abstract class Buffer {
|
||||
* Tells whether there are any elements between the current position and
|
||||
* the limit.
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, there is at least one element
|
||||
* @return {@code true} if, and only if, there is at least one element
|
||||
* remaining in this buffer
|
||||
*/
|
||||
public final boolean hasRemaining() {
|
||||
@ -478,7 +478,7 @@ public abstract class Buffer {
|
||||
/**
|
||||
* Tells whether or not this buffer is read-only.
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer is read-only
|
||||
* @return {@code true} if, and only if, this buffer is read-only
|
||||
*/
|
||||
public abstract boolean isReadOnly();
|
||||
|
||||
@ -486,11 +486,11 @@ public abstract class Buffer {
|
||||
* Tells whether or not this buffer is backed by an accessible
|
||||
* array.
|
||||
*
|
||||
* <p> If this method returns <tt>true</tt> then the {@link #array() array}
|
||||
* <p> If this method returns {@code true} then the {@link #array() array}
|
||||
* and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
|
||||
* </p>
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer
|
||||
* @return {@code true} if, and only if, this buffer
|
||||
* is backed by an array and is not read-only
|
||||
*
|
||||
* @since 1.6
|
||||
@ -529,7 +529,7 @@ public abstract class Buffer {
|
||||
* element of the buffer <i>(optional operation)</i>.
|
||||
*
|
||||
* <p> If this buffer is backed by an array then buffer position <i>p</i>
|
||||
* corresponds to array index <i>p</i> + <tt>arrayOffset()</tt>.
|
||||
* corresponds to array index <i>p</i> + {@code arrayOffset()}.
|
||||
*
|
||||
* <p> Invoke the {@link #hasArray hasArray} method before invoking this
|
||||
* method in order to ensure that this buffer has an accessible backing
|
||||
@ -552,7 +552,7 @@ public abstract class Buffer {
|
||||
* Tells whether or not this buffer is
|
||||
* <a href="ByteBuffer.html#direct"><i>direct</i></a>.
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer is direct
|
||||
* @return {@code true} if, and only if, this buffer is direct
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
|
@ -75,9 +75,9 @@ public final class ByteOrder {
|
||||
/**
|
||||
* Constructs a string describing this object.
|
||||
*
|
||||
* <p> This method returns the string <tt>"BIG_ENDIAN"</tt> for {@link
|
||||
* #BIG_ENDIAN} and <tt>"LITTLE_ENDIAN"</tt> for {@link #LITTLE_ENDIAN}.
|
||||
* </p>
|
||||
* <p> This method returns the string
|
||||
* {@code "BIG_ENDIAN"} for {@link #BIG_ENDIAN} and
|
||||
* {@code "LITTLE_ENDIAN"} for {@link #LITTLE_ENDIAN}.
|
||||
*
|
||||
* @return The specified string
|
||||
*/
|
||||
|
@ -116,10 +116,10 @@ public abstract class MappedByteBuffer
|
||||
* Tells whether or not this buffer's content is resident in physical
|
||||
* memory.
|
||||
*
|
||||
* <p> A return value of <tt>true</tt> implies that it is highly likely
|
||||
* <p> A return value of {@code true} implies that it is highly likely
|
||||
* that all of the data in this buffer is resident in physical memory and
|
||||
* may therefore be accessed without incurring any virtual-memory page
|
||||
* faults or I/O operations. A return value of <tt>false</tt> does not
|
||||
* faults or I/O operations. A return value of {@code false} does not
|
||||
* necessarily imply that the buffer's content is not resident in physical
|
||||
* memory.
|
||||
*
|
||||
@ -127,7 +127,7 @@ public abstract class MappedByteBuffer
|
||||
* underlying operating system may have paged out some of the buffer's data
|
||||
* by the time that an invocation of this method returns. </p>
|
||||
*
|
||||
* @return <tt>true</tt> if it is likely that this buffer's content
|
||||
* @return {@code true} if it is likely that this buffer's content
|
||||
* is resident in physical memory
|
||||
*/
|
||||
public final boolean isLoaded() {
|
||||
|
@ -78,7 +78,7 @@ class XXX {
|
||||
* @return The $type$ value at the given index
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If <tt>index</tt> is negative
|
||||
* If {@code index} is negative
|
||||
* or not smaller than the buffer's limit,
|
||||
* minus $nbytesButOne$
|
||||
*/
|
||||
@ -100,7 +100,7 @@ class XXX {
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If <tt>index</tt> is negative
|
||||
* If {@code index} is negative
|
||||
* or not smaller than the buffer's limit,
|
||||
* minus $nbytesButOne$
|
||||
*
|
||||
|
@ -133,7 +133,7 @@ import java.util.stream.$Streamtype$Stream;
|
||||
* <h2> Access to binary data </h2>
|
||||
*
|
||||
* <p> This class defines methods for reading and writing values of all other
|
||||
* primitive types, except <tt>boolean</tt>. Primitive values are translated
|
||||
* primitive types, except {@code boolean}. Primitive values are translated
|
||||
* to (or from) sequences of bytes according to the buffer's current byte
|
||||
* order, which may be retrieved and modified via the {@link #order order}
|
||||
* methods. Specific byte orders are represented by instances of the {@link
|
||||
@ -151,8 +151,8 @@ import java.util.stream.$Streamtype$Stream;
|
||||
* void {@link #putFloat(float) putFloat(float f)}
|
||||
* void {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
|
||||
*
|
||||
* <p> Corresponding methods are defined for the types <tt>char</tt>,
|
||||
* <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and <tt>double</tt>. The index
|
||||
* <p> Corresponding methods are defined for the types {@code char,
|
||||
* short, int, long}, and {@code double}. The index
|
||||
* parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
|
||||
* bytes rather than of the type being read or written.
|
||||
*
|
||||
@ -167,8 +167,7 @@ import java.util.stream.$Streamtype$Stream;
|
||||
* #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
|
||||
* the {@link FloatBuffer} class that is backed by the byte buffer upon which
|
||||
* the method is invoked. Corresponding view-creation methods are defined for
|
||||
* the types <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and
|
||||
* <tt>double</tt>.
|
||||
* the types {@code char, short, int, long}, and {@code double}.
|
||||
*
|
||||
* <p> View buffers have three important advantages over the families of
|
||||
* type-specific <i>get</i> and <i>put</i> methods described above:
|
||||
@ -196,7 +195,7 @@ import java.util.stream.$Streamtype$Stream;
|
||||
*
|
||||
* <p> Like a byte buffer, $a$ $type$ buffer is either <a
|
||||
* href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>. A
|
||||
* $type$ buffer created via the <tt>wrap</tt> methods of this class will
|
||||
* $type$ buffer created via the {@code wrap} methods of this class will
|
||||
* be non-direct. $A$ $type$ buffer created as a view of a byte buffer will
|
||||
* be direct if, and only if, the byte buffer itself is direct. Whether or not
|
||||
* $a$ $type$ buffer is direct may be determined by invoking the {@link
|
||||
@ -208,7 +207,7 @@ import java.util.stream.$Streamtype$Stream;
|
||||
*
|
||||
* <p> This class implements the {@link CharSequence} interface so that
|
||||
* character buffers may be used wherever character sequences are accepted, for
|
||||
* example in the regular-expression package <tt>{@link java.util.regex}</tt>.
|
||||
* example in the regular-expression package {@link java.util.regex}.
|
||||
* </p>
|
||||
*
|
||||
#end[char]
|
||||
@ -306,7 +305,7 @@ public abstract class $Type$Buffer
|
||||
* @return The new $type$ buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the <tt>capacity</tt> is a negative integer
|
||||
* If the {@code capacity} is a negative integer
|
||||
*/
|
||||
public static $Type$Buffer allocateDirect(int capacity) {
|
||||
return new Direct$Type$Buffer(capacity);
|
||||
@ -335,7 +334,7 @@ public abstract class $Type$Buffer
|
||||
* @return The new $type$ buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the <tt>capacity</tt> is a negative integer
|
||||
* If the {@code capacity} is a negative integer
|
||||
*/
|
||||
public static $Type$Buffer allocate(int capacity) {
|
||||
if (capacity < 0)
|
||||
@ -349,8 +348,8 @@ public abstract class $Type$Buffer
|
||||
* <p> The new buffer will be backed by the given $type$ array;
|
||||
* that is, modifications to the buffer will cause the array to be modified
|
||||
* and vice versa. The new buffer's capacity will be
|
||||
* <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
|
||||
* will be <tt>offset + length</tt>, its mark will be undefined, and its
|
||||
* {@code array.length}, its position will be {@code offset}, its limit
|
||||
* will be {@code offset + length}, its mark will be undefined, and its
|
||||
* byte order will be
|
||||
#if[byte]
|
||||
* {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
|
||||
@ -366,19 +365,19 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param offset
|
||||
* The offset of the subarray to be used; must be non-negative and
|
||||
* no larger than <tt>array.length</tt>. The new buffer's position
|
||||
* no larger than {@code array.length}. The new buffer's position
|
||||
* will be set to this value.
|
||||
*
|
||||
* @param length
|
||||
* The length of the subarray to be used;
|
||||
* must be non-negative and no larger than
|
||||
* <tt>array.length - offset</tt>.
|
||||
* The new buffer's limit will be set to <tt>offset + length</tt>.
|
||||
* {@code array.length - offset}.
|
||||
* The new buffer's limit will be set to {@code offset + length}.
|
||||
*
|
||||
* @return The new $type$ buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on the <tt>offset</tt> and <tt>length</tt>
|
||||
* If the preconditions on the {@code offset} and {@code length}
|
||||
* parameters do not hold
|
||||
*/
|
||||
public static $Type$Buffer wrap($type$[] array,
|
||||
@ -397,7 +396,7 @@ public abstract class $Type$Buffer
|
||||
* <p> The new buffer will be backed by the given $type$ array;
|
||||
* that is, modifications to the buffer will cause the array to be modified
|
||||
* and vice versa. The new buffer's capacity and limit will be
|
||||
* <tt>array.length</tt>, its position will be zero, its mark will be
|
||||
* {@code array.length}, its position will be zero, its mark will be
|
||||
* undefined, and its byte order will be
|
||||
#if[byte]
|
||||
* {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
|
||||
@ -458,8 +457,8 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> The content of the new, read-only buffer will be the content of the
|
||||
* given character sequence. The buffer's capacity will be
|
||||
* <tt>csq.length()</tt>, its position will be <tt>start</tt>, its limit
|
||||
* will be <tt>end</tt>, and its mark will be undefined. </p>
|
||||
* {@code csq.length()}, its position will be {@code start}, its limit
|
||||
* will be {@code end}, and its mark will be undefined. </p>
|
||||
*
|
||||
* @param csq
|
||||
* The character sequence from which the new character buffer is to
|
||||
@ -467,19 +466,19 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param start
|
||||
* The index of the first character to be used;
|
||||
* must be non-negative and no larger than <tt>csq.length()</tt>.
|
||||
* must be non-negative and no larger than {@code csq.length()}.
|
||||
* The new buffer's position will be set to this value.
|
||||
*
|
||||
* @param end
|
||||
* The index of the character following the last character to be
|
||||
* used; must be no smaller than <tt>start</tt> and no larger
|
||||
* than <tt>csq.length()</tt>.
|
||||
* used; must be no smaller than {@code start} and no larger
|
||||
* than {@code csq.length()}.
|
||||
* The new buffer's limit will be set to this value.
|
||||
*
|
||||
* @return The new character buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on the <tt>start</tt> and <tt>end</tt>
|
||||
* If the preconditions on the {@code start} and {@code end}
|
||||
* parameters do not hold
|
||||
*/
|
||||
public static CharBuffer wrap(CharSequence csq, int start, int end) {
|
||||
@ -495,7 +494,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> The content of the new, read-only buffer will be the content of the
|
||||
* given character sequence. The new buffer's capacity and limit will be
|
||||
* <tt>csq.length()</tt>, its position will be zero, and its mark will be
|
||||
* {@code csq.length()}, its position will be zero, and its mark will be
|
||||
* undefined. </p>
|
||||
*
|
||||
* @param csq
|
||||
@ -624,7 +623,7 @@ public abstract class $Type$Buffer
|
||||
* @return The $type$ at the given index
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If <tt>index</tt> is negative
|
||||
* If {@code index} is negative
|
||||
* or not smaller than the buffer's limit
|
||||
*/
|
||||
public abstract $type$ get(int index);
|
||||
@ -657,7 +656,7 @@ public abstract class $Type$Buffer
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If <tt>index</tt> is negative
|
||||
* If {@code index} is negative
|
||||
* or not smaller than the buffer's limit
|
||||
*
|
||||
* @throws ReadOnlyBufferException
|
||||
@ -674,17 +673,17 @@ public abstract class $Type$Buffer
|
||||
* <p> This method transfers $type$s from this buffer into the given
|
||||
* destination array. If there are fewer $type$s remaining in the
|
||||
* buffer than are required to satisfy the request, that is, if
|
||||
* <tt>length</tt> <tt>></tt> <tt>remaining()</tt>, then no
|
||||
* {@code length} {@code >} {@code remaining()}, then no
|
||||
* $type$s are transferred and a {@link BufferUnderflowException} is
|
||||
* thrown.
|
||||
*
|
||||
* <p> Otherwise, this method copies <tt>length</tt> $type$s from this
|
||||
* <p> Otherwise, this method copies {@code length} $type$s from this
|
||||
* buffer into the given array, starting at the current position of this
|
||||
* buffer and at the given offset in the array. The position of this
|
||||
* buffer is then incremented by <tt>length</tt>.
|
||||
* buffer is then incremented by {@code length}.
|
||||
*
|
||||
* <p> In other words, an invocation of this method of the form
|
||||
* <tt>src.get(dst, off, len)</tt> has exactly the same effect as
|
||||
* <code>src.get(dst, off, len)</code> has exactly the same effect as
|
||||
* the loop
|
||||
*
|
||||
* <pre>{@code
|
||||
@ -701,21 +700,21 @@ public abstract class $Type$Buffer
|
||||
* @param offset
|
||||
* The offset within the array of the first $type$ to be
|
||||
* written; must be non-negative and no larger than
|
||||
* <tt>dst.length</tt>
|
||||
* {@code dst.length}
|
||||
*
|
||||
* @param length
|
||||
* The maximum number of $type$s to be written to the given
|
||||
* array; must be non-negative and no larger than
|
||||
* <tt>dst.length - offset</tt>
|
||||
* {@code dst.length - offset}
|
||||
*
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws BufferUnderflowException
|
||||
* If there are fewer than <tt>length</tt> $type$s
|
||||
* If there are fewer than {@code length} $type$s
|
||||
* remaining in this buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on the <tt>offset</tt> and <tt>length</tt>
|
||||
* If the preconditions on the {@code offset} and {@code length}
|
||||
* parameters do not hold
|
||||
*/
|
||||
public $Type$Buffer get($type$[] dst, int offset, int length) {
|
||||
@ -733,7 +732,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> This method transfers $type$s from this buffer into the given
|
||||
* destination array. An invocation of this method of the form
|
||||
* <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
|
||||
* {@code src.get(a)} behaves in exactly the same way as the invocation
|
||||
*
|
||||
* <pre>
|
||||
* src.get(a, 0, a.length) </pre>
|
||||
@ -744,7 +743,7 @@ public abstract class $Type$Buffer
|
||||
* @return This buffer
|
||||
*
|
||||
* @throws BufferUnderflowException
|
||||
* If there are fewer than <tt>length</tt> $type$s
|
||||
* If there are fewer than {@code length} $type$s
|
||||
* remaining in this buffer
|
||||
*/
|
||||
public $Type$Buffer get($type$[] dst) {
|
||||
@ -760,17 +759,17 @@ public abstract class $Type$Buffer
|
||||
* <p> This method transfers the $type$s remaining in the given source
|
||||
* buffer into this buffer. If there are more $type$s remaining in the
|
||||
* source buffer than in this buffer, that is, if
|
||||
* <tt>src.remaining()</tt> <tt>></tt> <tt>remaining()</tt>,
|
||||
* {@code src.remaining()} {@code >} {@code remaining()},
|
||||
* then no $type$s are transferred and a {@link
|
||||
* BufferOverflowException} is thrown.
|
||||
*
|
||||
* <p> Otherwise, this method copies
|
||||
* <i>n</i> = <tt>src.remaining()</tt> $type$s from the given
|
||||
* <i>n</i> = {@code src.remaining()} $type$s from the given
|
||||
* buffer into this buffer, starting at each buffer's current position.
|
||||
* The positions of both buffers are then incremented by <i>n</i>.
|
||||
*
|
||||
* <p> In other words, an invocation of this method of the form
|
||||
* <tt>dst.put(src)</tt> has exactly the same effect as the loop
|
||||
* {@code dst.put(src)} has exactly the same effect as the loop
|
||||
*
|
||||
* <pre>
|
||||
* while (src.hasRemaining())
|
||||
@ -814,17 +813,17 @@ public abstract class $Type$Buffer
|
||||
* <p> This method transfers $type$s into this buffer from the given
|
||||
* source array. If there are more $type$s to be copied from the array
|
||||
* than remain in this buffer, that is, if
|
||||
* <tt>length</tt> <tt>></tt> <tt>remaining()</tt>, then no
|
||||
* {@code length} {@code >} {@code remaining()}, then no
|
||||
* $type$s are transferred and a {@link BufferOverflowException} is
|
||||
* thrown.
|
||||
*
|
||||
* <p> Otherwise, this method copies <tt>length</tt> $type$s from the
|
||||
* <p> Otherwise, this method copies {@code length} $type$s from the
|
||||
* given array into this buffer, starting at the given offset in the array
|
||||
* and at the current position of this buffer. The position of this buffer
|
||||
* is then incremented by <tt>length</tt>.
|
||||
* is then incremented by {@code length}.
|
||||
*
|
||||
* <p> In other words, an invocation of this method of the form
|
||||
* <tt>dst.put(src, off, len)</tt> has exactly the same effect as
|
||||
* <code>dst.put(src, off, len)</code> has exactly the same effect as
|
||||
* the loop
|
||||
*
|
||||
* <pre>{@code
|
||||
@ -840,12 +839,12 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param offset
|
||||
* The offset within the array of the first $type$ to be read;
|
||||
* must be non-negative and no larger than <tt>array.length</tt>
|
||||
* must be non-negative and no larger than {@code array.length}
|
||||
*
|
||||
* @param length
|
||||
* The number of $type$s to be read from the given array;
|
||||
* must be non-negative and no larger than
|
||||
* <tt>array.length - offset</tt>
|
||||
* {@code array.length - offset}
|
||||
*
|
||||
* @return This buffer
|
||||
*
|
||||
@ -853,7 +852,7 @@ public abstract class $Type$Buffer
|
||||
* If there is insufficient space in this buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on the <tt>offset</tt> and <tt>length</tt>
|
||||
* If the preconditions on the {@code offset} and {@code length}
|
||||
* parameters do not hold
|
||||
*
|
||||
* @throws ReadOnlyBufferException
|
||||
@ -874,7 +873,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> This method transfers the entire content of the given source
|
||||
* $type$ array into this buffer. An invocation of this method of the
|
||||
* form <tt>dst.put(a)</tt> behaves in exactly the same way as the
|
||||
* form {@code dst.put(a)} behaves in exactly the same way as the
|
||||
* invocation
|
||||
*
|
||||
* <pre>
|
||||
@ -903,18 +902,18 @@ public abstract class $Type$Buffer
|
||||
* <p> This method transfers $type$s from the given string into this
|
||||
* buffer. If there are more $type$s to be copied from the string than
|
||||
* remain in this buffer, that is, if
|
||||
* <tt>end - start</tt> <tt>></tt> <tt>remaining()</tt>,
|
||||
* <code>end - start</code> {@code >} {@code remaining()},
|
||||
* then no $type$s are transferred and a {@link
|
||||
* BufferOverflowException} is thrown.
|
||||
*
|
||||
* <p> Otherwise, this method copies
|
||||
* <i>n</i> = <tt>end</tt> - <tt>start</tt> $type$s
|
||||
* <i>n</i> = {@code end} - {@code start} $type$s
|
||||
* from the given string into this buffer, starting at the given
|
||||
* <tt>start</tt> index and at the current position of this buffer. The
|
||||
* {@code start} index and at the current position of this buffer. The
|
||||
* position of this buffer is then incremented by <i>n</i>.
|
||||
*
|
||||
* <p> In other words, an invocation of this method of the form
|
||||
* <tt>dst.put(src, start, end)</tt> has exactly the same effect
|
||||
* <code>dst.put(src, start, end)</code> has exactly the same effect
|
||||
* as the loop
|
||||
*
|
||||
* <pre>{@code
|
||||
@ -931,12 +930,12 @@ public abstract class $Type$Buffer
|
||||
* @param start
|
||||
* The offset within the string of the first $type$ to be read;
|
||||
* must be non-negative and no larger than
|
||||
* <tt>string.length()</tt>
|
||||
* {@code string.length()}
|
||||
*
|
||||
* @param end
|
||||
* The offset within the string of the last $type$ to be read,
|
||||
* plus one; must be non-negative and no larger than
|
||||
* <tt>string.length()</tt>
|
||||
* {@code string.length()}
|
||||
*
|
||||
* @return This buffer
|
||||
*
|
||||
@ -944,7 +943,7 @@ public abstract class $Type$Buffer
|
||||
* If there is insufficient space in this buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on the <tt>start</tt> and <tt>end</tt>
|
||||
* If the preconditions on the {@code start} and {@code end}
|
||||
* parameters do not hold
|
||||
*
|
||||
* @throws ReadOnlyBufferException
|
||||
@ -966,7 +965,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> This method transfers the entire content of the given source string
|
||||
* into this buffer. An invocation of this method of the form
|
||||
* <tt>dst.put(s)</tt> behaves in exactly the same way as the invocation
|
||||
* {@code dst.put(s)} behaves in exactly the same way as the invocation
|
||||
*
|
||||
* <pre>
|
||||
* dst.put(s, 0, s.length()) </pre>
|
||||
@ -995,11 +994,11 @@ public abstract class $Type$Buffer
|
||||
* Tells whether or not this buffer is backed by an accessible $type$
|
||||
* array.
|
||||
*
|
||||
* <p> If this method returns <tt>true</tt> then the {@link #array() array}
|
||||
* <p> If this method returns {@code true} then the {@link #array() array}
|
||||
* and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
|
||||
* </p>
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer
|
||||
* @return {@code true} if, and only if, this buffer
|
||||
* is backed by an array and is not read-only
|
||||
*/
|
||||
public final boolean hasArray() {
|
||||
@ -1038,7 +1037,7 @@ public abstract class $Type$Buffer
|
||||
* element of the buffer <i>(optional operation)</i>.
|
||||
*
|
||||
* <p> If this buffer is backed by an array then buffer position <i>p</i>
|
||||
* corresponds to array index <i>p</i> + <tt>arrayOffset()</tt>.
|
||||
* corresponds to array index <i>p</i> + {@code arrayOffset()}.
|
||||
*
|
||||
* <p> Invoke the {@link #hasArray hasArray} method before invoking this
|
||||
* method in order to ensure that this buffer has an accessible backing
|
||||
@ -1166,11 +1165,11 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> The $type$s between the buffer's current position and its limit,
|
||||
* if any, are copied to the beginning of the buffer. That is, the
|
||||
* $type$ at index <i>p</i> = <tt>position()</tt> is copied
|
||||
* $type$ at index <i>p</i> = {@code position()} is copied
|
||||
* to index zero, the $type$ at index <i>p</i> + 1 is copied
|
||||
* to index one, and so forth until the $type$ at index
|
||||
* <tt>limit()</tt> - 1 is copied to index
|
||||
* <i>n</i> = <tt>limit()</tt> - <tt>1</tt> - <i>p</i>.
|
||||
* {@code limit()} - 1 is copied to index
|
||||
* <i>n</i> = {@code limit()} - {@code 1} - <i>p</i>.
|
||||
* The buffer's position is then set to <i>n+1</i> and its limit is set to
|
||||
* its capacity. The mark, if defined, is discarded.
|
||||
*
|
||||
@ -1183,7 +1182,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> Invoke this method after writing data from a buffer in case the
|
||||
* write was incomplete. The following loop, for example, copies bytes
|
||||
* from one channel to another via the buffer <tt>buf</tt>:
|
||||
* from one channel to another via the buffer {@code buf}:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
* buf.clear(); // Prepare buffer for use
|
||||
@ -1206,7 +1205,7 @@ public abstract class $Type$Buffer
|
||||
/**
|
||||
* Tells whether or not this $type$ buffer is direct.
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer is direct
|
||||
* @return {@code true} if, and only if, this buffer is direct
|
||||
*/
|
||||
public abstract boolean isDirect();
|
||||
|
||||
@ -1239,8 +1238,8 @@ public abstract class $Type$Buffer
|
||||
* Returns the current hash code of this buffer.
|
||||
*
|
||||
* <p> The hash code of a $type$ buffer depends only upon its remaining
|
||||
* elements; that is, upon the elements from <tt>position()</tt> up to, and
|
||||
* including, the element at <tt>limit()</tt> - <tt>1</tt>.
|
||||
* elements; that is, upon the elements from {@code position()} up to, and
|
||||
* including, the element at {@code limit()} - {@code 1}.
|
||||
*
|
||||
* <p> Because buffer hash codes are content-dependent, it is inadvisable
|
||||
* to use buffers as keys in hash maps or similar data structures unless it
|
||||
@ -1289,7 +1288,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param ob The object to which this buffer is to be compared
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this buffer is equal to the
|
||||
* @return {@code true} if, and only if, this buffer is equal to the
|
||||
* given object
|
||||
*/
|
||||
public boolean equals(Object ob) {
|
||||
@ -1368,7 +1367,7 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* <p> The first character of the resulting string will be the character at
|
||||
* this buffer's position, while the last character will be the character
|
||||
* at index <tt>limit()</tt> - 1. Invoking this method does not
|
||||
* at index {@code limit()} - 1. Invoking this method does not
|
||||
* change the buffer's position. </p>
|
||||
*
|
||||
* @return The specified string
|
||||
@ -1388,7 +1387,7 @@ public abstract class $Type$Buffer
|
||||
* <p> When viewed as a character sequence, the length of a character
|
||||
* buffer is simply the number of characters between the position
|
||||
* (inclusive) and the limit (exclusive); that is, it is equivalent to
|
||||
* <tt>remaining()</tt>. </p>
|
||||
* {@code remaining()}. </p>
|
||||
*
|
||||
* @return The length of this character buffer
|
||||
*/
|
||||
@ -1402,13 +1401,13 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param index
|
||||
* The index of the character to be read, relative to the position;
|
||||
* must be non-negative and smaller than <tt>remaining()</tt>
|
||||
* must be non-negative and smaller than {@code remaining()}
|
||||
*
|
||||
* @return The character at index
|
||||
* <tt>position() + index</tt>
|
||||
* <code>position() + index</code>
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on <tt>index</tt> do not hold
|
||||
* If the preconditions on {@code index} do not hold
|
||||
*/
|
||||
public final char charAt(int index) {
|
||||
return get(position() + checkIndex(index, 1));
|
||||
@ -1422,26 +1421,26 @@ public abstract class $Type$Buffer
|
||||
* content of this buffer is mutable then modifications to one buffer will
|
||||
* cause the other to be modified. The new buffer's capacity will be that
|
||||
* of this buffer, its position will be
|
||||
* <tt>position()</tt> + <tt>start</tt>, and its limit will be
|
||||
* <tt>position()</tt> + <tt>end</tt>. The new buffer will be
|
||||
* {@code position()} + {@code start}, and its limit will be
|
||||
* {@code position()} + {@code end}. The new buffer will be
|
||||
* direct if, and only if, this buffer is direct, and it will be read-only
|
||||
* if, and only if, this buffer is read-only. </p>
|
||||
*
|
||||
* @param start
|
||||
* The index, relative to the current position, of the first
|
||||
* character in the subsequence; must be non-negative and no larger
|
||||
* than <tt>remaining()</tt>
|
||||
* than {@code remaining()}
|
||||
*
|
||||
* @param end
|
||||
* The index, relative to the current position, of the character
|
||||
* following the last character in the subsequence; must be no
|
||||
* smaller than <tt>start</tt> and no larger than
|
||||
* <tt>remaining()</tt>
|
||||
* smaller than {@code start} and no larger than
|
||||
* {@code remaining()}
|
||||
*
|
||||
* @return The new character buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the preconditions on <tt>start</tt> and <tt>end</tt>
|
||||
* If the preconditions on {@code start} and {@code end}
|
||||
* do not hold
|
||||
*/
|
||||
public abstract CharBuffer subSequence(int start, int end);
|
||||
@ -1453,21 +1452,21 @@ public abstract class $Type$Buffer
|
||||
* Appends the specified character sequence to this
|
||||
* buffer <i>(optional operation)</i>.
|
||||
*
|
||||
* <p> An invocation of this method of the form <tt>dst.append(csq)</tt>
|
||||
* <p> An invocation of this method of the form {@code dst.append(csq)}
|
||||
* behaves in exactly the same way as the invocation
|
||||
*
|
||||
* <pre>
|
||||
* dst.put(csq.toString()) </pre>
|
||||
*
|
||||
* <p> Depending on the specification of <tt>toString</tt> for the
|
||||
* character sequence <tt>csq</tt>, the entire sequence may not be
|
||||
* <p> Depending on the specification of {@code toString} for the
|
||||
* character sequence {@code csq}, the entire sequence may not be
|
||||
* appended. For instance, invoking the {@link $Type$Buffer#toString()
|
||||
* toString} method of a character buffer will return a subsequence whose
|
||||
* content depends upon the buffer's position and limit.
|
||||
*
|
||||
* @param csq
|
||||
* The character sequence to append. If <tt>csq</tt> is
|
||||
* <tt>null</tt>, then the four characters <tt>"null"</tt> are
|
||||
* The character sequence to append. If {@code csq} is
|
||||
* {@code null}, then the four characters {@code "null"} are
|
||||
* appended to this character buffer.
|
||||
*
|
||||
* @return This buffer
|
||||
@ -1491,8 +1490,8 @@ public abstract class $Type$Buffer
|
||||
* Appends a subsequence of the specified character sequence to this
|
||||
* buffer <i>(optional operation)</i>.
|
||||
*
|
||||
* <p> An invocation of this method of the form <tt>dst.append(csq, start,
|
||||
* end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in exactly the
|
||||
* <p> An invocation of this method of the form {@code dst.append(csq, start,
|
||||
* end)} when {@code csq} is not {@code null}, behaves in exactly the
|
||||
* same way as the invocation
|
||||
*
|
||||
* <pre>
|
||||
@ -1500,9 +1499,9 @@ public abstract class $Type$Buffer
|
||||
*
|
||||
* @param csq
|
||||
* The character sequence from which a subsequence will be
|
||||
* appended. If <tt>csq</tt> is <tt>null</tt>, then characters
|
||||
* will be appended as if <tt>csq</tt> contained the four
|
||||
* characters <tt>"null"</tt>.
|
||||
* appended. If {@code csq} is {@code null}, then characters
|
||||
* will be appended as if {@code csq} contained the four
|
||||
* characters {@code "null"}.
|
||||
*
|
||||
* @return This buffer
|
||||
*
|
||||
@ -1510,9 +1509,9 @@ public abstract class $Type$Buffer
|
||||
* If there is insufficient space in this buffer
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
|
||||
* is greater than <tt>end</tt>, or <tt>end</tt> is greater than
|
||||
* <tt>csq.length()</tt>
|
||||
* If {@code start} or {@code end} are negative, {@code start}
|
||||
* is greater than {@code end}, or {@code end} is greater than
|
||||
* {@code csq.length()}
|
||||
*
|
||||
* @throws ReadOnlyBufferException
|
||||
* If this buffer is read-only
|
||||
@ -1528,7 +1527,7 @@ public abstract class $Type$Buffer
|
||||
* Appends the specified $type$ to this
|
||||
* buffer <i>(optional operation)</i>.
|
||||
*
|
||||
* <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
|
||||
* <p> An invocation of this method of the form {@code dst.append($x$)}
|
||||
* behaves in exactly the same way as the invocation
|
||||
*
|
||||
* <pre>
|
||||
@ -1562,7 +1561,7 @@ public abstract class $Type$Buffer
|
||||
* Retrieves this buffer's byte order.
|
||||
*
|
||||
* <p> The byte order of $a$ $type$ buffer created by allocation or by
|
||||
* wrapping an existing <tt>$type$</tt> array is the {@link
|
||||
* wrapping an existing {@code $type$} array is the {@link
|
||||
* ByteOrder#nativeOrder native order} of the underlying
|
||||
* hardware. The byte order of $a$ $type$ buffer created as a <a
|
||||
* href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
|
||||
|
@ -70,13 +70,13 @@ public interface AsynchronousByteChannel
|
||||
* {@code 0} without initiating an I/O operation.
|
||||
*
|
||||
* <p> Suppose that a byte sequence of length <i>n</i> is read, where
|
||||
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
|
||||
* {@code 0} {@code <} <i>n</i> {@code <=} <i>r</i>.
|
||||
* This byte sequence will be transferred into the buffer so that the first
|
||||
* byte in the sequence is at index <i>p</i> and the last byte is at index
|
||||
* <i>p</i> <tt>+</tt> <i>n</i> <tt>-</tt> <tt>1</tt>,
|
||||
* <i>p</i> {@code +} <i>n</i> {@code -} {@code 1},
|
||||
* where <i>p</i> is the buffer's position at the moment the read is
|
||||
* performed. Upon completion the buffer's position will be equal to
|
||||
* <i>p</i> <tt>+</tt> <i>n</i>; its limit will not have changed.
|
||||
* <i>p</i> {@code +} <i>n</i>; its limit will not have changed.
|
||||
*
|
||||
* <p> Buffers are not safe for use by multiple concurrent threads so care
|
||||
* should be taken to not access the buffer until the operation has
|
||||
@ -151,13 +151,13 @@ public interface AsynchronousByteChannel
|
||||
* {@code 0} without initiating an I/O operation.
|
||||
*
|
||||
* <p> Suppose that a byte sequence of length <i>n</i> is written, where
|
||||
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
|
||||
* {@code 0} {@code <} <i>n</i> {@code <=} <i>r</i>.
|
||||
* This byte sequence will be transferred from the buffer starting at index
|
||||
* <i>p</i>, where <i>p</i> is the buffer's position at the moment the
|
||||
* write is performed; the index of the last byte written will be
|
||||
* <i>p</i> <tt>+</tt> <i>n</i> <tt>-</tt> <tt>1</tt>.
|
||||
* <i>p</i> {@code +} <i>n</i> {@code -} {@code 1}.
|
||||
* Upon completion the buffer's position will be equal to
|
||||
* <i>p</i> <tt>+</tt> <i>n</i>; its limit will not have changed.
|
||||
* <i>p</i> {@code +} <i>n</i>; its limit will not have changed.
|
||||
*
|
||||
* <p> Buffers are not safe for use by multiple concurrent threads so care
|
||||
* should be taken to not access the buffer until the operation has
|
||||
|
@ -41,7 +41,7 @@ import java.io.IOException;
|
||||
* by invoking the {@link #bind(SocketAddress,int) bind} method. Once bound,
|
||||
* the {@link #accept(Object,CompletionHandler) accept} method
|
||||
* is used to initiate the accepting of connections to the channel's socket.
|
||||
* An attempt to invoke the <tt>accept</tt> method on an unbound channel will
|
||||
* An attempt to invoke the {@code accept} method on an unbound channel will
|
||||
* cause a {@link NotYetBoundException} to be thrown.
|
||||
*
|
||||
* <p> Channels of this type are safe for use by multiple concurrent threads
|
||||
@ -122,13 +122,13 @@ public abstract class AsynchronousServerSocketChannel
|
||||
* java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousServerSocketChannel
|
||||
* openAsynchronousServerSocketChannel} method on the {@link
|
||||
* java.nio.channels.spi.AsynchronousChannelProvider} object that created
|
||||
* the given group. If the group parameter is <tt>null</tt> then the
|
||||
* the given group. If the group parameter is {@code null} then the
|
||||
* resulting channel is created by the system-wide default provider, and
|
||||
* bound to the <em>default group</em>.
|
||||
*
|
||||
* @param group
|
||||
* The group to which the newly constructed channel should be bound,
|
||||
* or <tt>null</tt> for the default group
|
||||
* or {@code null} for the default group
|
||||
*
|
||||
* @return A new asynchronous server socket channel
|
||||
*
|
||||
@ -176,7 +176,7 @@ public abstract class AsynchronousServerSocketChannel
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or <tt>null</tt> to bind
|
||||
* The local address to bind the socket, or {@code null} to bind
|
||||
* to an automatically assigned socket address
|
||||
*
|
||||
* @return This channel
|
||||
|
@ -452,11 +452,11 @@ public abstract class AsynchronousSocketChannel
|
||||
* at the moment that the read is attempted.
|
||||
*
|
||||
* <p> Suppose that a byte sequence of length <i>n</i> is read, where
|
||||
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
|
||||
* Up to the first <tt>dsts[offset].remaining()</tt> bytes of this sequence
|
||||
* are transferred into buffer <tt>dsts[offset]</tt>, up to the next
|
||||
* <tt>dsts[offset+1].remaining()</tt> bytes are transferred into buffer
|
||||
* <tt>dsts[offset+1]</tt>, and so forth, until the entire byte sequence
|
||||
* {@code 0} {@code <} <i>n</i> {@code <=} <i>r</i>.
|
||||
* Up to the first {@code dsts[offset].remaining()} bytes of this sequence
|
||||
* are transferred into buffer {@code dsts[offset]}, up to the next
|
||||
* {@code dsts[offset+1].remaining()} bytes are transferred into buffer
|
||||
* {@code dsts[offset+1]}, and so forth, until the entire byte sequence
|
||||
* is transferred into the given buffers. As many bytes as possible are
|
||||
* transferred into each buffer, hence the final position of each updated
|
||||
* buffer, except the last updated buffer, is guaranteed to be equal to
|
||||
@ -606,11 +606,11 @@ public abstract class AsynchronousSocketChannel
|
||||
* at the moment that the write is attempted.
|
||||
*
|
||||
* <p> Suppose that a byte sequence of length <i>n</i> is written, where
|
||||
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
|
||||
* Up to the first <tt>srcs[offset].remaining()</tt> bytes of this sequence
|
||||
* are written from buffer <tt>srcs[offset]</tt>, up to the next
|
||||
* <tt>srcs[offset+1].remaining()</tt> bytes are written from buffer
|
||||
* <tt>srcs[offset+1]</tt>, and so forth, until the entire byte sequence is
|
||||
* {@code 0} {@code <} <i>n</i> {@code <=} <i>r</i>.
|
||||
* Up to the first {@code srcs[offset].remaining()} bytes of this sequence
|
||||
* are written from buffer {@code srcs[offset]}, up to the next
|
||||
* {@code srcs[offset+1].remaining()} bytes are written from buffer
|
||||
* {@code srcs[offset+1]}, and so forth, until the entire byte sequence is
|
||||
* written. As many bytes as possible are written from each buffer, hence
|
||||
* the final position of each updated buffer, except the last updated
|
||||
* buffer, is guaranteed to be equal to that buffer's limit. The underlying
|
||||
|
@ -58,7 +58,7 @@ public interface Channel extends Closeable {
|
||||
/**
|
||||
* Tells whether or not this channel is open.
|
||||
*
|
||||
* @return <tt>true</tt> if, and only if, this channel is open
|
||||
* @return {@code true} if, and only if, this channel is open
|
||||
*/
|
||||
public boolean isOpen();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user