From 200784d505dd98444c48c9ccb7f2e4df36dcbb6a Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Oct 2015 18:13:34 -0400 Subject: [PATCH 001/113] 8132051: Better byte behavior Co-authored-by: Roland Westerlin Co-authored-by: Vladimir Kozlov Co-authored-by: John Rose Reviewed-by: bdelsart, roland, kvn, jrose, ahgross --- .../cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 5 +- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 59 +++++++++++++++-- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 2 + .../src/cpu/sparc/vm/templateTable_sparc.cpp | 65 +++++++++++++++++-- .../src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/interp_masm_x86.cpp | 51 +++++++++++++++ hotspot/src/cpu/x86/vm/interp_masm_x86.hpp | 3 + hotspot/src/cpu/x86/vm/templateTable_x86.cpp | 60 +++++++++++++++-- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 35 +++++++++- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 3 +- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 61 ++++++++++++++++- hotspot/src/share/vm/c1/c1_Instruction.hpp | 7 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 23 +++++++ hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 1 + .../share/vm/classfile/classFileParser.cpp | 6 +- .../src/share/vm/classfile/defaultMethods.cpp | 4 +- .../vm/interpreter/bytecodeInterpreter.cpp | 25 +++++-- .../src/share/vm/interpreter/bytecodes.cpp | 3 +- .../src/share/vm/interpreter/bytecodes.hpp | 1 + .../vm/interpreter/interpreterRuntime.cpp | 3 +- .../vm/interpreter/templateInterpreter.cpp | 12 ++-- .../vm/interpreter/templateInterpreter.hpp | 2 +- .../templateInterpreterGenerator.cpp | 17 ++++- .../share/vm/interpreter/templateTable.cpp | 1 + hotspot/src/share/vm/oops/constMethod.cpp | 1 + hotspot/src/share/vm/oops/constMethod.hpp | 5 ++ hotspot/src/share/vm/oops/cpCache.hpp | 25 +++---- hotspot/src/share/vm/oops/klass.hpp | 15 +++++ hotspot/src/share/vm/oops/method.cpp | 4 +- hotspot/src/share/vm/oops/oop.inline.hpp | 4 +- hotspot/src/share/vm/opto/memnode.cpp | 2 +- hotspot/src/share/vm/opto/parse1.cpp | 34 ++++++++++ hotspot/src/share/vm/opto/parse2.cpp | 6 +- hotspot/src/share/vm/opto/type.cpp | 10 +-- hotspot/src/share/vm/prims/jni.cpp | 2 + hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 2 +- hotspot/src/share/vm/prims/jvmtiExport.cpp | 2 +- hotspot/src/share/vm/prims/unsafe.cpp | 13 +++- hotspot/src/share/vm/runtime/reflection.cpp | 2 +- .../share/vm/utilities/globalDefinitions.hpp | 21 +++--- 40 files changed, 514 insertions(+), 88 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 6185a1d59cd..de568fd7693 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -344,7 +344,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -389,7 +389,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 4e0b6d504f6..580b1336bf3 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -208,6 +208,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case atos: ld_ptr(oop_addr, Otos_l); st_ptr(G0, oop_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: ld(val_addr, Otos_l1); break; @@ -452,9 +453,10 @@ void InterpreterMacroAssembler::push(TosState state) { interp_verify_oop(Otos_i, state, __FILE__, __LINE__); switch (state) { case atos: push_ptr(); break; - case btos: push_i(); break; - case ctos: - case stos: push_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: push_i(); break; case ltos: push_l(); break; case ftos: push_f(); break; @@ -468,9 +470,10 @@ void InterpreterMacroAssembler::push(TosState state) { void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; - case btos: pop_i(); break; - case ctos: - case stos: pop_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: pop_i(); break; case ltos: pop_l(); break; case ftos: pop_f(); break; @@ -1103,6 +1106,49 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, interp_verify_oop(Otos_i, state, __FILE__, __LINE__); } +void InterpreterMacroAssembler::narrow(Register result) { + + ld_ptr(Address(Lmethod, Method::const_offset()), G3_scratch); + ldub(G3_scratch, in_bytes(ConstMethod::result_type_offset()), G3_scratch); + + Label notBool, notByte, notChar, done; + + // common case first + cmp(G3_scratch, T_INT); + br(Assembler::equal, true, pn, done); + delayed()->nop(); + + cmp(G3_scratch, T_BOOLEAN); + br(Assembler::notEqual, true, pn, notBool); + delayed()->cmp(G3_scratch, T_BYTE); + and3(result, 1, result); + ba(done); + delayed()->nop(); + + bind(notBool); + // cmp(G3_scratch, T_BYTE); + br(Assembler::notEqual, true, pn, notByte); + delayed()->cmp(G3_scratch, T_CHAR); + sll(result, 24, result); + sra(result, 24, result); + ba(done); + delayed()->nop(); + + bind(notByte); + // cmp(G3_scratch, T_CHAR); + sll(result, 16, result); + br(Assembler::notEqual, true, pn, done); + delayed()->sra(result, 16, result); + // sll(result, 16, result); + srl(result, 16, result); + + // bind(notChar); + // must be short, instructions already executed in delay slot + // sll(result, 16, result); + // sra(result, 16, result); + + bind(done); +} // remove activation // @@ -1151,6 +1197,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 #endif case btos: // fall through + case ztos: // fall through case ctos: case stos: // fall through case atos: // fall through diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 4fa3b09b3a9..1baceb1233c 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -103,6 +103,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void dispatch_via (TosState state, address* table); + void narrow(Register result); + // Removes the current activation (incl. unlocking of monitors). // Additionally this code is used for earlyReturn in which case we // want to skip throwing an exception and installing an exception. diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 1315f7c8d60..2976383f767 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -165,6 +165,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -922,8 +923,20 @@ void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(O2); // index // Otos_i: val + // O2: index // O3: array __ index_check(O3, O2, 0, G3_scratch, O2); + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(O3, G4_scratch); + __ ld(G4_scratch, in_bytes(Klass::layout_helper_offset()), G4_scratch); + __ set(Klass::layout_helper_boolean_diffbit(), G3_scratch); + __ andcc(G3_scratch, G4_scratch, G0); + Label L_skip; + __ br(Assembler::zero, false, Assembler::pn, L_skip); + __ delayed()->nop(); + __ and3(Otos_i, 1, Otos_i); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } @@ -2008,6 +2021,12 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(Otos_i); + } __ remove_activation(state, /* throw_monitor_exception */ true); // The caller's SP was adjusted upon method entry to accomodate @@ -2218,7 +2237,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr Label checkVolatile; // compute field type - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj; + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj; __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags); // Make sure we don't need to mask Rflags after the above shift ConstantPoolCacheEntry::verify_tos_state_shift(); @@ -2273,7 +2292,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed() ->cmp(Rflags, ctos); + __ delayed() ->cmp(Rflags, ztos); // btos __ ldsb(Rclass, Roffset, Otos_i); @@ -2286,6 +2305,22 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ bind(notByte); + // cmp(Rflags, ztos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed() ->cmp(Rflags, ctos); + + // ztos + __ ldsb(Rclass, Roffset, Otos_i); + __ push(itos); + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + + __ bind(notBool); + // cmp(Rflags, ctos); __ br(Assembler::notEqual, false, Assembler::pt, notChar); __ delayed() ->cmp(Rflags, stos); @@ -2449,6 +2484,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // save tos values before call_VM() clobbers them case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break; @@ -2466,6 +2502,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break; @@ -2581,7 +2618,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr ConstantPoolCacheEntry::verify_tos_state_shift(); // compute field type - Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat; + Label notInt, notShort, notChar, notObj, notByte, notBool, notLong, notFloat; if (is_static) { // putstatic with object type most likely, check that first @@ -2649,7 +2686,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed()->cmp(Rflags, ltos); + __ delayed()->cmp(Rflags, ztos); // btos { @@ -2664,6 +2701,25 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + + // cmp(Rflags, btos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed()->cmp(Rflags, ltos); + + // ztos + { + __ pop_i(); + if (!is_static) pop_and_check_object(Rclass); + __ and3(Otos_i, 1, Otos_i); + __ stb(Otos_i, Rclass, Roffset); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, G3_scratch, G4_scratch, true, byte_no); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + } + + __ bind(notBool); // cmp(Rflags, ltos); __ br(Assembler::notEqual, false, Assembler::pt, notLong); __ delayed()->cmp(Rflags, ctos); @@ -2787,6 +2843,7 @@ void TemplateTable::fast_storefield(TosState state) { pop_and_check_object(Rclass); switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ and3(Otos_i, 1, Otos_i); // fall through to bputfield case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break; case Bytecodes::_fast_cputfield: /* fall through */ case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break; diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index b545d0b6989..20c19325463 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -284,7 +284,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -332,7 +332,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { // Seems to be a precise post_barrier(LIR_OprFact::address(array_addr), value.result()); } else { - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); } } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp index 8dc3084c442..f8578f9f420 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp @@ -349,6 +349,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { verify_oop(rax, state); break; case ltos: movptr(rax, val_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -370,6 +371,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case ltos: movl(rdx, val_addr1); // fall through case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -616,6 +618,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -633,6 +636,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -668,6 +672,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: pop_i(rax); break; @@ -716,6 +721,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: push_i(rax); break; @@ -849,6 +855,51 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { dispatch_base(state, table); } +void InterpreterMacroAssembler::narrow(Register result) { + + // Get method->_constMethod->_result_type + movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + movptr(rcx, Address(rcx, Method::const_offset())); + load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset())); + + Label done, notBool, notByte, notChar; + + // common case first + cmpl(rcx, T_INT); + jcc(Assembler::equal, done); + + // mask integer result to narrower return type. + cmpl(rcx, T_BOOLEAN); + jcc(Assembler::notEqual, notBool); + andl(result, 0x1); + jmp(done); + + bind(notBool); + cmpl(rcx, T_BYTE); + jcc(Assembler::notEqual, notByte); + LP64_ONLY(movsbl(result, result);) + NOT_LP64(shll(result, 24);) // truncate upper 24 bits + NOT_LP64(sarl(result, 24);) // and sign-extend byte + jmp(done); + + bind(notByte); + cmpl(rcx, T_CHAR); + jcc(Assembler::notEqual, notChar); + LP64_ONLY(movzwl(result, result);) + NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits + jmp(done); + + bind(notChar); + // cmpl(rcx, T_SHORT); // all that's left + // jcc(Assembler::notEqual, done); + LP64_ONLY(movswl(result, result);) + NOT_LP64(shll(result, 16);) // truncate upper 16 bits + NOT_LP64(sarl(result, 16);) // and sign-extend short + + // Nothing to do for T_INT + bind(done); +} + // remove activation // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 470ac6e6399..9ed5c2c9ad3 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -192,6 +192,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void prepare_to_jump_from_interpreted(); void jump_from_interpreted(Register method, Register temp); + // narrow int return value + void narrow(Register result); + // Returning from interpreted functions // // Removes the current activation (incl. unlocking of monitors) diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 42520c7e418..9f99613b1e6 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -243,6 +243,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -1082,6 +1083,16 @@ void TemplateTable::bastore() { // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(rcx, rdx); + __ movl(rcx, Address(rcx, Klass::layout_helper_offset())); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ testl(rcx, diffbit); + Label L_skip; + __ jccb(Assembler::zero, L_skip); + __ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -2540,13 +2551,12 @@ void TemplateTable::fast_binaryswitch() { void TemplateTable::_return(TosState state) { transition(state, state); - Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); - assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { assert(state == vtos, "only valid state"); + Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); __ movptr(robj, aaddress(0)); __ load_klass(rdi, robj); __ movl(rdi, Address(rdi, Klass::access_flags_offset())); @@ -2559,7 +2569,14 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(rax); + } __ remove_activation(state, rbcp); + __ jmp(rbcp); } @@ -2754,7 +2771,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize)); - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); // Make sure we don't need to mask edx after the above shift @@ -2773,6 +2790,20 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jmp(Done); __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos (same code as btos) + __ load_signed_byte(rax, field); + __ push(ztos); + // Rewrite bytecode to be faster + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); // atos @@ -3006,7 +3037,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);) - Label notByte, notInt, notShort, notChar, + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); @@ -3027,6 +3058,22 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos + { + __ pop(ztos); + if (!is_static) pop_and_check_object(obj); + __ andl(rax, 0x1); + __ movb(field, rax); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); @@ -3214,6 +3261,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(rax); break; @@ -3238,6 +3286,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(rax); break; @@ -3297,6 +3346,9 @@ void TemplateTable::fast_storefield(TosState state) { case Bytecodes::_fast_iputfield: __ movl(field, rax); break; + case Bytecodes::_fast_zputfield: + __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(field, rax); break; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 4dc68335b6a..48143d50e72 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -82,6 +82,29 @@ int CppInterpreter::normal_entry(Method* method, intptr_t UNUSED, TRAPS) { return 0; } +intptr_t narrow(BasicType type, intptr_t result) { + // mask integer result to narrower return type. + switch (type) { + case T_BOOLEAN: + return result&1; + case T_BYTE: + return (intptr_t)(jbyte)result; + case T_CHAR: + return (intptr_t)(uintptr_t)(jchar)result; + case T_SHORT: + return (intptr_t)(jshort)result; + case T_OBJECT: // nothing to do fall through + case T_LONG: + case T_INT: + case T_FLOAT: + case T_DOUBLE: + case T_VOID: + return result; + default : ShouldNotReachHere(); + } +} + + void CppInterpreter::main_loop(int recurse, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -195,8 +218,14 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { stack->set_sp(stack->sp() + method->max_locals()); // Push our result - for (int i = 0; i < result_slots; i++) - stack->push(result[-i]); + for (int i = 0; i < result_slots; i++) { + // Adjust result to smaller + intptr_t res = result[-i]; + if (result_slots == 1) { + res = narrow(result_type_of(method), res); + } + stack->push(res); + } } int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { @@ -532,6 +561,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0); break; @@ -570,6 +600,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0); break; diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index c4a084a4518..2b01e3ae04c 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -305,7 +305,8 @@ void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), - x->elt_type(), value, x->state_before())); + x->elt_type(), value, x->state_before(), + x->check_boolean())); return; } } diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 172e26eb4d9..7eacc2c952d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -976,7 +976,19 @@ void GraphBuilder::store_indexed(BasicType type) { (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { length = append(new ArrayLength(array, state_before)); } - StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); + ciType* array_type = array->declared_type(); + bool check_boolean = false; + if (array_type != NULL) { + if (array_type->is_loaded() && + array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) { + assert(type == T_BYTE, "boolean store uses bastore"); + Value mask = append(new Constant(new IntConstant(1))); + value = append(new LogicOp(Bytecodes::_iand, value, mask)); + } + } else if (type == T_BYTE) { + check_boolean = true; + } + StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean); append(result); _memory->store_value(value); @@ -1443,6 +1455,36 @@ void GraphBuilder::method_return(Value x) { need_mem_bar = true; } + BasicType bt = method()->return_type()->basic_type(); + switch (bt) { + case T_BYTE: + { + Value shift = append(new Constant(new IntConstant(24))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_SHORT: + { + Value shift = append(new Constant(new IntConstant(16))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_CHAR: + { + Value mask = append(new Constant(new IntConstant(0xFFFF))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + case T_BOOLEAN: + { + Value mask = append(new Constant(new IntConstant(1))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + } + // Check to see whether we are inlining. If so, Return // instructions become Gotos to the continuation point. if (continuation() != NULL) { @@ -1611,6 +1653,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); break; } @@ -1672,6 +1718,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching); if (!needs_patching) store = _memory->store(store); if (store != NULL) { @@ -4134,7 +4184,12 @@ void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_ #ifndef _LP64 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); #endif - Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); + Value val = args->at(3); + if (t == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } + Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, val, is_volatile)); compilation()->set_has_unsafe_access(true); kill_all(); } @@ -4208,7 +4263,7 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { Value index = args->at(1); if (is_store) { Value value = args->at(2); - Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before)); + Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before, false)); store->set_flag(Instruction::NeedsRangeCheckFlag, false); _memory->store_value(value); } else { diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 8f6bf233f3d..38fcc56ae75 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -974,11 +974,13 @@ LEAF(StoreIndexed, AccessIndexed) ciMethod* _profiled_method; int _profiled_bci; + bool _check_boolean; + public: // creation - StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before) + StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before, bool check_boolean) : AccessIndexed(array, index, length, elt_type, state_before) - , _value(value), _profiled_method(NULL), _profiled_bci(0) + , _value(value), _profiled_method(NULL), _profiled_bci(0), _check_boolean(check_boolean) { set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object())); set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object())); @@ -990,6 +992,7 @@ LEAF(StoreIndexed, AccessIndexed) Value value() const { return _value; } bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } + bool check_boolean() const { return _check_boolean; } // Helpers for MethodData* profiling void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } void set_profiled_method(ciMethod* method) { _profiled_method = method; } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 3c8454e5260..956bb657ed6 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3680,3 +3680,26 @@ void LIRGenerator::do_MemBar(MemBar* x) { } } } + +LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) { + if (x->check_boolean()) { + LIR_Opr value_fixed = rlock_byte(T_BYTE); + if (TwoOperandLIRForm) { + __ move(value, value_fixed); + __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed); + } else { + __ logical_and(value, LIR_OprFact::intConst(1), value_fixed); + } + LIR_Opr klass = new_register(T_METADATA); + __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info); + null_check_info = NULL; + LIR_Opr layout = new_register(T_INT); + __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout); + __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE); + value = value_fixed; + } + return value; +} diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index bf36d7dc10e..6885ff6186c 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -448,6 +448,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void profile_arguments(ProfileCall* x); void profile_parameters(Base* x); void profile_parameters_at_call(ProfileCall* x); + LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info); public: Compilation* compilation() const { return _compilation; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index cedf1b48509..5a735d525e5 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2713,11 +2713,9 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, m->set_constants(_cp); m->set_name_index(name_index); m->set_signature_index(signature_index); -#ifdef CC_INTERP - // hmm is there a gc issue here?? + ResultTypeFinder rtf(cp->symbol_at(signature_index)); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); if (args_size >= 0) { m->set_size_of_parameters(args_size); diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index 65d546e249c..1b8cf3084ed 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -860,10 +860,8 @@ static Method* new_method( m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); m->set_signature_index(cp->utf8(sig)); -#ifdef CC_INTERP ResultTypeFinder rtf(sig); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->set_size_of_parameters(params); m->set_max_stack(max_stack); m->set_max_locals(params); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index dbe5355b1df..2b42fab10b9 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1767,8 +1767,19 @@ run: ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } - CASE(_bastore): - ARRAY_STOREFROM32(T_BYTE, jbyte, "%d", STACK_INT, 0); + CASE(_bastore): { + ARRAY_INTRO(-3); + int item = STACK_INT(-1); + // if it is a T_BOOLEAN array, mask the stored value to 0/1 + if (arrObj->klass() == Universe::boolArrayKlassObj()) { + item &= 1; + } else { + assert(arrObj->klass() == Universe::byteArrayKlassObj(), + "should be byte array otherwise"); + } + ((typeArrayOop)arrObj)->byte_at_put(index, item); + UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); + } CASE(_castore): ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0); CASE(_sastore): @@ -1999,7 +2010,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field_acquire(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field_acquire(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field_acquire(field_offset), -1); @@ -2020,7 +2031,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field(field_offset), -1); @@ -2109,6 +2120,9 @@ run: obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->release_byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->release_long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { @@ -2129,6 +2143,9 @@ run: obj->obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index 78ef212d9bf..863c85fae63 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -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 @@ -496,6 +496,7 @@ void Bytecodes::initialize() { def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield ); diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 4f52e7b4a1a..86e88d4b516 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -257,6 +257,7 @@ class Bytecodes: AllStatic { _fast_aputfield , _fast_bputfield , + _fast_zputfield , _fast_cputfield , _fast_dputfield , _fast_fputfield , diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 27fed0c33f2..cd1d88926aa 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1077,7 +1077,8 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, char sig_type = '\0'; switch(cp_entry->flag_state()) { - case btos: sig_type = 'Z'; break; + case btos: sig_type = 'B'; break; + case ztos: sig_type = 'Z'; break; case ctos: sig_type = 'C'; break; case stos: sig_type = 'S'; break; case itos: sig_type = 'I'; break; diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index a059bd5871f..8b368a12d79 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -89,8 +89,9 @@ void TemplateInterpreter::initialize() { // Implementation of EntryPoint EntryPoint::EntryPoint() { - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _entry[btos] = NULL; + _entry[ztos] = NULL; _entry[ctos] = NULL; _entry[stos] = NULL; _entry[atos] = NULL; @@ -102,9 +103,10 @@ EntryPoint::EntryPoint() { } -EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { - assert(number_of_states == 9, "check the code below"); +EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { + assert(number_of_states == 10, "check the code below"); _entry[btos] = bentry; + _entry[ztos] = zentry; _entry[ctos] = centry; _entry[stos] = sentry; _entry[atos] = aentry; @@ -155,6 +157,7 @@ EntryPoint DispatchTable::entry(int i) const { return EntryPoint( _table[btos][i], + _table[ztos][i], _table[ctos][i], _table[stos][i], _table[atos][i], @@ -169,8 +172,9 @@ EntryPoint DispatchTable::entry(int i) const { void DispatchTable::set_entry(int i, EntryPoint& entry) { assert(0 <= i && i < length, "index out of bounds"); - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _table[btos][i] = entry.entry(btos); + _table[ztos][i] = entry.entry(ztos); _table[ctos][i] = entry.entry(ctos); _table[stos][i] = entry.entry(stos); _table[atos][i] = entry.entry(atos); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp index 1955cae20cb..f9d008d5c92 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp @@ -47,7 +47,7 @@ class EntryPoint VALUE_OBJ_CLASS_SPEC { public: // Construction EntryPoint(); - EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); + EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); // Attributes address entry(TosState state) const; // return target address for a given tosca state diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index a10981c48af..a2c427f4aa8 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -74,6 +74,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_trace_code = EntryPoint( generate_trace_code(btos), + generate_trace_code(ztos), generate_trace_code(ctos), generate_trace_code(stos), generate_trace_code(atos), @@ -94,6 +95,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), generate_return_entry_for(atos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(ltos, i, index_size), @@ -105,13 +107,16 @@ void TemplateInterpreterGenerator::generate_all() { } { CodeletMark cm(_masm, "invoke return entry points"); - const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + // These states are in order specified in TosState, except btos/ztos/ctos/stos are + // really the same as itos since there is no top of stack optimization for these types + const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl}; const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { TosState state = states[i]; + assert(state != ilgl, "states array is wrong above"); Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); @@ -122,6 +127,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_earlyret_entry = EntryPoint( generate_earlyret_entry_for(btos), + generate_earlyret_entry_for(ztos), generate_earlyret_entry_for(ctos), generate_earlyret_entry_for(stos), generate_earlyret_entry_for(atos), @@ -140,6 +146,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), generate_deopt_entry_for(atos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(ltos, i), @@ -167,6 +174,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_continuation_entry = EntryPoint( generate_continuation_for(btos), + generate_continuation_for(ztos), generate_continuation_for(ctos), generate_continuation_for(stos), generate_continuation_for(atos), @@ -182,6 +190,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_safept_entry = EntryPoint( generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), @@ -301,7 +310,7 @@ void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { void TemplateInterpreterGenerator::set_unimplemented(int i) { address e = _unimplemented_bytecode; - EntryPoint entry(e, e, e, e, e, e, e, e, e); + EntryPoint entry(e, e, e, e, e, e, e, e, e, e); Interpreter::_normal_table.set_entry(i, entry); Interpreter::_wentry_point[i] = _unimplemented_bytecode; } @@ -316,6 +325,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { assert(_unimplemented_bytecode != NULL, "should have been generated before"); assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); address bep = _illegal_bytecode_sequence; + address zep = _illegal_bytecode_sequence; address cep = _illegal_bytecode_sequence; address sep = _illegal_bytecode_sequence; address aep = _illegal_bytecode_sequence; @@ -337,7 +347,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { set_wide_entry_point(t, wep); } // set entry points - EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); + EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep); Interpreter::_normal_table.set_entry(code, entry); Interpreter::_wentry_point[code] = wep; CodeCacheExtensions::completed_template_interpreter_entries(_masm, code); @@ -355,6 +365,7 @@ void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& assert(t->is_valid(), "template must exist"); switch (t->tos_in()) { case btos: + case ztos: case ctos: case stos: ShouldNotReachHere(); // btos/ctos/stos should use itos. diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp index ebca67320bd..4672a1ee4eb 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.cpp +++ b/hotspot/src/share/vm/interpreter/templateTable.cpp @@ -488,6 +488,7 @@ void TemplateTable::initialize() { def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos ); def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); + def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos ); def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos ); diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 5ffc8e03e81..8de67525a27 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -66,6 +66,7 @@ ConstMethod::ConstMethod(int byte_code_size, set_max_locals(0); set_method_idnum(0); set_size_of_parameters(0); + set_result_type(T_VOID); } // Accessor that copies to metadata. diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 01df3b1a3d8..7f63d9e2b38 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -210,6 +210,7 @@ private: int _constMethod_size; u2 _flags; + u1 _result_type; // BasicType of result // Size of Java bytecodes allocated immediately after Method*. u2 _code_size; @@ -494,6 +495,8 @@ public: static ByteSize size_of_parameters_offset() { return byte_offset_of(ConstMethod, _size_of_parameters); } + static ByteSize result_type_offset() + { return byte_offset_of(ConstMethod, _result_type); } // Unique id for the method static const u2 MAX_IDNUM; @@ -516,6 +519,8 @@ public: int size_of_parameters() const { return _size_of_parameters; } void set_size_of_parameters(int size) { _size_of_parameters = size; } + void set_result_type(BasicType rt) { assert(rt < 16, "result type too large"); + _result_type = (u1)rt; } // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; } diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index 33828d52f6a..840177a10cd 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -77,18 +77,19 @@ class PSPromotionManager; // f2 flag true if f2 contains an oop (e.g., virtual final method) // fv flag true if invokeinterface used for method in class Object // -// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the +// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 16 with the // following mapping to the TosState states: // // btos: 0 -// ctos: 1 -// stos: 2 -// itos: 3 -// ltos: 4 -// ftos: 5 -// dtos: 6 -// atos: 7 -// vtos: 8 +// ztos: 1 +// ctos: 2 +// stos: 3 +// itos: 4 +// ltos: 5 +// ftos: 6 +// dtos: 7 +// atos: 8 +// vtos: 9 // // Entry specific: field entries: // _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index @@ -352,14 +353,8 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } - bool is_byte() const { return flag_state() == btos; } - bool is_char() const { return flag_state() == ctos; } - bool is_short() const { return flag_state() == stos; } - bool is_int() const { return flag_state() == itos; } bool is_long() const { return flag_state() == ltos; } - bool is_float() const { return flag_state() == ftos; } bool is_double() const { return flag_state() == dtos; } - bool is_object() const { return flag_state() == atos; } TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index cff1d74d6ef..14675aa81ee 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -342,6 +342,21 @@ protected: assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity"); return (BasicType) btvalue; } + + // Want a pattern to quickly diff against layout header in register + // find something less clever! + static int layout_helper_boolean_diffbit() { + jint zlh = array_layout_helper(T_BOOLEAN); + jint blh = array_layout_helper(T_BYTE); + assert(zlh != blh, "array layout helpers must differ"); + int diffbit = 1; + while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) { + diffbit <<= 1; + assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE"); + } + return diffbit; + } + static int layout_helper_log2_element_size(jint lh) { assert(lh < (jint)_lh_neutral_value, "must be array"); int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index b3f2b868b64..d6fe27a1c93 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1220,10 +1220,8 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, m->set_signature_index(_imcp_invoke_signature); assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(m->signature() == signature, ""); -#ifdef CC_INTERP ResultTypeFinder rtf(signature); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->compute_size_of_parameters(THREAD); m->init_intrinsic_id(); assert(m->is_method_handle_intrinsic(), ""); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 5f896346986..c3072a1b21c 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -443,7 +443,7 @@ jchar oopDesc::char_field(int offset) const { return (jchar) * void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } -void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; } +void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (((jint) contents) & 1); } jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); } void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; } @@ -483,7 +483,7 @@ jchar oopDesc::char_field_acquire(int offset) const { return O void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } -void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); } +void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), (contents & 1)); } jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); } void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); } diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index d6b3c9394ad..5580c7901d4 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -2389,7 +2389,7 @@ StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const ctl != NULL, "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: + case T_BOOLEAN: val = gvn.transform(new AndINode(val, gvn.intcon(0x1))); // Fall through to T_BYTE case case T_BYTE: return new StoreBNode(ctl, mem, adr, adr_type, val, mo); case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 833f0a66add..22b3e27292e 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -730,6 +730,26 @@ void Parse::do_all_blocks() { #endif } +static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) { + switch (bt) { + case T_BYTE: + v = gvn->transform(new LShiftINode(v, gvn->intcon(24))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(24))); + break; + case T_SHORT: + v = gvn->transform(new LShiftINode(v, gvn->intcon(16))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(16))); + break; + case T_CHAR: + v = gvn->transform(new AndINode(v, gvn->intcon(0xFFFF))); + break; + case T_BOOLEAN: + v = gvn->transform(new AndINode(v, gvn->intcon(0x1))); + break; + } + return v; +} + //-------------------------------build_exits---------------------------------- // Build normal and exceptional exit merge points. void Parse::build_exits() { @@ -754,6 +774,16 @@ void Parse::build_exits() { // Add a return value to the exit state. (Do not push it yet.) if (tf()->range()->cnt() > TypeFunc::Parms) { const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + if (ret_bt == T_BOOLEAN || + ret_bt == T_CHAR || + ret_bt == T_BYTE || + ret_bt == T_SHORT) { + ret_type = TypeInt::INT; + } + } + // Don't "bind" an unloaded return klass to the ret_phi. If the klass // becomes loaded during the subsequent parsing, the loaded and unloaded // types will not join when we transform and push in do_exits(). @@ -1014,6 +1044,10 @@ void Parse::do_exits() { } return; } + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn); + } _exits.push_node(ret_type->basic_type(), ret_phi); } diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 6c0c2bec44f..c8553ce798b 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -64,11 +64,15 @@ void Parse::array_load(BasicType elem_type) { //--------------------------------array_store---------------------------------- void Parse::array_store(BasicType elem_type) { - Node* adr = array_addressing(elem_type, 1); + const Type* elem = Type::TOP; + Node* adr = array_addressing(elem_type, 1, &elem); if (stopped()) return; // guaranteed null or range check Node* val = pop(); dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); + if (elem == TypeInt::BOOL) { + elem_type = T_BOOLEAN; + } store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 42b290bd29e..babc67b2433 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1820,14 +1820,16 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig) break; case T_OBJECT: case T_ARRAY: - case T_BOOLEAN: - case T_CHAR: case T_FLOAT: - case T_BYTE: - case T_SHORT: case T_INT: field_array[pos++] = get_const_type(type); break; + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + field_array[pos++] = TypeInt::INT; + break; default: ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 80dc866f136..2f9b49359c5 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -2188,6 +2188,7 @@ JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID field_value.unionType = value; \ o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ o->Fieldname##_field_put(offset, value); \ ReturnProbe; \ JNI_END @@ -2387,6 +2388,7 @@ JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID field_value.unionType = value; \ JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ ReturnProbe;\ JNI_END diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 96ee3a19adb..dd241a014d7 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1354,7 +1354,7 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa ResultTypeFinder rtf(signature); TosState fr_tos = as_TosState(rtf.type()); if (fr_tos != tos) { - if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) { + if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) { return JVMTI_ERROR_TYPE_MISMATCH; } } diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 20de3f979cb..324d297e649 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1702,7 +1702,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { - if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') { + if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. // determine which it really is, and convert fieldDescriptor fd; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index f951f694f1d..72226385d3e 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -133,13 +133,22 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { ///// Data in the Java heap. +#define truncate_jboolean(x) ((x) & 1) +#define truncate_jbyte(x) (x) +#define truncate_jshort(x) (x) +#define truncate_jchar(x) (x) +#define truncate_jint(x) (x) +#define truncate_jlong(x) (x) +#define truncate_jfloat(x) (x) +#define truncate_jdouble(x) (x) + #define GET_FIELD(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset) #define SET_FIELD(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - *(type_name*)index_oop_from_field_offset_long(p, offset) = x + *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x) #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ @@ -150,7 +159,7 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); + OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x)); // Get/SetObject must be special-cased, since it works with handles. diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 1832711848b..625d55830de 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -1025,7 +1025,7 @@ static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) { static void narrow(jvalue* value, BasicType narrow_type, TRAPS) { switch (narrow_type) { case T_BOOLEAN: - value->z = (jboolean)value->i; + value->z = (jboolean) (value->i & 1); return; case T_BYTE: value->b = (jbyte)value->i; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3c04e2a0f54..fde654f1cf5 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -846,14 +846,15 @@ class JavaValue { enum TosState { // describes the tos cache contents btos = 0, // byte, bool tos cached - ctos = 1, // char tos cached - stos = 2, // short tos cached - itos = 3, // int tos cached - ltos = 4, // long tos cached - ftos = 5, // float tos cached - dtos = 6, // double tos cached - atos = 7, // object cached - vtos = 8, // tos not cached + ztos = 1, // byte, bool tos cached + ctos = 2, // char tos cached + stos = 3, // short tos cached + itos = 4, // int tos cached + ltos = 5, // long tos cached + ftos = 6, // float tos cached + dtos = 7, // double tos cached + atos = 8, // object cached + vtos = 9, // tos not cached number_of_states, ilgl // illegal state: should not occur }; @@ -862,7 +863,7 @@ enum TosState { // describes the tos cache contents inline TosState as_TosState(BasicType type) { switch (type) { case T_BYTE : return btos; - case T_BOOLEAN: return btos; // FIXME: Add ztos + case T_BOOLEAN: return ztos; case T_CHAR : return ctos; case T_SHORT : return stos; case T_INT : return itos; @@ -878,8 +879,8 @@ inline TosState as_TosState(BasicType type) { inline BasicType as_BasicType(TosState state) { switch (state) { - //case ztos: return T_BOOLEAN;//FIXME case btos : return T_BYTE; + case ztos : return T_BOOLEAN; case ctos : return T_CHAR; case stos : return T_SHORT; case itos : return T_INT; From 46cb32012acde827d2924895083a4cfada9864db Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 7 Jan 2016 13:59:49 -0500 Subject: [PATCH 002/113] 8146518: Zero interpreter broken with better byte behaviours Replaced Method::_result_type_index with Method::_result_type for better byte behaviours should be used for Zero also. Reviewed-by: roland, kvn, bdelsart, kevinw --- hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp | 7 ++++--- hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp | 6 +----- hotspot/src/share/vm/oops/method.cpp | 9 --------- hotspot/src/share/vm/oops/method.hpp | 12 ------------ 4 files changed, 5 insertions(+), 29 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 48143d50e72..43b45fad16a 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -94,6 +94,7 @@ intptr_t narrow(BasicType type, intptr_t result) { case T_SHORT: return (intptr_t)(jshort)result; case T_OBJECT: // nothing to do fall through + case T_ARRAY: case T_LONG: case T_INT: case T_FLOAT: @@ -184,7 +185,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[result_type_of(method)]; + result_slots = type2size[method->result_type()]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -222,7 +223,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { // Adjust result to smaller intptr_t res = result[-i]; if (result_slots == 1) { - res = narrow(result_type_of(method), res); + res = narrow(method->result_type(), res); } stack->push(res); } @@ -436,7 +437,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // Push our result if (!HAS_PENDING_EXCEPTION) { - BasicType type = result_type_of(method); + BasicType type = method->result_type(); stack->set_sp(stack->sp() - type2size[type]); switch (type) { diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp index 3a6bd52f2cb..9c0a2a01091 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -49,8 +49,4 @@ static intptr_t* calculate_unwind_sp(ZeroStack* stack, oop method_handle); static void throw_exception(JavaThread* thread, Symbol* name,char *msg=NULL); - private: - // Fast result type determination - static BasicType result_type_of(Method* method); - #endif // CPU_ZERO_VM_CPPINTERPRETER_ZERO_HPP diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index d6fe27a1c93..3491bda1c69 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -84,9 +84,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) { NoSafepointVerifier no_safepoint; set_constMethod(xconst); set_access_flags(access_flags); -#ifdef CC_INTERP - set_result_index(T_VOID); -#endif set_intrinsic_id(vmIntrinsics::_none); set_jfr_towrite(false); set_force_inline(false); @@ -445,12 +442,6 @@ void Method::compute_size_of_parameters(Thread *thread) { set_size_of_parameters(asc.size() + (is_static() ? 0 : 1)); } -#ifdef CC_INTERP -void Method::set_result_index(BasicType type) { - _result_index = Interpreter::BasicType_as_index(type); -} -#endif - BasicType Method::result_type() const { ResultTypeFinder rtf(signature()); return rtf.type(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index a1acd932cea..264a07db004 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -69,9 +69,6 @@ class Method : public Metadata { AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) // note: can have vtables with >2**16 elements (because of inheritance) -#ifdef CC_INTERP - int _result_index; // C++ interpreter needs for converting results to/from stack -#endif u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) // Flags @@ -171,11 +168,6 @@ class Method : public Metadata { return constMethod()->type_annotations(); } -#ifdef CC_INTERP - void set_result_index(BasicType type); - int result_index() { return _result_index; } -#endif - // Helper routine: get klass name + "." + method name + signature as // C string, for the purpose of providing more useful NoSuchMethodErrors // and fatal error handling. The string is allocated in resource @@ -552,7 +544,6 @@ class Method : public Metadata { void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments) Symbol* klass_name() const; // returns the name of the method holder BasicType result_type() const; // type of the method result - int result_type_index() const; // type index of the method result bool is_returning_oop() const { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); } bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); } @@ -653,9 +644,6 @@ class Method : public Metadata { // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } static ByteSize access_flags_offset() { return byte_offset_of(Method, _access_flags ); } -#ifdef CC_INTERP - static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); } -#endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } static ByteSize method_data_offset() { From 9105842337913b9b8e5922b1195efe050459b194 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 8 Feb 2016 12:54:57 +0000 Subject: [PATCH 003/113] 8148475: Missing SA Bytecode updates Reviewed-by: coleenp --- .../jvm/hotspot/interpreter/Bytecodes.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java index 3f09ee30c19..8f51fb8cb8b 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,29 +253,30 @@ public class Bytecodes { public static final int _fast_sgetfield = 210; public static final int _fast_aputfield = 211; public static final int _fast_bputfield = 212; - public static final int _fast_cputfield = 213; - public static final int _fast_dputfield = 214; - public static final int _fast_fputfield = 215; - public static final int _fast_iputfield = 216; - public static final int _fast_lputfield = 217; - public static final int _fast_sputfield = 218; - public static final int _fast_aload_0 = 219; - public static final int _fast_iaccess_0 = 220; - public static final int _fast_aaccess_0 = 221; - public static final int _fast_faccess_0 = 222; - public static final int _fast_iload = 223; - public static final int _fast_iload2 = 224; - public static final int _fast_icaload = 225; - public static final int _fast_invokevfinal = 226; - public static final int _fast_linearswitch = 227; - public static final int _fast_binaryswitch = 228; - public static final int _fast_aldc = 229; - public static final int _fast_aldc_w = 230; - public static final int _return_register_finalizer = 231; - public static final int _invokehandle = 232; - public static final int _shouldnotreachhere = 233; // For debugging + public static final int _fast_zputfield = 213; + public static final int _fast_cputfield = 214; + public static final int _fast_dputfield = 215; + public static final int _fast_fputfield = 216; + public static final int _fast_iputfield = 217; + public static final int _fast_lputfield = 218; + public static final int _fast_sputfield = 219; + public static final int _fast_aload_0 = 220; + public static final int _fast_iaccess_0 = 221; + public static final int _fast_aaccess_0 = 222; + public static final int _fast_faccess_0 = 223; + public static final int _fast_iload = 224; + public static final int _fast_iload2 = 225; + public static final int _fast_icaload = 226; + public static final int _fast_invokevfinal = 227; + public static final int _fast_linearswitch = 228; + public static final int _fast_binaryswitch = 229; + public static final int _fast_aldc = 230; + public static final int _fast_aldc_w = 231; + public static final int _return_register_finalizer = 232; + public static final int _invokehandle = 233; + public static final int _shouldnotreachhere = 234; // For debugging - public static final int number_of_codes = 234; + public static final int number_of_codes = 235; // Flag bits derived from format strings, can_trap, can_rewrite, etc.: // semantic flags: @@ -776,6 +777,7 @@ public class Bytecodes { def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield ); From ea91682fe1e6b041f366466b5f3445ad8e141dc6 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 9 Feb 2016 15:54:16 -0500 Subject: [PATCH 004/113] 8149170: Better byte behavior should normalize JNI arguments Arguments coming from native should be converted to 0=false, 1-255=true Reviewed-by: kvn, kevinw, jrose, bdelsart, gtriantafill --- hotspot/make/test/JtregNative.gmk | 3 +- hotspot/src/share/vm/prims/jni.cpp | 26 +++++++- .../runtime/BoolReturn/BoolConstructor.java | 35 +++++++++++ .../BoolReturn/NativeSmallIntCallsTest.java | 60 +++++++++++++++++++ .../BoolReturn/libNativeSmallIntCalls.c | 57 ++++++++++++++++++ 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 hotspot/test/runtime/BoolReturn/BoolConstructor.java create mode 100644 hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java create mode 100644 hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 95c6bf242b7..62478ce6923 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \ $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ + $(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ $(HOTSPOT_TOPDIR)/test/compiler/native \ diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 2f9b49359c5..8c1a020ac0f 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -919,7 +919,14 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { protected: va_list _ap; - inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = va_arg(_ap, jint); + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg @@ -960,9 +967,17 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { while ( 1 ) { switch ( fingerprint & parameter_feature_mask ) { case bool_parm: + get_bool(); + break; case char_parm: + get_char(); + break; case short_parm: + get_short(); + break; case byte_parm: + get_byte(); + break; case int_parm: get_int(); break; @@ -996,7 +1011,14 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher { protected: const jvalue *_ap; - inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); } + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = (_ap++)->z; + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int((jint)(_ap++)->c); } inline void get_short() { _arguments->push_int((jint)(_ap++)->s); } inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); } diff --git a/hotspot/test/runtime/BoolReturn/BoolConstructor.java b/hotspot/test/runtime/BoolReturn/BoolConstructor.java new file mode 100644 index 00000000000..c870a4e6366 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/BoolConstructor.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; + +public class BoolConstructor { + + boolean field; + BoolConstructor(boolean b, boolean expected) { + field = b; + // System.out.println("b is " + b + " field is " + field); + Asserts.assertTrue(field == b, "BoolConstructor argument not converted correctly"); + Asserts.assertTrue(field == expected, "BoolConstructor argument not stored correctly"); + } +} diff --git a/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java new file mode 100644 index 00000000000..d911435382a --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8149170 + * @summary Test native functions return booleans as 0/1 but differently than java functions + * @library /testlibrary + * @compile BoolConstructor.java + * @run main/native NativeSmallIntCallsTest + */ + +// This test shows that returns from native calls for boolean truncate to JNI_TRUE if value != 0 +// and JNI_FALSE if value returned is 0. + +import jdk.test.lib.Asserts; + +public class NativeSmallIntCallsTest { + static native boolean nativeCastToBoolCallTrue(); + static native boolean nativeCastToBoolCallFalse(); + static native boolean nativeCallBoolConstructor(int visible, boolean expected); + static { + System.loadLibrary("NativeSmallIntCalls"); + } + + public static void main(java.lang.String[] unused) throws Exception { + // Call through jni + // JNI makes all results != 0 true for compatibility + boolean nativeTrueVal = nativeCastToBoolCallTrue(); + Asserts.assertTrue(nativeTrueVal, "trueval is false!"); + + boolean nativeFalseVal = nativeCastToBoolCallFalse(); + Asserts.assertTrue(nativeFalseVal, "falseval is false in native!"); + + // Call a constructor or method that passes jboolean values into Java from native + nativeCallBoolConstructor(1, true); + nativeCallBoolConstructor(0x10, true); + nativeCallBoolConstructor(0x100, false); + nativeCallBoolConstructor(0x1000, false); + } +} diff --git a/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c new file mode 100644 index 00000000000..acf09ac41f8 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT void JNICALL +Java_NativeSmallIntCallsTest_nativeCallBoolConstructor(JNIEnv* env, jobject obj, int visible, int expected) { + jclass cls; + jmethodID ctor; + + cls = (*env)->FindClass(env, "BoolConstructor"); + if(NULL == cls) { + return; + } + + ctor = (*env)->GetMethodID(env, cls, "", "(ZZ)V"); + if(NULL == ctor) { + return; + } + + // printf("visible 0x%x expected %d\n", visible, expected); + + (*env)->NewObject(env, cls, ctor, (jboolean) visible, expected); +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallTrue(JNIEnv* env, jobject obj) { + + return 55; +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallFalse(JNIEnv* env, jobject obj) { + + return 44; +} + From f1b44959119f484f6744b9a53984656560ea74c8 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sat, 20 Feb 2016 14:11:18 -0800 Subject: [PATCH 005/113] 8149367: PolicyQualifierInfo/index_Ctor JCk test fails with IOE: Invalid encoding for PolicyQualifierInfo Fix incorrect code Reviewed-by: jrose, coleenp, kevinw --- .../src/share/vm/runtime/deoptimization.cpp | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 9c038d74c48..d380bf6d518 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -896,13 +896,25 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_at_put(index, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_at_put(index, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_at_put(index, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_at_put(index, (jboolean)*((jint*)&val)); @@ -1017,13 +1029,25 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_field_put(offset, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_field_put(offset, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_field_put(offset, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_field_put(offset, (jboolean)*((jint*)&val)); From c606f158a9cf51e4ddc4703f0c0b79a0584c912c Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Sun, 21 Feb 2016 08:33:59 -0500 Subject: [PATCH 006/113] 8150012: Better byte behavior for reflection Reviewed-by: kvn, jrose, kevinw, ahgross --- hotspot/src/share/vm/oops/typeArrayOop.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index 8ab2f4d1f74..adf99a30fe4 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -96,7 +96,7 @@ class typeArrayOopDesc : public arrayOopDesc { void byte_at_put(int which, jbyte contents) { *byte_at_addr(which) = contents; } jboolean bool_at(int which) const { return *bool_at_addr(which); } - void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = contents; } + void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = (((jint)contents) & 1); } jchar char_at(int which) const { return *char_at_addr(which); } void char_at_put(int which, jchar contents) { *char_at_addr(which) = contents; } From 43e034bc512d81cb6c31ab4d9afc711034ccde71 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 25 Feb 2016 21:45:26 +0000 Subject: [PATCH 007/113] 8150654: Zero cleanup of CppInterpreter::result_type_of() Reviewed-by: coleenp --- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 43b45fad16a..e05e6d65bc0 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -804,26 +804,6 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { return (InterpreterFrame *) fp; } -BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t = T_ILLEGAL; // silence compiler warnings - switch (method->result_index()) { - case 0 : t = T_BOOLEAN; break; - case 1 : t = T_CHAR; break; - case 2 : t = T_BYTE; break; - case 3 : t = T_SHORT; break; - case 4 : t = T_INT; break; - case 5 : t = T_LONG; break; - case 6 : t = T_VOID; break; - case 7 : t = T_FLOAT; break; - case 8 : t = T_DOUBLE; break; - case 9 : t = T_OBJECT; break; - default: ShouldNotReachHere(); - } - assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), - "out of step with AbstractInterpreter::BasicType_as_index"); - return t; -} - address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { ShouldNotCallThis(); return NULL; From 183d5aad2e36238fdc92148cbed0125b5ae7f63a Mon Sep 17 00:00:00 2001 From: Nadeesh TV Date: Thu, 21 Apr 2016 17:51:18 +0000 Subject: [PATCH 008/113] 8154050: java.time.format.DateTimeFormatter can't parse localized zone-offset Corrected the mistake in calculating parse end position Reviewed-by: rriggs, scolebourne --- .../time/format/DateTimeFormatterBuilder.java | 18 +++----- .../TCKLocalizedOffsetIdPrinterParser.java | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index d7baf69c5b5..c77a8c5f888 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1539,8 +1539,8 @@ public final class DateTimeFormatterBuilder { *
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffsetPrefixed(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffsetPrefixed(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT);
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL);
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -3519,9 +3519,7 @@ public final class DateTimeFormatterBuilder {
                 return false;
             }
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                buf.append(gmtText);
-            }
+            buf.append(gmtText);
             int totalSecs = Math.toIntExact(offsetSecs);
             if (totalSecs != 0) {
                 int absHours = Math.abs((totalSecs / 3600) % 100);  // anything larger than 99 silently dropped
@@ -3565,14 +3563,12 @@ public final class DateTimeFormatterBuilder {
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int pos = position;
-            int end = pos + text.length();
+            int end = text.length();
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
+            if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
                     return ~position;
                 }
-                pos += gmtText.length();
-            }
+            pos += gmtText.length();
             // parse normal plus/minus offset
             int negative = 0;
             if (pos == end) {
diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
new file mode 100644
index 00000000000..d0a1f189e92
--- /dev/null
+++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tck.java.time.format;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test localized behavior of formatter.
+ */
+@Test
+public class TCKLocalizedOffsetIdPrinterParser {
+    @Test
+    public void test_localized_offset_parse() {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O")
+                                                       .withLocale(Locale.ENGLISH);
+        String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC));
+        formatter.parse(date) ;
+     }
+}

From 40263e2a3452c165a67024165c98057a277e1ff8 Mon Sep 17 00:00:00 2001
From: Lana Steuck 
Date: Thu, 21 Apr 2016 12:57:11 -0700
Subject: [PATCH 009/113] Added tag jdk-9+115 for changeset 3414aeff4a80

---
 jdk/.hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/jdk/.hgtags b/jdk/.hgtags
index e9974a728e5..74ad9bf9055 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -357,3 +357,4 @@ b2a69d66dc65ad1d3aeb3bd362cf5bb0deba040e jdk-9+111
 1565a0efe6f0ca411a6df277df1e069431c60988 jdk-9+112
 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113
 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114
+35225b837d66582037eeadeb471c13235dfd793d jdk-9+115

From ac4936ef857e31fcdbff28798e42f33e8065df64 Mon Sep 17 00:00:00 2001
From: Amy Lu 
Date: Fri, 22 Apr 2016 13:01:41 +0800
Subject: [PATCH 010/113] 8153933: Remove intermittent key from
 TimeZone/Bug6772689.java and move back to tier1

Reviewed-by: darcy
---
 jdk/test/TEST.groups                        | 2 --
 jdk/test/java/util/TimeZone/Bug6772689.java | 1 -
 2 files changed, 3 deletions(-)

diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index cf3f0abfd9d..673b0862d5c 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -32,7 +32,6 @@ tier1 = \
     -java/util/WeakHashMap/GCDuringIteration.java \
     -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
-    -java/util/TimeZone/Bug6772689.java \
     sun/nio/cs/ISO8859x.java \
     java/nio/Buffer \
     com/sun/crypto/provider/Cipher \
@@ -43,7 +42,6 @@ tier2 = \
     java/util/WeakHashMap/GCDuringIteration.java \
     java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
-    java/util/TimeZone/Bug6772689.java \
     :jdk_io \
     :jdk_nio \
     -sun/nio/cs/ISO8859x.java \
diff --git a/jdk/test/java/util/TimeZone/Bug6772689.java b/jdk/test/java/util/TimeZone/Bug6772689.java
index a1ce49682b4..f730567013d 100644
--- a/jdk/test/java/util/TimeZone/Bug6772689.java
+++ b/jdk/test/java/util/TimeZone/Bug6772689.java
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 6772689
- * @key intermittent
  * @summary Test for standard-to-daylight transitions at midnight:
  * date stays on the given day.
  */

From d9e44503b4843911e00cd3a79c3dd04f7b5c0405 Mon Sep 17 00:00:00 2001
From: Nadeesh TV 
Date: Fri, 22 Apr 2016 05:46:54 +0000
Subject: [PATCH 011/113] 8148947: DateTimeFormatter pattern letter 'g'

Handled 'g'  in the required places

Reviewed-by: rriggs, scolebourne
---
 .../java/time/format/DateTimeFormatter.java   | 11 ++--
 .../time/format/DateTimeFormatterBuilder.java | 58 ++++++++++---------
 .../java/time/temporal/JulianFields.java      | 10 +++-
 .../format/TCKDateTimeFormatterBuilder.java   | 35 ++++++++++-
 4 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
index 3478af25761..9810a088b48 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -284,6 +284,7 @@ import java.util.Set;
  *   D       day-of-year                 number            189
  *   M/L     month-of-year               number/text       7; 07; Jul; July; J
  *   d       day-of-month                number            10
+ *   g       modified-julian-day         number            2451334
  *
  *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
  *   Y       week-based-year             year              1996; 96
@@ -308,10 +309,10 @@ import java.util.Set;
  *
  *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
  *   z       time-zone name              zone-name         Pacific Standard Time; PST
- *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
- *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
- *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
- *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+ *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00
+ *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
+ *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15
+ *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00
  *
  *   p       pad next                    pad modifier      1
  *
diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index c77a8c5f888..e8ca3f1e99f 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -90,6 +90,7 @@ import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeTextProvider.LocaleStore;
 import java.time.temporal.ChronoField;
 import java.time.temporal.IsoFields;
+import java.time.temporal.JulianFields;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQueries;
@@ -1383,6 +1384,7 @@ public final class DateTimeFormatterBuilder {
      *   D       day-of-year                 number            189
      *   M/L     month-of-year               number/text       7; 07; Jul; July; J
      *   d       day-of-month                number            10
+     *   g       modified-julian-day         number            2451334
      *
      *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
      *   Y       week-based-year             year              1996; 96
@@ -1408,9 +1410,9 @@ public final class DateTimeFormatterBuilder {
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
-     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
-     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
-     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
+     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15
+     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00
      *
      *   p       pad next                    pad modifier      1
      *
@@ -1437,37 +1439,37 @@ public final class DateTimeFormatterBuilder {
      *    GGGG    4      appendText(ChronoField.ERA, TextStyle.FULL)
      *    GGGGG   5      appendText(ChronoField.ERA, TextStyle.NARROW)
      *
-     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL);
-     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000);
-     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL);
-     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD);
-     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL);
-     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000);
-     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL);
-     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD);
+     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL)
+     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000)
+     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL)
+     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD)
+     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL)
+     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000)
+     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL)
+     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD)
      *    Y       1      append special localized WeekFields element for numeric week-based-year
-     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits;
-     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL);
-     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD);
+     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits
+     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL)
+     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD)
      *
-     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    QQQ     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT)
      *    QQQQ    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL)
      *    QQQQQ   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW)
-     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    qqq     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    qqqq    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    qqqqq   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW_STANDALONE)
      *
-     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    MMM     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT)
      *    MMMM    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL)
      *    MMMMM   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW)
-     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    LLL     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    LLLL    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    LLLLL   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW_STANDALONE)
@@ -1481,6 +1483,7 @@ public final class DateTimeFormatterBuilder {
      *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2)
      *    DDD     3      appendValue(ChronoField.DAY_OF_YEAR, 3)
      *    F       1      appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)
+     *    g..g    1..n   appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL)
      *    E       1      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EE      2      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EEE     3      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
@@ -1539,8 +1542,8 @@ public final class DateTimeFormatterBuilder {
      * 
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffset(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT)
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL)
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -1554,7 +1557,7 @@ public final class DateTimeFormatterBuilder {
      *    Z       1      appendOffset("+HHMM","+0000")
      *    ZZ      2      appendOffset("+HHMM","+0000")
      *    ZZZ     3      appendOffset("+HHMM","+0000")
-     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL);
+     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL)
      *    ZZZZZ   5      appendOffset("+HH:MM:ss","Z")
      * 
*

@@ -1836,6 +1839,9 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Too many pattern letters: " + cur); } break; + case 'g': + appendValue(field, count, 19, SignStyle.NORMAL); + break; default: if (count == 1) { appendValue(field); @@ -1874,6 +1880,7 @@ public final class DateTimeFormatterBuilder { FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); // LDML FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); // 310 (proposed for LDML) FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); // 310 (proposed for LDML) + FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY); // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 // 310 - Z - matches SimpleDateFormat and LDML // 310 - V - time-zone id, matches LDML @@ -1884,7 +1891,6 @@ public final class DateTimeFormatterBuilder { // LDML - U - cycle year name, not supported by 310 yet // LDML - l - deprecated // LDML - j - not relevant - // LDML - g - modified-julian-day // LDML - v,V - extended time-zone names } diff --git a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java index 327037981eb..7fc501cb9dd 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,13 @@ public final class JulianFields { * *

Astronomical and Scientific Notes

* The standard astronomical definition uses a fraction to indicate the time-of-day, - * thus 3.25 would represent the time 18:00, since days start at midday. + * where each day is counted from midday to midday. For example, + * a fraction of 0 represents midday, a fraction of 0.25 + * represents 18:00, a fraction of 0.5 represents midnight and a fraction + * of 0.75 represents 06:00. + *

+ * By contrast, this implementation has no fractional part, and counts + * days from midnight to midnight. * This implementation uses an integer and days starting at midnight. * The integer value for the Julian Day Number is the astronomical Julian Day value at midday * of the date in question. diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 696ba8109cc..2fde35b5e2c 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -661,6 +661,8 @@ public class TCKDateTimeFormatterBuilder { {"W"}, {"W"}, + {"g"}, + {"ggggg"}, }; } @@ -761,6 +763,37 @@ public class TCKDateTimeFormatterBuilder { return LocalDate.of(y, m, d); } + //----------------------------------------------------------------------- + @DataProvider(name="modJulianFieldPattern") + Object[][] data_modJuilanFieldPattern() { + return new Object[][] { + {"g", "1"}, + {"g", "123456"}, + {"gggggg", "123456"}, + }; + } + + @Test(dataProvider="modJulianFieldPattern") + public void test_modJulianFieldPattern(String pattern, String input) throws Exception { + DateTimeFormatter.ofPattern(pattern).parse(input); + } + + @DataProvider(name="modJulianFieldValues") + Object[][] data_modJuilanFieldValues() { + return new Object[][] { + {1970, 1, 1, "40587"}, + {1858, 11, 17, "0"}, + {1858, 11, 16, "-1"}, + }; + } + + @Test(dataProvider="modJulianFieldValues") + public void test_modJulianFieldValues(int y, int m, int d, String expected) throws Exception { + DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter(); + assertEquals(LocalDate.of(y, m, d).format(df), expected); + } + + //----------------------------------------------------------------------- @Test public void test_adjacent_strict_firstFixedWidth() throws Exception { From 4cd4074db4a9d554b2e5b579292106821f7a2478 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Fri, 22 Apr 2016 17:07:54 +0800 Subject: [PATCH 012/113] 8154277: JavaDoc warnings in VirtualMachineManager.java and Pool.java Reviewed-by: alanb --- .../share/classes/com/sun/jdi/VirtualMachineManager.java | 6 +++--- .../share/classes/jdk/tools/jlink/plugin/Pool.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java index 5a6fd8b596c..58c435accf3 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java @@ -257,11 +257,11 @@ import java.io.IOException; * delegate to the {@link com.sun.jdi.connect.spi.TransportService#description() * description()} method of the underlying transport service. Both * the AttachingConnector and the ListeningConnector will have two - * Connector {@link com.sun.jdi.connect.Connector$Argument Arguments}. - * A {@link com.sun.jdi.connect.Connector$StringArgument StringArgument} + * Connector {@link com.sun.jdi.connect.Connector.Argument Arguments}. + * A {@link com.sun.jdi.connect.Connector.StringArgument StringArgument} * named {@code address} is the connector argument to specify the * address to attach too, or to listen on. A - * {@link com.sun.jdi.connect.Connector$IntegerArgument IntegerArgument} + * {@link com.sun.jdi.connect.Connector.IntegerArgument IntegerArgument} * named {@code timeout} is the connector argument to specify the * timeout when attaching, or accepting. The timeout connector may be * ignored depending on if the transport service supports an attach diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java index 3645f57c5f4..380ca41ac1a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java @@ -226,7 +226,7 @@ public abstract class Pool { *

  • For jimage content: /{module name}/{package1}/.../{packageN}/{file * name}
  • *
  • For other files (shared lib, launchers, config, ...):/{module name}/ - * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}
  • + * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name} * */ public static class ModuleData { From 741bd9b060d59f544558315041879f6a60b484bc Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 22 Apr 2016 09:27:35 +0000 Subject: [PATCH 013/113] 8144566: Custom HostnameVerifier disables SNI extension Reviewed-by: mullan, wetmore --- .../sun/security/ssl/SSLSocketImpl.java | 99 +++-- .../ServerName/BestEffortOnLazyConnected.java | 337 +++++++++++++++ .../https/HttpsURLConnection/ImpactOnSNI.java | 390 ++++++++++++++++++ 3 files changed, 802 insertions(+), 24 deletions(-) create mode 100644 jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java create mode 100644 jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 412c3ec8544..95258b2ec2b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -209,6 +209,12 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { Collection sniMatchers = Collections.emptyList(); + // Is the serverNames set to empty with SSLParameters.setServerNames()? + private boolean noSniExtension = false; + + // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()? + private boolean noSniMatcher = false; + // Configured application protocol values String[] applicationProtocols = new String[0]; @@ -642,6 +648,11 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { } super.connect(endpoint, timeout); + + if (host == null || host.length() == 0) { + useImplicitHost(false); + } + doneConnect(); } @@ -2098,41 +2109,62 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { outputRecord.setVersion(protocolVersion); } + // + // ONLY used by ClientHandshaker for the server hostname during handshaking + // synchronized String getHost() { // Note that the host may be null or empty for localhost. if (host == null || host.length() == 0) { - if (!trustNameService) { - // If the local name service is not trustworthy, reverse host - // name resolution should not be performed for endpoint - // identification. Use the application original specified - // hostname or IP address instead. - host = getOriginalHostname(getInetAddress()); - } else { - host = getInetAddress().getHostName(); - } + useImplicitHost(true); } return host; } /* - * Get the original application specified hostname. + * Try to set and use the implicit specified hostname */ - private static String getOriginalHostname(InetAddress inetAddress) { - /* - * Get the original hostname via jdk.internal.misc.SharedSecrets. - */ - JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess(); - String originalHostname = jna.getOriginalHostName(inetAddress); + private synchronized void useImplicitHost(boolean noSniUpdate) { - /* - * If no application specified hostname, use the IP address. - */ - if (originalHostname == null || originalHostname.length() == 0) { - originalHostname = inetAddress.getHostAddress(); + // Note: If the local name service is not trustworthy, reverse + // host name resolution should not be performed for endpoint + // identification. Use the application original specified + // hostname or IP address instead. + + // Get the original hostname via jdk.internal.misc.SharedSecrets + InetAddress inetAddress = getInetAddress(); + if (inetAddress == null) { // not connected + return; } - return originalHostname; + JavaNetInetAddressAccess jna = + SharedSecrets.getJavaNetInetAddressAccess(); + String originalHostname = jna.getOriginalHostName(inetAddress); + if ((originalHostname != null) && + (originalHostname.length() != 0)) { + + host = originalHostname; + if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) { + serverNames = + Utilities.addToSNIServerNameList(serverNames, host); + + if (!roleIsServer && + (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } + } + + return; + } + + // No explicitly specified hostname, no server name indication. + if (!trustNameService) { + // The local name service is not trustworthy, use IP address. + host = inetAddress.getHostAddress(); + } else { + // Use the underlying reverse host name resolution service. + host = getInetAddress().getHostName(); + } } // ONLY used by HttpsClient to setup the URI specified hostname @@ -2144,6 +2176,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { this.host = host; this.serverNames = Utilities.addToSNIServerNameList(this.serverNames, this.host); + + if (!roleIsServer && (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } } /** @@ -2533,8 +2569,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { // the super implementation does not handle the following parameters params.setEndpointIdentificationAlgorithm(identificationProtocol); params.setAlgorithmConstraints(algorithmConstraints); - params.setSNIMatchers(sniMatchers); - params.setServerNames(serverNames); + + if (sniMatchers.isEmpty() && !noSniMatcher) { + // 'null' indicates none has been set + params.setSNIMatchers(null); + } else { + params.setSNIMatchers(sniMatchers); + } + + if (serverNames.isEmpty() && !noSniExtension) { + // 'null' indicates none has been set + params.setServerNames(null); + } else { + params.setServerNames(serverNames); + } + params.setUseCipherSuitesOrder(preferLocalCipherSuites); params.setMaximumPacketSize(maximumPacketSize); params.setApplicationProtocols(applicationProtocols); @@ -2568,11 +2617,13 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { List sniNames = params.getServerNames(); if (sniNames != null) { + noSniExtension = sniNames.isEmpty(); serverNames = sniNames; } Collection matchers = params.getSNIMatchers(); if (matchers != null) { + noSniMatcher = matchers.isEmpty(); sniMatchers = matchers; } diff --git a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java new file mode 100644 index 00000000000..ba3e5f10e50 --- /dev/null +++ b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/** + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm BestEffortOnLazyConnected + */ + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.net.*; +import javax.net.ssl.*; + +public class BestEffortOnLazyConnected { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = "../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { + + sslSocket.connect(new InetSocketAddress(hostname, serverPort), 0); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } + } + + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new BestEffortOnLazyConnected(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + BestEffortOnLazyConnected() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java new file mode 100644 index 00000000000..4e0f0bdac59 --- /dev/null +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm ImpactOnSNI + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; + +public class ImpactOnSNI { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = + "../../../../../../javax/net/ssl/etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Is the connection ready to close? + */ + private static volatile boolean closeReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * Message posted + */ + private static final String postMsg = "HTTP post on a https server"; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + /* + * Accept connections + */ + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + BufferedReader br = + new BufferedReader(new InputStreamReader(sslIS)); + PrintStream ps = new PrintStream(sslOS); + + // process HTTP POST request from client + System.out.println("status line: " + br.readLine()); + String msg = null; + while ((msg = br.readLine()) != null && msg.length() > 0); + + msg = br.readLine(); + if (msg.equals(postMsg)) { + ps.println("HTTP/1.1 200 OK\n\n"); + } else { + ps.println("HTTP/1.1 500 Not OK\n\n"); + } + ps.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + + // close the socket + while (!closeReady) { + Thread.sleep(50); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + // Send HTTP POST request to server + URL url = new URL("https://" + hostname + ":" + serverPort); + + HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); + HttpsURLConnection http = (HttpsURLConnection)url.openConnection(); + http.setDoOutput(true); + + http.setRequestMethod("POST"); + PrintStream ps = new PrintStream(http.getOutputStream()); + try { + ps.println(postMsg); + ps.flush(); + if (http.getResponseCode() != 200) { + throw new RuntimeException("test Failed"); + } + } finally { + ps.close(); + http.disconnect(); + closeReady = true; + } + } + + private static class NameVerifier implements HostnameVerifier { + public boolean verify(String hostname, SSLSession session) { + return true; + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new ImpactOnSNI(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ImpactOnSNI() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} From 5b392c0abcaffb23ae12d2dbc6bdfefa3a30faf6 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 13:36:22 +0200 Subject: [PATCH 014/113] 8152667: MHs.iteratedLoop(...) throws unexpected WMTE, disallows Iterator subclasses, generates inconsistent loop result type Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 21 +++-- .../java/lang/invoke/LoopCombinatorTest.java | 83 ++++++++++++++++++- 2 files changed, 94 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 5f9fc90b54d..2b5fdfebfe9 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4572,17 +4572,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); */ public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { checkIteratedLoop(iterator, body); - final boolean voidInit = init == null || init.type().returnType() == void.class; + Class resultType = init == null ? + body == null ? void.class : body.type().returnType() : + init.type().returnType(); + boolean voidResult = resultType == void.class; + + MethodHandle initIterator; + if (iterator == null) { + MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); + initIterator = initit.asType(initit.type().changeParameterType(0, + body.type().parameterType(voidResult ? 1 : 2))); + } else { + initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class)); + } - MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); - MethodHandle initIterator = iterator == null ? - initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) : - iterator; - Class itype = initIterator.type().returnType(); Class ttype = body.type().parameterType(0); MethodHandle returnVar = - dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype); + dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class); MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext); MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype)); diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 1df672fb997..67edb08a8cd 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -28,6 +28,7 @@ * @bug 8150635 * @bug 8150956 * @bug 8150957 + * @bug 8152667 * @bug 8153637 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -400,10 +401,15 @@ public class LoopCombinatorTest { assertTrue(caught); } - @Test - public static void testIterateVoidIterator() { + @DataProvider + static Object[][] wrongIteratorTypes() { + return new Object[][]{{void.class}, {Object.class}, {Iterable.class}}; + } + + @Test(dataProvider = "wrongIteratorTypes") + public static void testIterateVoidIterator(Class it) { boolean caught = false; - MethodType v = methodType(void.class); + MethodType v = methodType(it); try { MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); } catch(IllegalArgumentException iae) { @@ -420,6 +426,77 @@ public class LoopCombinatorTest { loop.invoke(Arrays.asList("hello", "world")); } + @DataProvider + static Object[][] iterateParameters() { + MethodType i = methodType(int.class); + MethodType sil_i = methodType(int.class, String.class, int.class, List.class); + MethodType sl_v = methodType(void.class, String.class, List.class); + MethodType l_it = methodType(Iterator.class, List.class); + MethodType li_it = methodType(Iterator.class, List.class, int.class); + MethodType l_i = methodType(int.class, List.class); + MethodType _it = methodType(Iterator.class); + MethodType si_i = methodType(int.class, String.class, int.class); + MethodType s_i = methodType(int.class, String.class); + return new Object[][]{ + {null, null, sl_v}, + {null, i, sil_i}, + {null, l_i, sil_i}, + {l_it, null, sl_v}, + {l_it, i, sil_i}, + {li_it, l_i, sil_i}, + {l_it, null, sil_i}, + {li_it, null, sl_v}, + {_it, l_i, si_i}, + {_it, l_i, s_i} + }; + } + + @Test(dataProvider = "iterateParameters") + public static void testIterateParameters(MethodType it, MethodType in, MethodType bo) throws Throwable { + MethodHandle iterator = it == null ? null : MethodHandles.empty(it); + MethodHandle init = in == null ? null : MethodHandles.empty(in); + MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo)); + MethodType lt = loop.type(); + if (it == null && in == null) { + assertEquals(bo.dropParameterTypes(0, 1), lt); + } else if (it == null) { + if (in.parameterCount() == 0) { + assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt); + } else { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } + } else if (in == null) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() > in.parameterCount()) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() < in.parameterCount()) { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } else { + // both it, in present; with equal parameter list lengths + assertEquals(it.parameterList(), lt.parameterList()); + assertEquals(in.parameterList(), lt.parameterList()); + assertEquals(bo.returnType(), lt.returnType()); + } + } + + @Test + public static void testIteratorSubclass() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)), + null, MethodHandles.empty(methodType(void.class, String.class))); + assertEquals(methodType(void.class, List.class), loop.type()); + } + + static class BogusIterator implements Iterator { + @Override + public boolean hasNext() { + return false; + } + @Override + public Object next() { + return null; + } + } + static class Empty { static void f() { } From e53e280d376074035a3281aae0f466167ddcc06a Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 15:05:26 +0200 Subject: [PATCH 015/113] 8154751: MethodHandles.countedLoop does not accept empty bodies Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 12 ++++++++---- .../java/lang/invoke/LoopCombinatorTest.java | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 2b5fdfebfe9..9992483de04 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4476,12 +4476,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ? - zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class); + MethodHandle defaultResultHandle = init == null || init.type().returnType() == void.class ? + zero(void.class) : + identity(init.type().returnType()); + MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), + returnVar}; MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(body, 1, int.class), 0, + filterArgument(dropArguments(adaptedBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 67edb08a8cd..5637a9958a0 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -30,6 +30,7 @@ * @bug 8150957 * @bug 8152667 * @bug 8153637 + * @bug 8154751 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -347,6 +348,23 @@ public class LoopCombinatorTest { assertEquals(10, loop.invoke()); } + @Test + public static void testCountedLoopEmpty() throws Throwable { + // for (int i = 0; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedRangeLoopEmpty() throws Throwable { + // for (int i = -5; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, -5), + MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + @Test public static void testIterateSum() throws Throwable { // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21 From cafabcafce8227c4f8146c253b51bf4962bbbbaf Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 15:05:54 +0200 Subject: [PATCH 016/113] 8154754: MethodHandles.countedLoop errors in deriving loop arguments, result type, and local state Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 24 +++-- .../java/lang/invoke/LoopCombinatorTest.java | 88 +++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 9992483de04..6c37371a57b 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4476,16 +4476,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle defaultResultHandle = init == null || init.type().returnType() == void.class ? - zero(void.class) : - identity(init.type().returnType()); - MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + Class resultType; + MethodHandle actualInit; + if (init == null) { + resultType = body == null ? void.class : body.type().returnType(); + actualInit = empty(methodType(resultType)); + } else { + resultType = init.type().returnType(); + actualInit = init; + } + MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType); + MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); + MethodHandle actualEnd = end == null ? constant(int.class, 0) : end; MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), - returnVar}; - MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(adaptedBody, 1, int.class), 0, + MethodHandle[] loopLimit = {actualEnd, null, + MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] bodyClause = {actualInit, + filterArgument(dropArguments(actualBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 5637a9958a0..625e55c611d 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -31,6 +31,7 @@ * @bug 8152667 * @bug 8153637 * @bug 8154751 + * @bug 8154754 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -326,6 +327,74 @@ public class LoopCombinatorTest { loop.invoke(); } + @Test + public static void testCountedLoopNullBody() throws Throwable { + MethodHandle h5 = MethodHandles.constant(int.class, 5); + MethodHandle h13 = MethodHandles.constant(int.class, 13); + MethodHandle loop = MethodHandles.countedLoop(h5, h13, null); + assertEquals(methodType(int.class), loop.type()); + assertEquals(13, loop.invoke()); + } + + @Test + public static void testCountedLoopNullIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(null, null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopNullInitAndBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @DataProvider + static Object[][] countedLoopBodyParameters() { + return new Object[][] { + {methodType(String.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class, String.class)} + }; + } + + @Test(dataProvider = "countedLoopBodyParameters") + public static void testCountedLoopBodyParameters(MethodType initType, MethodType bodyType) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), + MethodHandles.empty(initType), MethodHandles.empty(bodyType)); + assertEquals(initType, loop.type()); + } + + @DataProvider + static Object[][] countedLoopTypes() { + return new Object[][]{{void.class}, {int.class}, {Object.class}, {String.class}, {List.class}}; + } + + @Test(dataProvider = "countedLoopTypes") + public static void testCountedLoopBodyParametersNullInit(Class t) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, + MethodHandles.empty(methodType(t, int.class))); + assertEquals(methodType(t), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopStateDefinedByBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, Counted.MH_stateBody); + assertEquals(Counted.MT_bodyDeterminesState, loop.type()); + assertEquals("sssssnull01234", loop.invoke()); + } + + @Test + public static void testCountedLoopArgsDefinedByIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop( + MethodHandles.dropArguments(MethodHandles.constant(int.class, 3), 0, String.class), + null, Counted.MH_append); + assertEquals(Counted.MT_iterationsDefineArgs, loop.type()); + assertEquals("hello012", loop.invoke("hello")); + } + @Test public static void testCountedRangeLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme @@ -839,6 +908,17 @@ public class LoopCombinatorTest { return x + counter; } + static String stateBody(int counter, String s) { + return "s" + s + counter; + } + + static String append(int counter, String localState, String loopArg) { + if (null == localState) { + return loopArg + counter; + } + return localState + counter; + } + static final Class COUNTED = Counted.class; static final MethodType MT_start = methodType(String.class, String.class); @@ -846,6 +926,8 @@ public class LoopCombinatorTest { static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class); static final MethodType MT_printHello = methodType(void.class, int.class); static final MethodType MT_addCounter = methodType(int.class, int.class, int.class); + static final MethodType MT_stateBody = methodType(String.class, int.class, String.class); + static final MethodType MT_append = methodType(String.class, int.class, String.class, String.class); static final MethodHandle MH_13; static final MethodHandle MH_m5; @@ -855,11 +937,15 @@ public class LoopCombinatorTest { static final MethodHandle MH_stepUpdateArray; static final MethodHandle MH_printHello; static final MethodHandle MH_addCounter; + static final MethodHandle MH_stateBody; + static final MethodHandle MH_append; static final MethodType MT_counted = methodType(String.class, String.class); static final MethodType MT_arrayCounted = methodType(void.class, int[].class); static final MethodType MT_countedPrinting = methodType(void.class); static final MethodType MT_counterInit = methodType(int.class); + static final MethodType MT_bodyDeterminesState = methodType(String.class); + static final MethodType MT_iterationsDefineArgs = methodType(String.class, String.class); static { try { @@ -871,6 +957,8 @@ public class LoopCombinatorTest { MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray); MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello); MH_addCounter = LOOKUP.findStatic(COUNTED, "addCounter", MT_addCounter); + MH_stateBody = LOOKUP.findStatic(COUNTED, "stateBody", MT_stateBody); + MH_append = LOOKUP.findStatic(COUNTED, "append", MT_append); } catch (Exception e) { throw new ExceptionInInitializerError(e); } From ddff1247c6f871881800a0b7456c7ba05ffd9dae Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 22 Apr 2016 09:43:19 -0700 Subject: [PATCH 017/113] 8154837: Class::getPackage with exploded modules when classes in modules defined to the boot loader Reviewed-by: alanb, chegar --- .../classes/jdk/internal/loader/BootLoader.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java index 6fc5e7d4ec8..269c193dbe4 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java @@ -30,6 +30,7 @@ import java.lang.module.ModuleReference; import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -184,9 +185,9 @@ public class BootLoader { /** * Define the {@code Package} with the given name. The specified - * location is a jrt URL to a named module in the run-time image, a - * file path to a module in an exploded run-time image, or the file - * path to an enty on the boot class path (java agent Boot-Class-Path + * location is a jrt URL to a named module in the run-time image, + * a file URL to a module in an exploded run-time image, or a file + * path to an entry on the boot class path (java agent Boot-Class-Path * or -Xbootclasspath/a. * *

    If the given location is a JAR file containing a manifest, @@ -194,7 +195,9 @@ public class BootLoader { * the manifest, if present. * * @param name package name - * @param location location where the package is (jrt URL or file path) + * @param location location where the package is (jrt URL or file URL + * for a named module in the run-time or exploded image; + * a file path for a package from -Xbootclasspath/a) */ static Package definePackage(String name, String location) { Module module = findModule(location); @@ -222,9 +225,9 @@ public class BootLoader { if (location.startsWith("jrt:/")) { // named module in runtime image ("jrt:/".length() == 5) mn = location.substring(5, location.length()); - } else { + } else if (location.startsWith("file:/")) { // named module in exploded image - Path path = Paths.get(location); + Path path = Paths.get(URI.create(location)); Path modulesDir = Paths.get(JAVA_HOME, "modules"); if (path.startsWith(modulesDir)) { mn = path.getFileName().toString(); From 48a86ddf3e17f7244d3e87b89d0f00b51ba0d7eb Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Fri, 22 Apr 2016 13:10:53 -0700 Subject: [PATCH 018/113] 8153330: deprecate Runtime.traceInstructions() and traceMethodCalls() Reviewed-by: alanb, dholmes, mchung --- .../share/classes/java/lang/Runtime.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index a5deffc16b8..3c73d5b61a3 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -718,41 +718,27 @@ public class Runtime { } /** - * Enables/Disables tracing of instructions. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each instruction in the virtual machine as it - * is executed. The format of this information, and the file or other - * output stream to which it is emitted, depends on the host environment. - * The virtual machine may ignore this request if it does not support - * this feature. The destination of the trace output is system - * dependent. - *

    - * If the {@code boolean} argument is {@code false}, this - * method causes the virtual machine to stop performing the - * detailed instruction trace it is performing. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control instruction tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceInstructions(boolean on) { } /** - * Enables/Disables tracing of method calls. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each method in the virtual machine as it is - * called. The format of this information, and the file or other output - * stream to which it is emitted, depends on the host environment. The - * virtual machine may ignore this request if it does not support - * this feature. - *

    - * Calling this method with argument false suggests that the - * virtual machine cease emitting per-call debugging information. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control method call tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceMethodCalls(boolean on) { } /** From 6c1f9eea71e8790bc5076204f33495cd559a5354 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sun, 24 Apr 2016 08:44:36 +0100 Subject: [PATCH 019/113] 8154919: Remove superfluous jdk.unsupported from tools/launcher/modules/limitmods/LimitModsTest.java Reviewed-by: alanb --- jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java index f11aa003e00..0cafaf42e66 100644 --- a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java +++ b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java @@ -103,10 +103,9 @@ public class LimitModsTest { public void testWithAddMods() throws Exception { int exitValue; - // java -limitmods java.base -addmods java.logging,jdk.unsupported -listmods + // java -limitmods java.base -addmods java.logging -listmods exitValue = executeTestJava("-limitmods", "java.base", - "-addmods", - "java.logging,jdk.unsupported", // TODO: add bug No. + "-addmods", "java.logging", "-listmods") .outputTo(System.out) .errorTo(System.out) From 3f14fca9652114ba863e408e59e477a0b93dbc44 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sun, 24 Apr 2016 08:51:04 +0100 Subject: [PATCH 020/113] 8147543: Remove sun.misc.ManagedLocalsThread Reviewed-by: rriggs --- .../classes/sun/misc/ManagedLocalsThread.java | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java diff --git a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java b/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java deleted file mode 100644 index 58d9013c261..00000000000 --- a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 - * 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 sun.misc; - -/** - * A thread that has it's thread locals, and inheritable thread - * locals erased on construction. - */ -public class ManagedLocalsThread extends Thread { - private static final jdk.internal.misc.Unsafe UNSAFE; - private static final long THREAD_LOCALS; - private static final long INHERITABLE_THREAD_LOCALS; - - public ManagedLocalsThread() { - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target) { - super(target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(String name) { - super(name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target) { - super(group, target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target, String name) { - super(target, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, String name) { - super(group, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - eraseThreadLocals(); - } - - /** - * Drops all thread locals (and inherited thread locals). - */ - public final void eraseThreadLocals() { - UNSAFE.putObject(this, THREAD_LOCALS, null); - UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null); - } - - static { - UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); - Class t = Thread.class; - try { - THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("threadLocals")); - INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("inheritableThreadLocals")); - } catch (Exception e) { - throw new Error(e); - } - } -} - From 52e49f6e86dd564c1cfc1c845a0478d4996458e5 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 3 Mar 2016 12:47:46 +0100 Subject: [PATCH 021/113] 8150460: (linux|bsd|aix)_close.c: file descriptor table may become large or may not work at all Reviewed-by: dsamersoff, rriggs --- .../java.base/aix/native/libnet/aix_close.c | 133 ++++++++++++++---- .../linux/native/libnet/linux_close.c | 124 ++++++++++++++-- .../macosx/native/libnet/bsd_close.c | 133 ++++++++++++++---- 3 files changed, 317 insertions(+), 73 deletions(-) diff --git a/jdk/src/java.base/aix/native/libnet/aix_close.c b/jdk/src/java.base/aix/native/libnet/aix_close.c index 0165c9a1959..77b5daecf60 100644 --- a/jdk/src/java.base/aix/native/libnet/aix_close.c +++ b/jdk/src/java.base/aix/native/libnet/aix_close.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE 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 @@ -50,6 +51,8 @@ ... */ +#include +#include #include #include #include @@ -86,10 +89,35 @@ typedef struct { static int sigWakeup = (SIGRTMAX - 1); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable = NULL; -static int fdCount = 0; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -108,42 +136,42 @@ void aix_close_init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* Check already initialized */ - if (fdCount > 0 && fdTable != NULL) { - return; - } - - /* - * Allocate table based on the maximum number of - * file descriptors. - */ + /* Determine the maximum number of possible file descriptors. */ if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { fprintf(stderr, "library initialization failed - " "unable to get max # of allocated fds\n"); abort(); } - fdCount = nbr_files.rlim_max; - /* - * We have a conceptual problem here, when the number of files is - * unlimited. As a kind of workaround, we ensure the table is big - * enough for handle even a large number of files. Since SAP itself - * recommends a limit of 32000 files, we just use 64000 as 'infinity'. - */ - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = 64000; + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - { - int i; - for (i=0; i < fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); } } @@ -161,17 +189,60 @@ void aix_close_init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. diff --git a/jdk/src/java.base/linux/native/libnet/linux_close.c b/jdk/src/java.base/linux/native/libnet/linux_close.c index f2e186f731e..45ab7b4dc1b 100644 --- a/jdk/src/java.base/linux/native/libnet/linux_close.c +++ b/jdk/src/java.base/linux/native/libnet/linux_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -59,10 +61,35 @@ typedef struct { static int sigWakeup = (__SIGRTMAX - 2); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -78,18 +105,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - fdCount = nbr_files.rlim_max; - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } + } + + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -106,15 +158,57 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } /* diff --git a/jdk/src/java.base/macosx/native/libnet/bsd_close.c b/jdk/src/java.base/macosx/native/libnet/bsd_close.c index 21478ce6e5f..728ea8bf1d7 100644 --- a/jdk/src/java.base/macosx/native/libnet/bsd_close.c +++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -61,18 +63,35 @@ typedef struct { static int sigWakeup = SIGIO; /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; -/* - * This limit applies if getlimit() returns unlimited. - * Unfortunately, this means if someone wants a higher limit - * then they have to set an explicit limit, higher than this, - * which is probably counter-intuitive. +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. */ -#define MAX_FD_COUNT 4096 +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -88,26 +107,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; - int i; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = MAX_FD_COUNT; - } else { - fdCount = nbr_files.rlim_max; + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - for (i=0; i fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -124,17 +160,60 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. From 0e76458fca8c289d1e0349757d78ab152b7a6ed6 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 14 Mar 2016 20:00:57 +0300 Subject: [PATCH 022/113] 8144073: Refactor hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java Reviewed-by: tschatzl, dfazunen --- .../humongousObjects/TestHumongousThreshold.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java index a9a83728195..3b66bc7507c 100644 --- a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java +++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015,2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public class TestHumongousThreshold { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int REGION_SIZE = WHITE_BOX.g1RegionSize(); private static final int MAX_CONTINUOUS_SIZE_CHECK = 129; - private static final int NON_HUMONGOUS_DIVIDER = 10; + private static final int NON_HUMONGOUS_STEPS = 10; /** * The method allocates byte[] with specified size and checks that: @@ -84,7 +84,7 @@ public class TestHumongousThreshold { * @return allocated byte array */ - private static byte[] allocateAndCheck(int arraySize, boolean expectedHumongous) { + private static void allocateAndCheck(int arraySize, boolean expectedHumongous) { byte[] storage = new byte[arraySize]; long objectSize = WHITE_BOX.getObjectSize(storage); boolean shouldBeHumongous = objectSize > (REGION_SIZE / 2); @@ -98,7 +98,6 @@ public class TestHumongousThreshold { "Object should be allocated as " + (shouldBeHumongous ? "humongous" : "non-humongous") + " but it wasn't; Allocation size = " + arraySize + "; Object size = " + objectSize + "; region size = " + REGION_SIZE); - return storage; } public static void main(String[] args) { @@ -108,7 +107,7 @@ public class TestHumongousThreshold { int maxByteArrayNonHumongousSize = (REGION_SIZE / 2) - byteArrayMemoryOverhead; // Increment for non-humongous testing - int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_DIVIDER; + int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_STEPS; // Maximum byte[] that takes one region int maxByteArrayOneRegionSize = REGION_SIZE - byteArrayMemoryOverhead; @@ -131,10 +130,10 @@ public class TestHumongousThreshold { allocateAndCheck(i, false); } - // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_DIVIDER + // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_STEPS System.out.format("Testing allocations with byte[] with length from 0 to %d with step %d%n", - nonHumongousStep * NON_HUMONGOUS_DIVIDER, nonHumongousStep); - for (int i = 0; i < NON_HUMONGOUS_DIVIDER; ++i) { + nonHumongousStep * NON_HUMONGOUS_STEPS, nonHumongousStep); + for (int i = 0; i < NON_HUMONGOUS_STEPS; ++i) { allocateAndCheck(i * nonHumongousStep, false); } From 4b662bba26d584ae0a3d0a536d817aa50104504f Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 18 Apr 2016 21:07:50 +0200 Subject: [PATCH 023/113] 8036952: copyright issues in jdk9/dev/langtools files Updated copyright notices. Reviewed-by: jjg, jlahoda --- .../com/sun/tools/javac/file/FSInfo.java | 24 +++++++++++++++++++ langtools/test/tools/javac/6520152/T.java | 23 ++++++++++++++++++ .../test/tools/javac/6520152/T6520152.java | 23 ++++++++++++++++++ .../test/tools/javac/6521805/T6521805e.out | 2 +- .../test/tools/javac/6521805/p/Outer.java | 2 ++ langtools/test/tools/javac/6521805/p/Sub.java | 2 ++ langtools/test/tools/javac/6547131/T.java | 23 ++++++++++++++++++ .../test/tools/javac/6589361/T6589361.java | 23 ++++++++++++++++++ .../tools/javac/6668794/badSource/Test.java | 2 +- .../typeAnnotations/referenceinfos/Test.java | 22 +++++++++++++++++ .../tools/javac/api/6731573/Erroneous.java | 2 ++ langtools/test/tools/javac/flow/T8062747.java | 23 ++++++++++++++++++ .../jvm/6397652/com/test/Test$Test$Test.java | 23 ++++++++++++++++++ .../javac/jvm/6397652/com/test/Test$Test.java | 23 ++++++++++++++++++ .../lambda/badMemberRefBytecode/Main.java | 24 +++++++++++++++++++ .../lambda/badMemberRefBytecode/Use.java | 23 ++++++++++++++++++ .../javac/lambda/lambdaExecution/TBlock.java | 23 ++++++++++++++++++ .../test/tools/javac/policy/test3/A.java | 2 ++ .../tools/javac/synthesize/src/Double.java | 23 ++++++++++++++++++ .../tools/javac/synthesize/src/Float.java | 23 ++++++++++++++++++ .../javac/warnings/6594914/Auxiliary.java | 2 ++ .../warnings/6594914/ExplicitCompilation.out | 2 +- .../warnings/6594914/ImplicitCompilation.out | 2 +- langtools/test/tools/javap/4111861/A.java | 23 ++++++++++++++++++ 24 files changed, 360 insertions(+), 4 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java index 974f28fe5ce..fea4ef7a60a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2008, 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 com.sun.tools.javac.file; diff --git a/langtools/test/tools/javac/6520152/T.java b/langtools/test/tools/javac/6520152/T.java index 8a46b8f5735..8443a4dc50e 100644 --- a/langtools/test/tools/javac/6520152/T.java +++ b/langtools/test/tools/javac/6520152/T.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + import java.io.Serializable; public class T { diff --git a/langtools/test/tools/javac/6520152/T6520152.java b/langtools/test/tools/javac/6520152/T6520152.java index bdb15990296..c7cbf31eb95 100644 --- a/langtools/test/tools/javac/6520152/T6520152.java +++ b/langtools/test/tools/javac/6520152/T6520152.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 6520152 diff --git a/langtools/test/tools/javac/6521805/T6521805e.out b/langtools/test/tools/javac/6521805/T6521805e.out index 04c71cd8821..31b628ce2d6 100644 --- a/langtools/test/tools/javac/6521805/T6521805e.out +++ b/langtools/test/tools/javac/6521805/T6521805e.out @@ -1,2 +1,2 @@ -Sub.java:8:11: compiler.err.synthetic.name.conflict: this$0, p.Inner +Sub.java:10:11: compiler.err.synthetic.name.conflict: this$0, p.Inner 1 error diff --git a/langtools/test/tools/javac/6521805/p/Outer.java b/langtools/test/tools/javac/6521805/p/Outer.java index 3dd1de56b78..8a92158426b 100644 --- a/langtools/test/tools/javac/6521805/p/Outer.java +++ b/langtools/test/tools/javac/6521805/p/Outer.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + package p; class Outer { diff --git a/langtools/test/tools/javac/6521805/p/Sub.java b/langtools/test/tools/javac/6521805/p/Sub.java index 7a9f78896e3..a6d00c76a6d 100644 --- a/langtools/test/tools/javac/6521805/p/Sub.java +++ b/langtools/test/tools/javac/6521805/p/Sub.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + package p; class Inner extends Outer.Super { diff --git a/langtools/test/tools/javac/6547131/T.java b/langtools/test/tools/javac/6547131/T.java index 76d8a5b344f..5acf9b2ae63 100644 --- a/langtools/test/tools/javac/6547131/T.java +++ b/langtools/test/tools/javac/6547131/T.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 6547131 diff --git a/langtools/test/tools/javac/6589361/T6589361.java b/langtools/test/tools/javac/6589361/T6589361.java index 4d405e41d21..5a69bc5ec99 100644 --- a/langtools/test/tools/javac/6589361/T6589361.java +++ b/langtools/test/tools/javac/6589361/T6589361.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 6589361 diff --git a/langtools/test/tools/javac/6668794/badSource/Test.java b/langtools/test/tools/javac/6668794/badSource/Test.java index 162493e5ab1..c683bbe7f48 100644 --- a/langtools/test/tools/javac/6668794/badSource/Test.java +++ b/langtools/test/tools/javac/6668794/badSource/Test.java @@ -1,5 +1,5 @@ /* - * @test /nodynamiccopyight/ + * @test /nodynamiccopyright/ * @bug 6668794 6668796 * @summary javac puts localized text in raw diagnostics * bad diagnostic "bad class file" given for source files diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java index b6cb1cae604..811bbbf454b 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ import java.util.*; import java.lang.annotation.*; diff --git a/langtools/test/tools/javac/api/6731573/Erroneous.java b/langtools/test/tools/javac/api/6731573/Erroneous.java index 7902f871c95..4bc66258016 100644 --- a/langtools/test/tools/javac/api/6731573/Erroneous.java +++ b/langtools/test/tools/javac/api/6731573/Erroneous.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + class A { boolean b; boolean b; diff --git a/langtools/test/tools/javac/flow/T8062747.java b/langtools/test/tools/javac/flow/T8062747.java index 857474216d5..8d2cfd17abc 100644 --- a/langtools/test/tools/javac/flow/T8062747.java +++ b/langtools/test/tools/javac/flow/T8062747.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 8062747 diff --git a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java index 83a81213721..6be3c7d93ac 100644 --- a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java +++ b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package com.test; public class Test$Test$Test { diff --git a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java index d15532570b1..f439128a987 100644 --- a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java +++ b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package com.test; public class Test$Test { diff --git a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java index 4c834cf3741..a188c4a74af 100644 --- a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java +++ b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + import java.util.Collections; public class Main { @@ -6,4 +29,5 @@ public class Main { Collections.sort(null, String::compareTo); } + } diff --git a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java index bb5a77a06ef..fa89e8118b1 100644 --- a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java +++ b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + public class Use { private Main m; } diff --git a/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java b/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java index 329eaf25de1..48d56c9f403 100644 --- a/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java +++ b/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * Performs operations upon an input object which may modify that object and/or * external state (other objects). diff --git a/langtools/test/tools/javac/policy/test3/A.java b/langtools/test/tools/javac/policy/test3/A.java index b21c7713860..c1f4c63bf88 100644 --- a/langtools/test/tools/javac/policy/test3/A.java +++ b/langtools/test/tools/javac/policy/test3/A.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + class A { void m1() { System.err.println("hello"); diff --git a/langtools/test/tools/javac/synthesize/src/Double.java b/langtools/test/tools/javac/synthesize/src/Double.java index 7ae620e85c8..b4cf0392933 100644 --- a/langtools/test/tools/javac/synthesize/src/Double.java +++ b/langtools/test/tools/javac/synthesize/src/Double.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package java.lang; public class Double extends Number diff --git a/langtools/test/tools/javac/synthesize/src/Float.java b/langtools/test/tools/javac/synthesize/src/Float.java index afbef38bebc..4b2fb18d5a6 100644 --- a/langtools/test/tools/javac/synthesize/src/Float.java +++ b/langtools/test/tools/javac/synthesize/src/Float.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + package java.lang; public class Float extends Number diff --git a/langtools/test/tools/javac/warnings/6594914/Auxiliary.java b/langtools/test/tools/javac/warnings/6594914/Auxiliary.java index e9c881643e2..19157042e8e 100644 --- a/langtools/test/tools/javac/warnings/6594914/Auxiliary.java +++ b/langtools/test/tools/javac/warnings/6594914/Auxiliary.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + import java.io.StringBufferInputStream; public class Auxiliary { diff --git a/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out b/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out index 3dff7922cf7..abb4822197b 100644 --- a/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out +++ b/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out @@ -1,2 +1,2 @@ -Auxiliary.java:1:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io +Auxiliary.java:3:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io 1 warning diff --git a/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out b/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out index 3dff7922cf7..abb4822197b 100644 --- a/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out +++ b/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out @@ -1,2 +1,2 @@ -Auxiliary.java:1:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io +Auxiliary.java:3:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io 1 warning diff --git a/langtools/test/tools/javap/4111861/A.java b/langtools/test/tools/javap/4111861/A.java index 32cc86a8f07..3abd02c6b8a 100644 --- a/langtools/test/tools/javap/4111861/A.java +++ b/langtools/test/tools/javap/4111861/A.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + class A { public static final int i = 42; public static final boolean b = true; From 9691505077918e937d7315a606e8ebf1648bec60 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 18 Apr 2016 22:25:50 +0200 Subject: [PATCH 024/113] 7152104: javac should not warn about missing serialVersionUID for anonymous inner classes Javac no longer issues warnings for missing serialVersionUID in anonymous classes. Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/Attr.java | 9 ++--- langtools/test/tools/javac/T6554097.java | 21 ++++++----- langtools/test/tools/javac/T6554097.out | 22 +++++++++--- .../javac/diags/examples/AnonymousClass.java | 13 ++++--- .../test/tools/javac/positions/T6253161.java | 36 ------------------- .../test/tools/javac/positions/T6253161.out | 2 -- .../test/tools/javac/positions/T6253161a.java | 28 --------------- .../test/tools/javac/positions/T6253161a.out | 2 -- .../tools/javac/{ => serial}/SerialWarn.java | 0 .../tools/javac/{ => serial}/SerialWarn.out | 0 .../tools/javac/serial/SerialWarnAnon.java | 15 ++++++++ 11 files changed, 57 insertions(+), 91 deletions(-) delete mode 100644 langtools/test/tools/javac/positions/T6253161.java delete mode 100644 langtools/test/tools/javac/positions/T6253161.out delete mode 100644 langtools/test/tools/javac/positions/T6253161a.java delete mode 100644 langtools/test/tools/javac/positions/T6253161a.out rename langtools/test/tools/javac/{ => serial}/SerialWarn.java (100%) rename langtools/test/tools/javac/{ => serial}/SerialWarn.out (100%) create mode 100644 langtools/test/tools/javac/serial/SerialWarnAnon.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index ccbe70acfbd..1fd1d379a74 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -4491,10 +4491,11 @@ public class Attr extends JCTree.Visitor { chk.checkNonCyclicElements(tree); // Check for proper use of serialVersionUID - if (env.info.lint.isEnabled(LintCategory.SERIAL) && - isSerializable(c.type) && - (c.flags() & Flags.ENUM) == 0 && - checkForSerial(c)) { + if (env.info.lint.isEnabled(LintCategory.SERIAL) + && isSerializable(c.type) + && (c.flags() & Flags.ENUM) == 0 + && !c.isAnonymous() + && checkForSerial(c)) { checkSerialVersionUID(tree, c); } if (allowTypeAnnos) { diff --git a/langtools/test/tools/javac/T6554097.java b/langtools/test/tools/javac/T6554097.java index 4deb2e9b5a8..076517c7140 100644 --- a/langtools/test/tools/javac/T6554097.java +++ b/langtools/test/tools/javac/T6554097.java @@ -3,24 +3,27 @@ * @bug 6554097 * @summary "final" confuses at-SuppressWarnings * @compile T6554097.java - * @compile/fail/ref=T6554097.out -XDrawDiagnostics -Werror -Xlint:serial T6554097.java + * @compile/fail/ref=T6554097.out -XDrawDiagnostics -Werror -Xlint:rawtypes T6554097.java */ +import java.util.ArrayList; + class T6554097 { - @SuppressWarnings("serial") final Throwable[] v1 = { new Throwable() {} }; - @SuppressWarnings("serial") Throwable[] v2 = { new Throwable() {} }; + + @SuppressWarnings("unchecked") final ArrayList[] v1 = { new ArrayList() {} }; + @SuppressWarnings("unchecked") ArrayList[] v2 = { new ArrayList() {} }; public static void m1() throws Throwable { - @SuppressWarnings("serial") final Throwable[] v3 = { new Throwable() {} }; - @SuppressWarnings("serial") Throwable[] v4 = { new Throwable() {} }; + @SuppressWarnings("unchecked") final ArrayList[] v3 = { new ArrayList() {} }; + @SuppressWarnings("unchecked") ArrayList[] v4 = { new ArrayList() {} }; } - final Throwable[] v5 = { new Throwable() {} }; - Throwable[] v6 = { new Throwable() {} }; + final ArrayList[] v5 = { new ArrayList() {} }; + ArrayList[] v6 = { new ArrayList() {} }; public static void m2() throws Throwable { - final Throwable[] v7 = { new Throwable() {} }; - Throwable[] v8 = { new Throwable() {} }; + final ArrayList[] v7 = { new ArrayList() {} }; + ArrayList[] v8 = { new ArrayList() {} }; } } diff --git a/langtools/test/tools/javac/T6554097.out b/langtools/test/tools/javac/T6554097.out index aecbd999cf5..14db8a54b81 100644 --- a/langtools/test/tools/javac/T6554097.out +++ b/langtools/test/tools/javac/T6554097.out @@ -1,7 +1,19 @@ -T6554097.java:18:46: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$5 -T6554097.java:19:46: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$6 -T6554097.java:22:50: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$7 -T6554097.java:23:54: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$8 +T6554097.java:13:42: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:13:65: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:14:42: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:14:65: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:17:50: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:17:73: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:18:50: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:18:73: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:21:11: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:21:34: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:22:11: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:22:34: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:25:15: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:25:38: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:26:15: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:26:38: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList - compiler.err.warnings.and.werror 1 error -4 warnings +16 warnings diff --git a/langtools/test/tools/javac/diags/examples/AnonymousClass.java b/langtools/test/tools/javac/diags/examples/AnonymousClass.java index 771d888ddbc..d5e3858f13a 100644 --- a/langtools/test/tools/javac/diags/examples/AnonymousClass.java +++ b/langtools/test/tools/javac/diags/examples/AnonymousClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,12 +22,15 @@ */ // key: compiler.misc.anonymous.class -// key: compiler.warn.missing.SVUID -// options: -Xlint:serial +// key: compiler.err.prob.found.req +// key: compiler.misc.inconvertible.types +// options: -Xlint:rawtypes // run: simple +import java.util.ArrayList; + class AnonymousClass { - Exception m() { - return new Exception() { }; + Object m() { + return (ArrayList) new ArrayList() { }; } } diff --git a/langtools/test/tools/javac/positions/T6253161.java b/langtools/test/tools/javac/positions/T6253161.java deleted file mode 100644 index 5824a457707..00000000000 --- a/langtools/test/tools/javac/positions/T6253161.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6253161 - * @summary Compiler will fail to find the correct location of serial warnings for anonymous inner classes - * @author Seetharama Avadhanam - * @compile -Xlint:serial -XDdev T6253161.java - * @compile/ref=T6253161.out -Xlint:serial -XDdev -XDrawDiagnostics T6253161.java - */ -import java.util.List; -import java.util.ArrayList; - -public class T6253161 { - @SuppressWarnings("unchecked") - public void anonymousMethod(){ - List list = new ArrayList(){ - static final long serialVersionUID = 1; - List list = new ArrayList(); - public List getMyList(){ - final List floatList = new ArrayList(){ - List integerList = new ArrayList(); - public List getMyList(){ - for(int i=0;i<10;i++) - integerList.add((int)((Float.parseFloat(i+""))+(1.11F))); - return (List)(Object)integerList; - } - public void testMethods(){ - //... - } - }.getMyList(); - for(int i=0;i<10;i++) - list.add((Float)(floatList.get(i)) * 11.232F * i); - return list; - } - }.getMyList(); - } -} diff --git a/langtools/test/tools/javac/positions/T6253161.out b/langtools/test/tools/javac/positions/T6253161.out deleted file mode 100644 index d5d2e5162e8..00000000000 --- a/langtools/test/tools/javac/positions/T6253161.out +++ /dev/null @@ -1,2 +0,0 @@ -T6253161.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161$1$1 -1 warning diff --git a/langtools/test/tools/javac/positions/T6253161a.java b/langtools/test/tools/javac/positions/T6253161a.java deleted file mode 100644 index 1adfd72f8a9..00000000000 --- a/langtools/test/tools/javac/positions/T6253161a.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6253161 - * @summary Compiler will fail to find the correct location of serial warnings for anonymous inner classes - * @author Seetharama Avadhanam - * @compile -Xlint:serial -XDdev T6253161a.java - * @compile/ref=T6253161a.out -Xlint:serial -XDdev -XDrawDiagnostics T6253161a.java - */ -import java.util.List; -import java.util.ArrayList; - -public class T6253161a { - @SuppressWarnings("unchecked") - public void anonymousMethod(){ - List list = new ArrayList(){ - static final long serialVersionUID = 1; - List list = new ArrayList(); - public List getMyList(){ - final List floatList = new ArrayList(){ - // Blank .... - }; - for(int i=0;i<10;i++) - list.add((Float)(floatList.get(i)) * 11.232F * i); - return list; - } - }.getMyList(); - } -} diff --git a/langtools/test/tools/javac/positions/T6253161a.out b/langtools/test/tools/javac/positions/T6253161a.out deleted file mode 100644 index e5ba714cb51..00000000000 --- a/langtools/test/tools/javac/positions/T6253161a.out +++ /dev/null @@ -1,2 +0,0 @@ -T6253161a.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161a$1$1 -1 warning diff --git a/langtools/test/tools/javac/SerialWarn.java b/langtools/test/tools/javac/serial/SerialWarn.java similarity index 100% rename from langtools/test/tools/javac/SerialWarn.java rename to langtools/test/tools/javac/serial/SerialWarn.java diff --git a/langtools/test/tools/javac/SerialWarn.out b/langtools/test/tools/javac/serial/SerialWarn.out similarity index 100% rename from langtools/test/tools/javac/SerialWarn.out rename to langtools/test/tools/javac/serial/SerialWarn.out diff --git a/langtools/test/tools/javac/serial/SerialWarnAnon.java b/langtools/test/tools/javac/serial/SerialWarnAnon.java new file mode 100644 index 00000000000..2e6def59519 --- /dev/null +++ b/langtools/test/tools/javac/serial/SerialWarnAnon.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7152104 + * @summary Make sure no warning is emitted for anonymous classes + * without serialVersionUID + * @compile SerialWarn.java + * @compile -Werror -XDrawDiagnostics -Xlint:serial SerialWarnAnon.java + */ + +class SerialWarnAnon { + interface SerialWarnAnonInterface extends java.io.Serializable { } + Object m() { + return new SerialWarnAnonInterface() { }; + } +} From 2d863bcd37bcbd06e39559add140e9d2cde73f5e Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 18 Apr 2016 14:04:09 -0700 Subject: [PATCH 025/113] 8145468: update java.lang APIs with new deprecations Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/ConstFold.java | 50 +++++++++---------- .../com/sun/tools/javac/jvm/ClassReader.java | 6 +-- .../classes/com/sun/tools/javac/jvm/Gen.java | 2 +- .../sun/tools/javac/parser/JavacParser.java | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java index be33a96ffc6..3436c18ceaf 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java @@ -125,15 +125,15 @@ strictfp class ConstFold { return syms.booleanType.constType(b2i(intValue(od) >= 0)); case lneg: // unary - - return syms.longType.constType(new Long(-longValue(od))); + return syms.longType.constType(Long.valueOf(-longValue(od))); case lxor: // ~ - return syms.longType.constType(new Long(~longValue(od))); + return syms.longType.constType(Long.valueOf(~longValue(od))); case fneg: // unary - - return syms.floatType.constType(new Float(-floatValue(od))); + return syms.floatType.constType(Float.valueOf(-floatValue(od))); case dneg: // ~ - return syms.doubleType.constType(new Double(-doubleValue(od))); + return syms.doubleType.constType(Double.valueOf(-doubleValue(od))); default: return null; @@ -216,37 +216,37 @@ strictfp class ConstFold { case ladd: return syms.longType.constType( - new Long(longValue(l) + longValue(r))); + Long.valueOf(longValue(l) + longValue(r))); case lsub: return syms.longType.constType( - new Long(longValue(l) - longValue(r))); + Long.valueOf(longValue(l) - longValue(r))); case lmul: return syms.longType.constType( - new Long(longValue(l) * longValue(r))); + Long.valueOf(longValue(l) * longValue(r))); case ldiv: return syms.longType.constType( - new Long(longValue(l) / longValue(r))); + Long.valueOf(longValue(l) / longValue(r))); case lmod: return syms.longType.constType( - new Long(longValue(l) % longValue(r))); + Long.valueOf(longValue(l) % longValue(r))); case land: return syms.longType.constType( - new Long(longValue(l) & longValue(r))); + Long.valueOf(longValue(l) & longValue(r))); case lor: return syms.longType.constType( - new Long(longValue(l) | longValue(r))); + Long.valueOf(longValue(l) | longValue(r))); case lxor: return syms.longType.constType( - new Long(longValue(l) ^ longValue(r))); + Long.valueOf(longValue(l) ^ longValue(r))); case lshl: case lshll: return syms.longType.constType( - new Long(longValue(l) << intValue(r))); + Long.valueOf(longValue(l) << intValue(r))); case lshr: case lshrl: return syms.longType.constType( - new Long(longValue(l) >> intValue(r))); + Long.valueOf(longValue(l) >> intValue(r))); case lushr: return syms.longType.constType( - new Long(longValue(l) >>> intValue(r))); + Long.valueOf(longValue(l) >>> intValue(r))); case lcmp: if (longValue(l) < longValue(r)) return syms.intType.constType(minusOne); @@ -256,19 +256,19 @@ strictfp class ConstFold { return syms.intType.constType(zero); case fadd: return syms.floatType.constType( - new Float(floatValue(l) + floatValue(r))); + Float.valueOf(floatValue(l) + floatValue(r))); case fsub: return syms.floatType.constType( - new Float(floatValue(l) - floatValue(r))); + Float.valueOf(floatValue(l) - floatValue(r))); case fmul: return syms.floatType.constType( - new Float(floatValue(l) * floatValue(r))); + Float.valueOf(floatValue(l) * floatValue(r))); case fdiv: return syms.floatType.constType( - new Float(floatValue(l) / floatValue(r))); + Float.valueOf(floatValue(l) / floatValue(r))); case fmod: return syms.floatType.constType( - new Float(floatValue(l) % floatValue(r))); + Float.valueOf(floatValue(l) % floatValue(r))); case fcmpg: case fcmpl: if (floatValue(l) < floatValue(r)) return syms.intType.constType(minusOne); @@ -282,19 +282,19 @@ strictfp class ConstFold { return syms.intType.constType(minusOne); case dadd: return syms.doubleType.constType( - new Double(doubleValue(l) + doubleValue(r))); + Double.valueOf(doubleValue(l) + doubleValue(r))); case dsub: return syms.doubleType.constType( - new Double(doubleValue(l) - doubleValue(r))); + Double.valueOf(doubleValue(l) - doubleValue(r))); case dmul: return syms.doubleType.constType( - new Double(doubleValue(l) * doubleValue(r))); + Double.valueOf(doubleValue(l) * doubleValue(r))); case ddiv: return syms.doubleType.constType( - new Double(doubleValue(l) / doubleValue(r))); + Double.valueOf(doubleValue(l) / doubleValue(r))); case dmod: return syms.doubleType.constType( - new Double(doubleValue(l) % doubleValue(r))); + Double.valueOf(doubleValue(l) % doubleValue(r))); case dcmpg: case dcmpl: if (doubleValue(l) < doubleValue(r)) return syms.intType.constType(minusOne); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 9806e85f959..12c46059519 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -457,13 +457,13 @@ public class ClassReader { poolObj[i] = getInt(index + 1); break; case CONSTANT_Float: - poolObj[i] = new Float(getFloat(index + 1)); + poolObj[i] = Float.valueOf(getFloat(index + 1)); break; case CONSTANT_Long: - poolObj[i] = new Long(getLong(index + 1)); + poolObj[i] = Long.valueOf(getLong(index + 1)); break; case CONSTANT_Double: - poolObj[i] = new Double(getDouble(index + 1)); + poolObj[i] = Double.valueOf(getDouble(index + 1)); break; case CONSTANT_MethodHandle: skipBytes(4); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index b551b61e8d9..5de84f0ab59 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -203,7 +203,7 @@ public class Gen extends JCTree.Visitor { */ void emitMinusOne(int tc) { if (tc == LONGcode) { - items.makeImmediateItem(syms.longType, new Long(-1)).load(); + items.makeImmediateItem(syms.longType, Long.valueOf(-1)).load(); } else { code.emitop0(iconst_m1); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index c0b69a9c86e..e6e3b839e25 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -686,7 +686,7 @@ public class JavacParser implements Parser { try { t = F.at(pos).Literal( TypeTag.LONG, - new Long(Convert.string2long(strval(prefix), token.radix()))); + Long.valueOf(Convert.string2long(strval(prefix), token.radix()))); } catch (NumberFormatException ex) { error(token.pos, "int.number.too.large", strval(prefix)); } From 8f62cdc8a03baaacac556edde84a7a01ba58cd62 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 18 Apr 2016 18:41:38 -0700 Subject: [PATCH 026/113] 8154504: javac tests fail after JDK API is deprecated Reviewed-by: darcy --- langtools/test/tools/javac/CaptureInSubtype.java | 2 +- langtools/test/tools/javac/OverrideChecks/T4721069.java | 2 +- langtools/test/tools/javac/generics/Nonlinear.java | 2 +- langtools/test/tools/javac/generics/odersky/BadTest4.java | 2 +- langtools/test/tools/javac/lambda/8074381/T8074381a.java | 2 ++ langtools/test/tools/javac/lambda/8074381/T8074381a.out | 4 ++-- langtools/test/tools/javac/lambda/TargetType27.java | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/langtools/test/tools/javac/CaptureInSubtype.java b/langtools/test/tools/javac/CaptureInSubtype.java index 41d5a3b0b1b..3b73e20a6dd 100644 --- a/langtools/test/tools/javac/CaptureInSubtype.java +++ b/langtools/test/tools/javac/CaptureInSubtype.java @@ -33,7 +33,7 @@ public class CaptureInSubtype { public static class ShowFlaw extends SuperOfShowFlaw { - static Flaw fn = new Flaw(new Integer(3)); + static Flaw fn = new Flaw(Integer.valueOf(3)); Flaw m(){return fn;} } diff --git a/langtools/test/tools/javac/OverrideChecks/T4721069.java b/langtools/test/tools/javac/OverrideChecks/T4721069.java index 18259f791d4..ea8f4da567d 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4721069.java +++ b/langtools/test/tools/javac/OverrideChecks/T4721069.java @@ -12,7 +12,7 @@ interface I { static class T { static void f(I i) { if (i == null) { - Integer x = new Integer(2); + Integer x = Integer.valueOf(2); } else { I x = i; x.getClass(); diff --git a/langtools/test/tools/javac/generics/Nonlinear.java b/langtools/test/tools/javac/generics/Nonlinear.java index f952d74c300..36004a07907 100644 --- a/langtools/test/tools/javac/generics/Nonlinear.java +++ b/langtools/test/tools/javac/generics/Nonlinear.java @@ -22,7 +22,7 @@ public class Nonlinear { // the program. public static void main (String [] args) { - Integer x = new Integer (5); + Integer x = Integer.valueOf(5); String y = castit (x); System.out.println (y); } diff --git a/langtools/test/tools/javac/generics/odersky/BadTest4.java b/langtools/test/tools/javac/generics/odersky/BadTest4.java index 1ad3e576b0c..516318d8147 100644 --- a/langtools/test/tools/javac/generics/odersky/BadTest4.java +++ b/langtools/test/tools/javac/generics/odersky/BadTest4.java @@ -30,7 +30,7 @@ class BadTest4 { static Cell makeCell(A x) { return new Cell(x); } static A id(A x) { return x; } - static Integer i = new Integer(1); + static Integer i = Integer.valueOf(1); static Number n = i; public static void main(String[] args) { diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.java b/langtools/test/tools/javac/lambda/8074381/T8074381a.java index 7b7b9dd6cc2..d11944d3926 100644 --- a/langtools/test/tools/javac/lambda/8074381/T8074381a.java +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java @@ -13,6 +13,7 @@ class T8074381a { boolean m(String s); } + @SuppressWarnings("deprecation") void testRaw() { Sub s1 = c -> true; Sub s2 = Boolean::new; @@ -22,6 +23,7 @@ class T8074381a { }; } + @SuppressWarnings("deprecation") void testNonRaw() { Sub s1 = c -> true; Sub s2 = Boolean::new; diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.out b/langtools/test/tools/javac/lambda/8074381/T8074381a.out index f7ba487c586..d969c59a919 100644 --- a/langtools/test/tools/javac/lambda/8074381/T8074381a.out +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out @@ -1,4 +1,4 @@ -T8074381a.java:17:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) T8074381a.java:18:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) -T8074381a.java:19:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup +T8074381a.java:19:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:20:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup 3 errors diff --git a/langtools/test/tools/javac/lambda/TargetType27.java b/langtools/test/tools/javac/lambda/TargetType27.java index 762a4ab8bef..dcb76901c7e 100644 --- a/langtools/test/tools/javac/lambda/TargetType27.java +++ b/langtools/test/tools/javac/lambda/TargetType27.java @@ -15,6 +15,6 @@ class TargetType27 { F m(F f) { return null; } void test() { - m((String s1) -> (String s2) -> new Integer(1)); + m((String s1) -> (String s2) -> Integer.valueOf(1)); } } From 28ed819ae90b622f2eedaaceb41a798a8c6af080 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 18 Apr 2016 19:14:50 -0700 Subject: [PATCH 027/113] 8154500: fix handling of jdk.launcher.patch.* in tests Reviewed-by: ksrini --- .../javadoc/tool/6964914/TestStdDoclet.java | 19 +++++++++++++----- .../javadoc/tool/6964914/TestUserDoclet.java | 19 ++++++++++++++---- .../tools/javadoc/6964914/TestStdDoclet.java | 19 +++++++++++++----- .../tools/javadoc/6964914/TestUserDoclet.java | 20 ++++++++++++++----- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java index 3fff0e1252d..3803a5241e9 100644 --- a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java +++ b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ */ import java.io.*; +import java.util.*; /** * Dummy javadoc comment. @@ -54,13 +55,21 @@ public class TestStdDoclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestStdDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-classpath", ".", // insulates us from ambient classpath "-Xdoclint:none", "-package", - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java index cec6d274d24..02c6ec882b3 100644 --- a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java +++ b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java @@ -30,7 +30,10 @@ import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -63,12 +66,20 @@ public class TestUserDoclet implements Doclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestUserDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-doclet", thisClassName, "-docletpath", testClasses.getPath(), - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java index d30ae8322ff..2ab14c0124c 100644 --- a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ */ import java.io.*; +import java.util.*; /** * Dummy javadoc comment. @@ -54,13 +55,21 @@ public class TestStdDoclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestStdDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-classpath", ".", // insulates us from ambient classpath "-Xdoclint:none", "-package", - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java b/langtools/test/tools/javadoc/6964914/TestUserDoclet.java index a09847073b2..7cb2041cfe6 100644 --- a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestUserDoclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ */ import java.io.*; +import java.util.*; + import com.sun.javadoc.Doclet; import com.sun.javadoc.RootDoc; @@ -55,12 +57,20 @@ public class TestUserDoclet extends Doclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestUserDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-doclet", thisClassName, "-docletpath", testClasses.getPath(), - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); From d6521300a0ff2896edd2e63113f9e740d855a71a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 19 Apr 2016 14:16:39 +0200 Subject: [PATCH 028/113] 7020499: Project Coin: improvements to try-with-resources desugaring Avoid unnecessary check for resource nullness if the resource is known to be non-null; put resource closing code in a method that is shared by multiple try-with-resources. Reviewed-by: darcy, mcimadamore, vromero --- .../com/sun/tools/javac/comp/Lower.java | 105 +++++++++++- .../TryWithResources/TwrAvoidNullCheck.java | 125 ++++++++++++++ .../javac/TryWithResources/TwrClose.java | 140 ++++++++++++++++ .../TryWithResources/TwrShareCloseCode.java | 158 ++++++++++++++++++ .../referenceinfos/ResourceVariable.java | 14 +- .../tools/javac/flow/tests/TestCaseTry.java | 10 +- 6 files changed, 533 insertions(+), 19 deletions(-) create mode 100644 langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrClose.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 197cff5c3be..0bb1d96a7fb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -86,6 +86,7 @@ public class Lower extends TreeTranslator { private final TypeEnvs typeEnvs; private final Name dollarAssertionsDisabled; private final Name classDollar; + private final Name dollarCloseResource; private final Types types; private final boolean debugLower; private final PkgInfo pkginfoOpt; @@ -109,6 +110,8 @@ public class Lower extends TreeTranslator { fromString(target.syntheticNameChar() + "assertionsDisabled"); classDollar = names. fromString("class" + target.syntheticNameChar()); + dollarCloseResource = names. + fromString(target.syntheticNameChar() + "closeResource"); types = Types.instance(context); Options options = Options.instance(context); @@ -1648,9 +1651,11 @@ public class Lower extends TreeTranslator { ListBuffer stats = new ListBuffer<>(); JCTree resource = resources.head; JCExpression expr = null; + boolean resourceNonNull; if (resource instanceof JCVariableDecl) { JCVariableDecl var = (JCVariableDecl) resource; expr = make.Ident(var.sym).setType(resource.type); + resourceNonNull = var.init != null && TreeInfo.skipParens(var.init).hasTag(NEWCLASS); stats.add(var); } else { Assert.check(resource instanceof JCExpression); @@ -1665,6 +1670,7 @@ public class Lower extends TreeTranslator { JCVariableDecl syntheticTwrVarDecl = make.VarDef(syntheticTwrVar, (JCExpression)resource); expr = (JCExpression)make.Ident(syntheticTwrVar); + resourceNonNull = TreeInfo.skipParens(resource).hasTag(NEWCLASS); stats.add(syntheticTwrVarDecl); } @@ -1694,7 +1700,7 @@ public class Lower extends TreeTranslator { int oldPos = make.pos; make.at(TreeInfo.endPos(block)); - JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr); + JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr, resourceNonNull); make.at(oldPos); JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, finallyCanCompleteNormally, depth + 1), @@ -1706,7 +1712,96 @@ public class Lower extends TreeTranslator { return newBlock; } - private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) { + /**If the estimated number of copies the close resource code in a single class is above this + * threshold, generate and use a method for the close resource code, leading to smaller code. + * As generating a method has overhead on its own, generating the method for cases below the + * threshold could lead to an increase in code size. + */ + public static final int USE_CLOSE_RESOURCE_METHOD_THRESHOLD = 4; + + private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource, + boolean resourceNonNull) { + MethodSymbol closeResource = (MethodSymbol)lookupSynthetic(dollarCloseResource, + currentClass.members()); + + if (closeResource == null && shouldUseCloseResourceMethod()) { + closeResource = new MethodSymbol( + PRIVATE | STATIC | SYNTHETIC, + dollarCloseResource, + new MethodType( + List.of(syms.throwableType, syms.autoCloseableType), + syms.voidType, + List.nil(), + syms.methodClass), + currentClass); + enterSynthetic(resource.pos(), closeResource, currentClass.members()); + + JCMethodDecl md = make.MethodDef(closeResource, null); + List params = md.getParameters(); + md.body = make.Block(0, List.of(makeTwrCloseStatement(params.get(0).sym, + make.Ident(params.get(1))))); + + JCClassDecl currentClassDecl = classDef(currentClass); + currentClassDecl.defs = currentClassDecl.defs.prepend(md); + } + + JCStatement closeStatement; + + if (closeResource != null) { + //$closeResource(#primaryException, #resource) + closeStatement = make.Exec(make.Apply(List.nil(), + make.Ident(closeResource), + List.of(make.Ident(primaryException), + resource) + ).setType(syms.voidType)); + } else { + closeStatement = makeTwrCloseStatement(primaryException, resource); + } + + JCStatement finallyStatement; + + if (resourceNonNull) { + finallyStatement = closeStatement; + } else { + // if (#resource != null) { $closeResource(...); } + finallyStatement = make.If(makeNonNullCheck(resource), + closeStatement, + null); + } + + return make.Block(0L, + List.of(finallyStatement)); + } + //where: + private boolean shouldUseCloseResourceMethod() { + class TryFinder extends TreeScanner { + int closeCount; + @Override + public void visitTry(JCTry tree) { + boolean empty = tree.body.stats.isEmpty(); + + for (JCTree r : tree.resources) { + closeCount += empty ? 1 : 2; + empty = false; //with multiple resources, only the innermost try can be empty. + } + super.visitTry(tree); + } + @Override + public void scan(JCTree tree) { + if (useCloseResourceMethod()) + return; + super.scan(tree); + } + boolean useCloseResourceMethod() { + return closeCount >= USE_CLOSE_RESOURCE_METHOD_THRESHOLD; + } + } + TryFinder tryFinder = new TryFinder(); + tryFinder.scan(classDef(currentClass)); + return tryFinder.useCloseResourceMethod(); + } + + private JCStatement makeTwrCloseStatement(Symbol primaryException, JCExpression resource) { // primaryException.addSuppressed(catchException); VarSymbol catchException = new VarSymbol(SYNTHETIC, make.paramName(2), @@ -1731,11 +1826,7 @@ public class Lower extends TreeTranslator { tryTree, makeResourceCloseInvocation(resource)); - // if (#resource != null) { if (primaryException ... } - return make.Block(0L, - List.of(make.If(makeNonNullCheck(resource), - closeIfStatement, - null))); + return closeIfStatement; } private JCStatement makeResourceCloseInvocation(JCExpression resource) { diff --git a/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java b/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java new file mode 100644 index 00000000000..f095b92b571 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7020499 + * @summary Verify that try-with-resources desugaring is not generating unnecessary null checks + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask TwrAvoidNullCheck + * @run main TwrAvoidNullCheck + */ + +import java.io.IOException; +import java.util.Arrays; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.Lower; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBinary; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import com.sun.tools.javac.util.List; + +import toolbox.ToolBox; + +public class TwrAvoidNullCheck { + public static void main(String... args) throws IOException { + new TwrAvoidNullCheck().run(); + } + void run() throws IOException { + run("new Test()", false); + run("null", true); + run("System.getProperty(\"test\") != null ? new Test() : null", true); + } + void run(String resourceSpecification, boolean expected) throws IOException { + String template = "public class Test implements AutoCloseable {\n" + + " void t() {\n" + + " try (Test resource = RESOURCE) { }\n" + + " }\n" + + " public void close() { }\n" + + "}\n"; + String code = template.replace("RESOURCE", resourceSpecification); + Context ctx = new Context(); + DumpLower.preRegister(ctx); + Iterable files = Arrays.asList(new ToolBox.JavaSource(code)); + JavacTask task = JavacTool.create().getTask(null, null, null, null, null, files, ctx); + task.call(); + + boolean hasNullCheck = ((DumpLower) DumpLower.instance(ctx)).hasNullCheck; + + if (hasNullCheck != expected) { + throw new IllegalStateException("expected: " + expected + + "; actual: " + hasNullCheck + + "; code: " + code); + } + } + + static class DumpLower extends Lower { + + public static void preRegister(Context ctx) { + ctx.put(lowerKey, new Factory() { + @Override + public Lower make(Context c) { + return new DumpLower(c); + } + }); + } + + public DumpLower(Context context) { + super(context); + } + + boolean hasNullCheck; + + @Override + public List translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + List result = super.translateTopLevelClass(env, cdef, make); + + new TreeScanner() { + @Override + public void visitBinary(JCBinary tree) { + hasNullCheck |= tree.operator.getSimpleName().contentEquals("!=") && + "resource".equals(String.valueOf(TreeInfo.name(tree.lhs))) && + TreeInfo.isNull(tree.rhs); + super.visitBinary(tree); + } + }.scan(result); + + return result; + } + + } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrClose.java b/langtools/test/tools/javac/TryWithResources/TwrClose.java new file mode 100644 index 00000000000..504a05bd5b4 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrClose.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7020499 + * @summary Verify that the close resource code works properly in all cases + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox TwrClose + * @run main TwrClose + */ + +import javax.tools.JavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.tools.javac.comp.Lower; + +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class TwrClose { + + public static void main(String... args) throws Exception { + for (int i = 1; i < Lower.USE_CLOSE_RESOURCE_METHOD_THRESHOLD * 2; i++) { + new TwrClose().compile(i); + } + } + + ToolBox tb = new ToolBox(); + JavaFileManager fm = ToolProvider.getSystemJavaCompiler() + .getStandardFileManager(null, null, null); + + void compile(int trysCount) throws Exception { + StringBuilder testInvocations = new StringBuilder(); + StringBuilder testMethods = new StringBuilder(); + + for (int i = 0; i < trysCount; i++) { + testInvocations.append(TEST_INVOCATIONS_TEMPLATE.replace("#N", Integer.toString(i))); + testMethods.append(TEST_METHOD_TEMPLATE.replace("#N", Integer.toString(i))); + } + + String sourceCode = FILE_TEMPLATE.replace("#TEST_INVOCATIONS", testInvocations.toString()) + .replace("#TEST_METHODS", testMethods.toString()); + + System.err.println("analyzing:"); + System.err.println(sourceCode); + + try (ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager()) { + new JavacTask(tb).fileManager(mfm) + .sources(sourceCode) + .run() + .writeAll(); + ClassLoader cl = new ClassLoader(TwrClose.class.getClassLoader()) { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] data = mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, name); + if (data != null) { + return defineClass(name, data, 0, data.length); + } + return super.findClass(name); + } + }; + + ((Runnable) cl.loadClass("Test").newInstance()).run(); + } + } + + final String TEST_INVOCATIONS_TEMPLATE = + " test#N(false, false, Arrays.asList(\"close\"));\n" + + " test#N(false, true, Arrays.asList(\"close\", \"close-exception\"));\n" + + " test#N(true, false, Arrays.asList(\"close\", \"inTwr\"));\n" + + " test#N(true, true, Arrays.asList(\"close\", \"inTwr\", \"close-exception\"));\n"; + + final String TEST_METHOD_TEMPLATE = + " private void test#N(boolean failInTwr, boolean failOnClose,\n" + + " List expectedMessages) {\n" + + " List messages = new ArrayList<>();\n" + + " try {\n" + + " try (CloseableImpl c = new CloseableImpl(messages, failOnClose)) {\n" + + " if (failInTwr)\n" + + " throw new IllegalStateException(\"inTwr\");\n" + + " }\n" + + " } catch (IllegalStateException ex) {\n" + + " messages.add(ex.getMessage());\n" + + " for (Throwable t : ex.getSuppressed()) {\n" + + " messages.add(t.getMessage());\n" + + " }\n" + + " }\n" + + " if (!expectedMessages.equals(messages))\n" + + " throw new AssertionError(\"Expected and actual messages differ; expectedMessages=\" +\n" + + " expectedMessages + \"; actual=\" + messages);\n" + + " }\n"; + + final String FILE_TEMPLATE = + "import java.util.*;\n" + + "public class Test implements Runnable {\n" + + " public void run() {\n" + + "#TEST_INVOCATIONS" + + " }\n" + + "#TEST_METHODS" + + " static class CloseableImpl implements AutoCloseable {\n" + + " private final List messages;\n" + + " private final boolean failOnClose;\n" + + " public CloseableImpl(List messages, boolean failOnClose) {\n" + + " this.messages = messages;\n" + + " this.failOnClose = failOnClose;\n" + + " }\n" + + " @Override\n" + + " public void close() {\n" + + " messages.add(\"close\");\n" + + " if (failOnClose)\n" + + " throw new IllegalStateException(\"close-exception\");\n" + + " }\n" + + " }\n" + + "}\n"; +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java b/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java new file mode 100644 index 00000000000..0d6ff045ef7 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7020499 + * @summary Verify that the code that closes the resources is shared by among try-with-resources + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox TwrShareCloseCode + * @run main TwrShareCloseCode + */ + +import java.io.IOException; +import java.util.Arrays; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.Lower; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import com.sun.tools.javac.util.List; + +import toolbox.ToolBox; + +public class TwrShareCloseCode { + public static void main(String... args) throws IOException { + new TwrShareCloseCode().run(); + } + + void run() throws IOException { + run("try (Test t1 = new Test()) { }", true); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }", true); + run("try (Test t1 = new Test();\n" + + " Test t2 = new Test()) { }", true); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }", true); + run("try (Test t1 = new Test();\n" + + " Test t2 = new Test();\n" + + " Test t3 = new Test()) { }", false); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }\n" + + "try (Test t4 = new Test()) { }", false); + + run("try (Test t1 = new Test()) { i++; }", true); + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { i++; }", false); + + run("try (Test t1 = new Test(); Test t2 = new Test()) { i++; }", false); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { }", true); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }", false); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { i++; }\n" + + "try (Test t3 = new Test()) { }", false); + } + void run(String trySpec, boolean expected) throws IOException { + String template = "public class Test implements AutoCloseable {\n" + + " void t(int i) {\n" + + " TRY\n" + + " }\n" + + " public void close() { }\n" + + "}\n"; + String code = template.replace("TRY", trySpec); + Context ctx = new Context(); + DumpLower.preRegister(ctx); + Iterable files = Arrays.asList(new ToolBox.JavaSource(code)); + JavacTask task = JavacTool.create().getTask(null, null, null, null, null, files, ctx); + task.call(); + boolean actual = ((DumpLower) DumpLower.instance(ctx)).closeSeen; + + if (expected != actual) { + throw new IllegalStateException("expected: " + expected + "; actual: " + actual + "; code:\n" + code); + } + } + + static class DumpLower extends Lower { + + public static void preRegister(Context ctx) { + ctx.put(lowerKey, new Factory() { + @Override + public Lower make(Context c) { + return new DumpLower(c); + } + }); + } + + public DumpLower(Context context) { + super(context); + } + + boolean closeSeen; + + @Override + public List translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + List result = super.translateTopLevelClass(env, cdef, make); + + new TreeScanner() { + @Override + public void visitMethodDef(JCMethodDecl tree) { + if (!tree.name.contentEquals("t")) + return; + + super.visitMethodDef(tree); + } + + @Override + public void visitApply(JCMethodInvocation tree) { + closeSeen |= TreeInfo.symbol(tree.meth).name.contentEquals("close"); + super.visitApply(tree); + } + }.scan(result); + + return result; + } + + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java index 266a3e8a592..b65535badf5 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,9 +36,9 @@ import static java.lang.System.lineSeparator; public class ResourceVariable { @TADescription(annotation = "TA", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {118}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {106}, lvarIndex = {1}) @TADescription(annotation = "TB", type = RESOURCE_VARIABLE, - lvarOffset = {22}, lvarLength = {35}, lvarIndex = {3}) + lvarOffset = {22}, lvarLength = {31}, lvarIndex = {3}) public String testResourceVariable() { return "public void f() throws IOException {" + lineSeparator() + @@ -49,7 +49,7 @@ public class ResourceVariable { } @TADescription(annotation = "RTAs", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {30}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {26}, lvarIndex = {1}) public String testRepeatedAnnotation1() { return "public void f() throws IOException {" + lineSeparator() + @@ -58,7 +58,7 @@ public class ResourceVariable { } @TADescription(annotation = "RTAs", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {30}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {26}, lvarIndex = {1}) public String testRepeatedAnnotation2() { return "public void f() throws IOException {" + lineSeparator() + @@ -67,9 +67,9 @@ public class ResourceVariable { } @TADescription(annotation = "TA", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {118}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {106}, lvarIndex = {1}) @TADescription(annotation = "TB", type = RESOURCE_VARIABLE, - lvarOffset = {22}, lvarLength = {35}, lvarIndex = {3}) + lvarOffset = {22}, lvarLength = {31}, lvarIndex = {3}) public String testSeveralVariablesInTryWithResources() { return "public void f() throws IOException {" + lineSeparator() + diff --git a/langtools/test/tools/javac/flow/tests/TestCaseTry.java b/langtools/test/tools/javac/flow/tests/TestCaseTry.java index b3a3762bd20..dbc1f2b9d74 100644 --- a/langtools/test/tools/javac/flow/tests/TestCaseTry.java +++ b/langtools/test/tools/javac/flow/tests/TestCaseTry.java @@ -52,9 +52,9 @@ public class TestCaseTry { o = ""; } - @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=38) - @AliveRange(varName="o", bytecodeStart=103, bytecodeLength=3) - @AliveRange(varName="o", bytecodeStart=110, bytecodeLength=1) + @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=13) + @AliveRange(varName="o", bytecodeStart=53, bytecodeLength=3) + @AliveRange(varName="o", bytecodeStart=60, bytecodeLength=1) void m3() { Object o; try (BufferedReader br = @@ -65,8 +65,8 @@ public class TestCaseTry { o = ""; } - @AliveRange(varName="o", bytecodeStart=12, bytecodeLength=96) - @AliveRange(varName="o", bytecodeStart=112, bytecodeLength=1) + @AliveRange(varName="o", bytecodeStart=12, bytecodeLength=46) + @AliveRange(varName="o", bytecodeStart=62, bytecodeLength=1) void m4() { String o; try (BufferedReader br = From 6921adecb8cb37b162181cd9665a34436c8b781c Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 20 Apr 2016 08:30:30 -0700 Subject: [PATCH 029/113] 8154445: JShell: Drop residual use of addReads from jshell Reviewed-by: alanb, ksrini --- .../share/classes/jdk/internal/jshell/remote/RemoteAgent.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java index 1a0cec3444f..f7d8e4a186d 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java @@ -113,7 +113,6 @@ class RemoteAgent { } Method doitMethod; try { - this.getClass().getModule().addReads(klass.getModule()); this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule()); doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class[0]); doitMethod.setAccessible(true); @@ -184,7 +183,6 @@ class RemoteAgent { break; } try { - this.getClass().getModule().addReads(klass.getModule()); Field var = klass.getDeclaredField(varname); var.setAccessible(true); Object res = var.get(null); From ecfc09db1610dd4e7bb52e45d1fe82d6fa4e3768 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 20 Apr 2016 08:35:44 -0700 Subject: [PATCH 030/113] 8153551: jshell tool: no longer a mechanism to see current feedback modes Reviewed-by: jlahoda --- .../classes/jdk/internal/jshell/tool/Feedback.java | 11 ++++++++--- langtools/test/jdk/jshell/ToolFormatTest.java | 8 +++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java index 8ebf1216611..958116c6987 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -606,6 +606,7 @@ class Feedback { fluffmsg("jshell.msg.feedback.mode", mode.name); } else { fluffmsg("jshell.msg.see", "/help /set feedback"); + printFeedbackModes(); } return valid; } @@ -671,13 +672,17 @@ class Feedback { } else { errorat("jshell.err.feedback.ambiguous.mode", umode); } - fluffmsg("jshell.msg.feedback.mode.following"); - modeMap.keySet().stream() - .forEach(mk -> fluff(" %s", mk)); + printFeedbackModes(); return null; } } + void printFeedbackModes() { + fluffmsg("jshell.msg.feedback.mode.following"); + modeMap.keySet().stream() + .forEach(mk -> fluff(" %s", mk)); + } + // Test if the format string is correctly final String nextFormat() { String format = at.next(); diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java index 6d61fba4671..f4758f8a876 100644 --- a/langtools/test/jdk/jshell/ToolFormatTest.java +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8148316 8148317 8151755 8152246 + * @bug 8148316 8148317 8151755 8152246 8153551 * @summary Tests for output customization * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -155,6 +155,12 @@ public class ToolFormatTest extends ReplToolTesting { } } + public void testShowFeedbackModes() { + test( + (a) -> assertCommandOutputContains(a, "/set feedback", "normal") + ); + } + public void testSetNewModeQuiet() { try { test( From 25c9be01d56ca788a421ec2cd9bfa7cd2e5b31ce Mon Sep 17 00:00:00 2001 From: Oleg Barbashov Date: Wed, 20 Apr 2016 17:17:56 -0700 Subject: [PATCH 031/113] 8151777: Add "@index" tag to the sampleapi generator Reviewed-by: ksrini, bpatel --- .../sampleapi/lib/sampleapi/SampleApi.java | 5 ++- .../generator/DocCommentGenerator.java | 43 +++++++++++++++---- .../sampleapi/generator/PackageGenerator.java | 4 +- .../sampleapi/lib/sampleapi/SampleApi.java | 5 ++- .../generator/DocCommentGenerator.java | 43 +++++++++++++++---- .../sampleapi/generator/PackageGenerator.java | 4 +- 6 files changed, 80 insertions(+), 24 deletions(-) diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java index 7b72cf0ba81..536787bcc26 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,5 +53,8 @@ public class SampleApi { public Fault(String msg) { super(msg); } + public Fault(String msg, Throwable th) { + super(msg, th); + } } } diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java index 691cd90eafe..b3ca960fe4e 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import javax.lang.model.element.Modifier; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; +import java.util.HashMap; +import java.util.Map; class DocCommentGenerator { @@ -99,14 +101,25 @@ class DocCommentGenerator { LITERAL("@literal", "Use < and > brackets instead of < and > escapes."), CODE("@code", "(i) -> new Abc((i > 0) ? (i << 1) : 0)"), LINK("@link", ""), - VALUE("@value", ""); + VALUE("@value", ""), + INDEX("@index", "", true); String tagName; String tagValue; + boolean counted; + Map counters; InlineTag(String tagName, String tagValue) { + this(tagName, tagValue, false); + } + + InlineTag(String tagName, String tagValue, boolean counted) { this.tagName = tagName; this.tagValue = tagValue; + this.counted = counted; + if (counted) { + counters = new HashMap<>(); + } } public String toString() { @@ -114,9 +127,14 @@ class DocCommentGenerator { } public String value(String value) { + String name = ((tagValue.length() != 0) ? " " + tagValue : "") + + ((value.length() != 0) ? " " + value : ""); + if (counted && !counters.containsKey(name)) { + counters.put(name, 0); + } return "{" + tagName - + ((tagValue.length() != 0) ? " " + tagValue : "") - + ((value.length() != 0) ? " " + value : "") + + name + + (counted ? "_" + counters.put(name, counters.get(name) + 1) : "") + "}"; } } @@ -179,7 +197,8 @@ class DocCommentGenerator { // public String getPackageComment() { - return Text.LOREMIPSUM + return InlineTag.INDEX.value("PackageCommentLabel") + " " + + Text.LOREMIPSUM + "\n

    " + Text.LIEUROPANLINGUES + "\n" + Text.CODE + "\n" + LinkTag.nextLink() @@ -192,7 +211,9 @@ class DocCommentGenerator { static int serialValIdx = 0; public String getBaseComment(JCClassDecl baseDecl, boolean toplevel) { - String buildComment = Text.LIEUROPANLINGUES + "\n"; + String buildComment = InlineTag.INDEX.value("BaseCommentLabel") + " "; + + buildComment += Text.LIEUROPANLINGUES + "\n"; buildComment += "

    It is possible to see inlined code:\n" + InlineTag.CODE @@ -237,8 +258,9 @@ class DocCommentGenerator { } public String getConstComment() { - String buildComment = Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; + String buildComment = InlineTag.INDEX.value("ConstCommentLabel") + " "; + buildComment += Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; buildComment += LinkTag.nextLink() + "\n"; buildComment += LinkTag.nextSee() + "\n"; buildComment += Tag.SINCE + "\n"; @@ -249,8 +271,9 @@ class DocCommentGenerator { public String getFieldComment(JCClassDecl baseDecl, JCVariableDecl varDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; + String buildComment = InlineTag.INDEX.value("FieldCommentLabel") + " "; + buildComment += Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; Set mods = varDecl.getModifiers().getFlags(); String varName = varDecl.getName().toString(); @@ -299,7 +322,9 @@ class DocCommentGenerator { public String getMethodComment(JCClassDecl baseDecl, JCMethodDecl methodDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; + String buildComment = InlineTag.INDEX.value("MethodCommentLabel") + " "; + + buildComment += Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; buildComment += "

    " + LinkTag.nextLink() + "\n"; diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java index 05e5524fc0d..8e7ed7c1d4c 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,7 +125,7 @@ public class PackageGenerator { processTopLevel((Element)node); } } catch (ParserConfigurationException | SAXException | IOException e) { - throw new Fault("Error parsing dataset " + dsName); + throw new Fault("Error parsing dataset " + dsName, e); } fx = false; diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java index 7b72cf0ba81..536787bcc26 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,5 +53,8 @@ public class SampleApi { public Fault(String msg) { super(msg); } + public Fault(String msg, Throwable th) { + super(msg, th); + } } } diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java index 691cd90eafe..b3ca960fe4e 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import javax.lang.model.element.Modifier; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; +import java.util.HashMap; +import java.util.Map; class DocCommentGenerator { @@ -99,14 +101,25 @@ class DocCommentGenerator { LITERAL("@literal", "Use < and > brackets instead of < and > escapes."), CODE("@code", "(i) -> new Abc((i > 0) ? (i << 1) : 0)"), LINK("@link", ""), - VALUE("@value", ""); + VALUE("@value", ""), + INDEX("@index", "", true); String tagName; String tagValue; + boolean counted; + Map counters; InlineTag(String tagName, String tagValue) { + this(tagName, tagValue, false); + } + + InlineTag(String tagName, String tagValue, boolean counted) { this.tagName = tagName; this.tagValue = tagValue; + this.counted = counted; + if (counted) { + counters = new HashMap<>(); + } } public String toString() { @@ -114,9 +127,14 @@ class DocCommentGenerator { } public String value(String value) { + String name = ((tagValue.length() != 0) ? " " + tagValue : "") + + ((value.length() != 0) ? " " + value : ""); + if (counted && !counters.containsKey(name)) { + counters.put(name, 0); + } return "{" + tagName - + ((tagValue.length() != 0) ? " " + tagValue : "") - + ((value.length() != 0) ? " " + value : "") + + name + + (counted ? "_" + counters.put(name, counters.get(name) + 1) : "") + "}"; } } @@ -179,7 +197,8 @@ class DocCommentGenerator { // public String getPackageComment() { - return Text.LOREMIPSUM + return InlineTag.INDEX.value("PackageCommentLabel") + " " + + Text.LOREMIPSUM + "\n

    " + Text.LIEUROPANLINGUES + "\n" + Text.CODE + "\n" + LinkTag.nextLink() @@ -192,7 +211,9 @@ class DocCommentGenerator { static int serialValIdx = 0; public String getBaseComment(JCClassDecl baseDecl, boolean toplevel) { - String buildComment = Text.LIEUROPANLINGUES + "\n"; + String buildComment = InlineTag.INDEX.value("BaseCommentLabel") + " "; + + buildComment += Text.LIEUROPANLINGUES + "\n"; buildComment += "

    It is possible to see inlined code:\n" + InlineTag.CODE @@ -237,8 +258,9 @@ class DocCommentGenerator { } public String getConstComment() { - String buildComment = Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; + String buildComment = InlineTag.INDEX.value("ConstCommentLabel") + " "; + buildComment += Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; buildComment += LinkTag.nextLink() + "\n"; buildComment += LinkTag.nextSee() + "\n"; buildComment += Tag.SINCE + "\n"; @@ -249,8 +271,9 @@ class DocCommentGenerator { public String getFieldComment(JCClassDecl baseDecl, JCVariableDecl varDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; + String buildComment = InlineTag.INDEX.value("FieldCommentLabel") + " "; + buildComment += Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; Set mods = varDecl.getModifiers().getFlags(); String varName = varDecl.getName().toString(); @@ -299,7 +322,9 @@ class DocCommentGenerator { public String getMethodComment(JCClassDecl baseDecl, JCMethodDecl methodDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; + String buildComment = InlineTag.INDEX.value("MethodCommentLabel") + " "; + + buildComment += Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; buildComment += "

    " + LinkTag.nextLink() + "\n"; diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java index 05e5524fc0d..8e7ed7c1d4c 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,7 +125,7 @@ public class PackageGenerator { processTopLevel((Element)node); } } catch (ParserConfigurationException | SAXException | IOException e) { - throw new Fault("Error parsing dataset " + dsName); + throw new Fault("Error parsing dataset " + dsName, e); } fx = false; From c413f5eb4419bdf83ddcfc672a4230e42a0e36fa Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:16 -0700 Subject: [PATCH 032/113] Added tag jdk-9+115 for changeset c36230ee15d9 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 8032358a539..e8881f37c97 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -357,3 +357,4 @@ f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 3d4117c36559b344a73f786d39cc7626b4d8e2c0 jdk-9+112 4e87682893e662421af10a62d29ae822ce0fea04 jdk-9+113 cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114 +31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115 From e85033c628f607fee4e9365938534ab56cedbfd3 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Tue, 22 Mar 2016 13:14:12 +0100 Subject: [PATCH 033/113] 8048146: sjavac uses unexpected exit code of -1 Changed exit codes for sjavac Reviewed-by: jlahoda --- .../sun/tools/sjavac/CompileJavaPackages.java | 7 ++--- .../sun/tools/sjavac/client/ClientMain.java | 8 +++-- .../sun/tools/sjavac/client/SjavacClient.java | 25 +++++++++------- .../tools/sjavac/comp/CompilationService.java | 21 +++++++++----- .../sun/tools/sjavac/comp/PooledSjavac.java | 3 +- .../com/sun/tools/sjavac/comp/SjavacImpl.java | 29 ++++++++++--------- .../sjavac/server/CompilationSubResult.java | 16 +++++----- .../tools/sjavac/server/IdleResetSjavac.java | 6 ++-- .../tools/sjavac/server/RequestHandler.java | 5 ++-- .../sun/tools/sjavac/server/ServerMain.java | 6 ++-- .../com/sun/tools/sjavac/server/Sjavac.java | 8 ++--- .../sun/tools/sjavac/server/SjavacServer.java | 6 ++-- langtools/test/tools/sjavac/HiddenFiles.java | 3 +- langtools/test/tools/sjavac/IdleShutdown.java | 6 ++-- .../tools/sjavac/IncludeExcludePatterns.java | 3 +- .../test/tools/sjavac/PooledExecution.java | 8 ++--- 16 files changed, 84 insertions(+), 76 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java index f6ac5d2ad44..18a079dad9d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java @@ -26,8 +26,6 @@ package com.sun.tools.sjavac; import java.io.File; -import java.io.IOException; -import java.io.Writer; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -42,9 +40,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.regex.Pattern; -import java.util.stream.Stream; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; @@ -283,7 +280,7 @@ public class CompileJavaPackages implements Transformer { } // Check the return values. - if (subResult.returnCode != 0) { + if (subResult.result != Result.OK) { rc = false; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java index 54c1e51952f..5ba63fed8d5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java @@ -28,6 +28,8 @@ package com.sun.tools.sjavac.client; import java.io.OutputStreamWriter; import java.io.Writer; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.AutoFlushWriter; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -58,7 +60,7 @@ public class ClientMain { options = Options.parseArgs(args); } catch (IllegalArgumentException e) { Log.error(e.getMessage()); - return -1; + return Result.CMDERR.exitCode; } Log.setLogLevel(options.getLogLevel()); @@ -73,13 +75,13 @@ public class ClientMain { Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); // Perform compilation - int rc = sjavac.compile(args); + Result result = sjavac.compile(args); // If sjavac is running in the foreground we should shut it down at this point if (!useServer) { sjavac.shutdown(); } - return rc; + return result.exitCode; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index 37fb47890c2..570530d7028 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -26,23 +26,20 @@ package com.sun.tools.sjavac.client; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; -import java.io.Writer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Scanner; -import java.util.stream.Stream; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.options.OptionHelper; @@ -116,8 +113,8 @@ public class SjavacClient implements Sjavac { } @Override - public int compile(String[] args) { - int result = -1; + public Result compile(String[] args) { + Result result = null; try (Socket socket = tryConnect()) { PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); @@ -150,22 +147,28 @@ public class SjavacClient implements Sjavac { } if (type.equals(SjavacServer.LINE_TYPE_RC)) { - result = Integer.parseInt(content); + result = Main.Result.valueOf(content); } } } catch (PortFileInaccessibleException e) { Log.error("Port file inaccessible."); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } catch (IOException ioe) { Log.error("IOException caught during compilation: " + ioe.getMessage()); Log.debug(ioe); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Restore interrupt Log.error("Compilation interrupted."); Log.debug(ie); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } + + if (result == null) { + // No LINE_TYPE_RC was found. + result = Result.ERROR; + } + return result; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java index 0eb4f7e2358..bf55947827c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java @@ -42,6 +42,8 @@ import javax.tools.ToolProvider; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Dependencies; import com.sun.tools.javac.util.ListBuffer; @@ -80,7 +82,7 @@ public class CompilationService { Dependencies.GraphDependencies.preRegister(context); // Now setup the actual compilation - CompilationSubResult compilationResult = new CompilationSubResult(0); + CompilationSubResult compilationResult = new CompilationSubResult(Result.OK); // First deal with explicit source files on cmdline and in at file ListBuffer explicitJFOs = new ListBuffer<>(); @@ -97,7 +99,7 @@ public class CompilationService { // Create a log to capture compiler output StringWriter stderrLog = new StringWriter(); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + Result result; PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs); @@ -120,20 +122,23 @@ public class CompilationService { task.addTaskListener(pubApiCollector); task.addTaskListener(papVerifier); logJavacInvocation(args); - rc = task.doCall(); - Log.debug("javac returned with code " + rc); + result = task.doCall(); + Log.debug("javac result: " + result); sfm.flush(); + } else { + result = Result.ERROR; } } catch (Exception e) { Log.error(Util.getStackTrace(e)); stderrLog.append(Util.getStackTrace(e)); - rc = com.sun.tools.javac.main.Main.Result.ERROR; + result = Result.ERROR; } compilationResult.packageArtifacts = sfm.getPackageArtifacts(); - if (papVerifier.errorsDiscovered()) - rc = com.sun.tools.javac.main.Main.Result.ERROR; + if (papVerifier.errorsDiscovered()) { + result = Result.ERROR; + } compilationResult.packageDependencies = depsCollector.getDependencies(false); compilationResult.packageCpDependencies = depsCollector.getDependencies(true); @@ -141,7 +146,7 @@ public class CompilationService { compilationResult.packagePubapis = pubApiCollector.getPubApis(true); compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); compilationResult.stderr = stderrLog.toString(); - compilationResult.returnCode = rc.exitCode; + compilationResult.result = result; return compilationResult; } catch (IOException e) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java index 82be0ae3b16..f84d52d5296 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java @@ -25,6 +25,7 @@ package com.sun.tools.sjavac.comp; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.server.Sjavac; @@ -54,7 +55,7 @@ public class PooledSjavac implements Sjavac { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { Log log = Log.get(); try { return pool.submit(() -> { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index 4c39a70f779..3553fcf9075 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -41,6 +41,7 @@ import java.util.stream.Stream; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Context; import com.sun.tools.sjavac.JavacState; import com.sun.tools.sjavac.Log; @@ -69,36 +70,36 @@ import javax.tools.JavaFileManager; public class SjavacImpl implements Sjavac { @Override - public int compile(String[] args) { + public Result compile(String[] args) { Options options; try { options = Options.parseArgs(args); } catch (IllegalArgumentException e) { Log.error(e.getMessage()); - return RC_FATAL; + return Result.CMDERR; } if (!validateOptions(options)) - return RC_FATAL; + return Result.CMDERR; if (srcDstOverlap(options.getSources(), options.getDestDir())) { - return RC_FATAL; + return Result.CMDERR; } if (!createIfMissing(options.getDestDir())) - return RC_FATAL; + return Result.ERROR; Path stateDir = options.getStateDir(); if (stateDir != null && !createIfMissing(options.getStateDir())) - return RC_FATAL; + return Result.ERROR; Path gensrc = options.getGenSrcDir(); if (gensrc != null && !createIfMissing(gensrc)) - return RC_FATAL; + return Result.ERROR; Path hdrdir = options.getHeaderDir(); if (hdrdir != null && !createIfMissing(hdrdir)) - return RC_FATAL; + return Result.ERROR; if (stateDir == null) { // Prepare context. Direct logging to our byte array stream. @@ -113,7 +114,7 @@ public class SjavacImpl implements Sjavac { .filter(arg -> !arg.startsWith(Option.SERVER.arg)) .toArray(String[]::new); // Compile - Main.Result result = new Main("javac", printWriter).compile(passThroughArgs, context); + Result result = new Main("javac", printWriter).compile(passThroughArgs, context); // Process compiler output (which is always errors) printWriter.flush(); @@ -128,7 +129,7 @@ public class SjavacImpl implements Sjavac { throw new UncheckedIOException(es); } } - return result.exitCode; + return result; } else { // Load the prev build state database. @@ -166,7 +167,7 @@ public class SjavacImpl implements Sjavac { if (sources.isEmpty()) { Log.error("Found nothing to compile!"); - return RC_FATAL; + return Result.ERROR; } @@ -292,15 +293,15 @@ public class SjavacImpl implements Sjavac { javac_state.removeSuperfluousArtifacts(recently_compiled); } - return rc[0] ? RC_OK : RC_FATAL; + return rc[0] ? Result.OK : Result.ERROR; } catch (ProblemException e) { // For instance make file list mismatch. Log.error(e.getMessage()); Log.debug(e); - return RC_FATAL; + return Result.ERROR; } catch (Exception e) { Log.error(e); - return RC_FATAL; + return Result.ERROR; } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java index 1b96379b79d..5a60aa2bef7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.pubapi.PubApi; /** @@ -44,10 +45,7 @@ public class CompilationSubResult implements Serializable { static final long serialVersionUID = 46739181113L; - // Return code constants - public final static int ERROR_FATAL = -1; - - public int returnCode; + public Result result; public Map> packageArtifacts = new HashMap<>(); public Map>> packageDependencies = new HashMap<>(); public Map>> packageCpDependencies = new HashMap<>(); @@ -56,11 +54,11 @@ public class CompilationSubResult implements Serializable { public String stdout = ""; public String stderr = ""; - public CompilationSubResult(int returnCode) { - this.returnCode = returnCode; + public CompilationSubResult(Result result) { + this.result = result; } - public void setReturnCode(int returnCode) { - this.returnCode = returnCode; + public void setResult(Result result) { + this.result = result; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java index 8b7d17b0c0c..724c5062d5d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java @@ -25,11 +25,9 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Timer; import java.util.TimerTask; @@ -66,7 +64,7 @@ public class IdleResetSjavac implements Sjavac { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { startCall(); try { return delegate.compile(args); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java index 62ba3b995a9..e26a5c77766 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java @@ -25,6 +25,7 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -100,10 +101,10 @@ public class RequestHandler extends Thread { checkInternalErrorLog(); // Perform compilation - int rc = sjavac.compile(args); + Main.Result rc = sjavac.compile(args); // Send return code back to client - out.println(LINE_TYPE_RC + ":" + rc); + out.println(LINE_TYPE_RC + ":" + rc.name()); // Check for internal errors again. checkInternalErrorLog(); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java index 6690c3ece70..39c22966e22 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java @@ -32,6 +32,8 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.Thread.UncaughtExceptionHandler; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log.Level; import com.sun.tools.sjavac.server.log.LazyInitFileLog; @@ -75,7 +77,7 @@ public class ServerMain { // Any options other than --startserver? if (args.length > 1) { Log.error("When spawning a background server, only a single --startserver argument is allowed."); - return 1; + return Result.CMDERR.exitCode; } int exitCode; @@ -84,7 +86,7 @@ public class ServerMain { exitCode = server.startServer(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(); - exitCode = -1; + exitCode = Result.ERROR.exitCode; } return exitCode; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java index 91063c5a809..dd3c43db74d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main.Result; + import java.io.Writer; @@ -38,10 +40,6 @@ import java.io.Writer; * deletion without notice. */ public interface Sjavac { - - final static int RC_FATAL = -1; - final static int RC_OK = 0; - - int compile(String[] args); + Result compile(String[] args); void shutdown(); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java index 16450295afe..d7dcc203ade 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java @@ -40,6 +40,8 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.client.PortFileInaccessibleException; @@ -167,7 +169,7 @@ public class SjavacServer implements Terminable { if (portFile.containsPortInfo()) { Log.debug("Javac server not started because portfile exists!"); portFile.unlock(); - return -1; + return Result.ERROR.exitCode; } // .-----------. .--------. .------. @@ -221,7 +223,7 @@ public class SjavacServer implements Terminable { // Shut down sjavac.shutdown(); - return 0; + return Result.OK.exitCode; } @Override diff --git a/langtools/test/tools/sjavac/HiddenFiles.java b/langtools/test/tools/sjavac/HiddenFiles.java index f6a7c7ba91d..237146af29b 100644 --- a/langtools/test/tools/sjavac/HiddenFiles.java +++ b/langtools/test/tools/sjavac/HiddenFiles.java @@ -36,6 +36,7 @@ * @run main Wrapper HiddenFiles */ +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.server.Sjavac; @@ -62,6 +63,6 @@ public class HiddenFiles extends SjavacBase { "-d", BIN.toString(), "--state-dir=" + STATE_DIR); - Assert.check(rc == Sjavac.RC_FATAL, "Compilation succeeded unexpectedly."); + Assert.check(rc == Result.ERROR.exitCode, "Compilation succeeded unexpectedly."); } } diff --git a/langtools/test/tools/sjavac/IdleShutdown.java b/langtools/test/tools/sjavac/IdleShutdown.java index 7178d6c89e5..334f03149c2 100644 --- a/langtools/test/tools/sjavac/IdleShutdown.java +++ b/langtools/test/tools/sjavac/IdleShutdown.java @@ -29,9 +29,9 @@ * @build Wrapper * @run main Wrapper IdleShutdown */ -import java.io.Writer; import java.util.concurrent.atomic.AtomicLong; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.server.IdleResetSjavac; import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Terminable; @@ -103,13 +103,13 @@ public class IdleShutdown { public void shutdown() { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { // Attempt to trigger idle timeout during a call by sleeping try { Thread.sleep(TIMEOUT_MS + 1000); } catch (InterruptedException e) { } - return 0; + return Result.OK; } } } diff --git a/langtools/test/tools/sjavac/IncludeExcludePatterns.java b/langtools/test/tools/sjavac/IncludeExcludePatterns.java index 41b02a3ddbe..6e38aadc218 100644 --- a/langtools/test/tools/sjavac/IncludeExcludePatterns.java +++ b/langtools/test/tools/sjavac/IncludeExcludePatterns.java @@ -33,6 +33,7 @@ * @run main Wrapper IncludeExcludePatterns */ +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.server.Sjavac; @@ -131,7 +132,7 @@ public class IncludeExcludePatterns extends SjavacBase { int rc = compile((Object[]) args.split(" ")); // Compilation should always pass in these tests - Assert.check(rc == Sjavac.RC_OK, "Compilation failed unexpectedly."); + Assert.check(rc == Result.OK.exitCode, "Compilation failed unexpectedly."); // The resulting .class files should correspond to the visible source files Set result = allFilesInDir(BIN); diff --git a/langtools/test/tools/sjavac/PooledExecution.java b/langtools/test/tools/sjavac/PooledExecution.java index ccd4265fee2..bfa24b4fdcd 100644 --- a/langtools/test/tools/sjavac/PooledExecution.java +++ b/langtools/test/tools/sjavac/PooledExecution.java @@ -30,12 +30,10 @@ * @build Wrapper * @run main Wrapper PooledExecution */ -import java.io.PrintWriter; -import java.io.Writer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import com.sun.tools.sjavac.Log; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.server.Sjavac; @@ -111,7 +109,7 @@ public class PooledExecution { AtomicInteger activeRequests = new AtomicInteger(0); @Override - public int compile(String[] args) { + public Result compile(String[] args) { leftToStart.countDown(); int numActiveRequests = activeRequests.incrementAndGet(); System.out.printf("Left to start: %2d / Currently active: %2d%n", @@ -125,7 +123,7 @@ public class PooledExecution { } activeRequests.decrementAndGet(); System.out.println("Task completed"); - return 0; + return Result.OK; } @Override From b51a55a78cb36b057e1ee217f2b634a9773fbb5c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 6 Apr 2016 10:50:19 +0300 Subject: [PATCH 034/113] 8153277: [TESTBUG] gc/arguments/TestMaxMinHeapFreeRatioFlags is too sensitive for stray allocations in verifyRatio Reviewed-by: mgerdin, dfazunen --- hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index 055ea672adb..af37af4947c 100644 --- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -168,6 +168,11 @@ public class TestMaxMinHeapFreeRatioFlags { long maxHeapSize = getMax(); int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1); + // Initial checks. This also links up everything in these helper methods, + // in case it brings more garbage. + forceGC(gcTries); + verifyRatio(minRatio, maxRatio); + // commit 0.5 of total heap size to have enough space // to both shink and expand while (getCommitted() < maxHeapSize / 2) { @@ -215,7 +220,6 @@ public class TestMaxMinHeapFreeRatioFlags { if (previouslyCommitted <= getCommitted()) { throw new RuntimeException("Heap was not shrinked."); } - } public static void forceGC(int gcTries) { From 0c06163b35d78b2ef3c006593fc241528b796a20 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 6 Apr 2016 13:32:48 +0200 Subject: [PATCH 035/113] 8077144: Concurrent mark initialization takes too long Remove per-marking thread liveness bitmaps and recreate liveness bitmap concurrently after the cleanup pause. Reviewed-by: mgerdin, ehelin, kbarrett --- .../share/vm/gc/g1/concurrentMarkThread.cpp | 5 + .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 817 ++++++++---------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 151 +--- .../vm/gc/g1/g1ConcurrentMark.inline.hpp | 147 +--- hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp | 7 +- .../share/vm/gc/g1/g1OopClosures.inline.hpp | 6 +- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 3 + hotspot/src/share/vm/utilities/bitMap.cpp | 4 + hotspot/src/share/vm/utilities/bitMap.hpp | 7 + hotspot/test/gc/g1/Test2GbHeap.java | 16 +- 10 files changed, 452 insertions(+), 711 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index c72cbae1474..7eef582e3db 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -183,6 +183,11 @@ void ConcurrentMarkThread::run_service() { } } while (cm()->restart_for_overflow()); + if (!cm()->has_aborted()) { + G1ConcPhaseTimer t(_cm, "Concurrent Create Live Data"); + cm()->create_live_data(); + } + double end_time = os::elapsedVTime(); // Update the total virtual time before doing this, since it will try // to measure it to get the vtime for this marking. We purposely diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 2ed3dd0f4ed..a181b467c7d 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -48,6 +48,7 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/vmGCOperations.hpp" #include "logging/log.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -355,10 +356,8 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _sleep_factor(0.0), _marking_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/), - _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >> - CardTableModRefBS::card_shift, - false /* in_resource_area*/), + _region_live_bm(), + _card_live_bm(), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -390,8 +389,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _parallel_workers(NULL), - _count_card_bitmaps(NULL), - _count_marked_bytes(NULL), _completed_initialization(false) { _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage); @@ -502,43 +499,28 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* return; } + allocate_internal_bitmaps(); + + if (G1PretouchAuxiliaryMemory) { + pretouch_internal_bitmaps(); + } + _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); - _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); - _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC); - - BitMap::idx_t card_bm_size = _card_bm.size(); - // so that the assertion in MarkingTaskQueue::task_queue doesn't fail _active_tasks = _max_worker_id; - uint max_regions = _g1h->max_regions(); for (uint i = 0; i < _max_worker_id; ++i) { G1CMTaskQueue* task_queue = new G1CMTaskQueue(); task_queue->initialize(); _task_queues->register_queue(i, task_queue); - _count_card_bitmaps[i] = BitMap(card_bm_size, false); - _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); - - _tasks[i] = new G1CMTask(i, this, - _count_marked_bytes[i], - &_count_card_bitmaps[i], - task_queue, _task_queues); + _tasks[i] = new G1CMTask(i, this, task_queue, _task_queues); _accum_task_vtime[i] = 0.0; } - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_bottom_card_num = - intptr_t(uintptr_t(_g1h->reserved_region().start()) >> - CardTableModRefBS::card_shift); - - // Clear all the liveness counting data - clear_all_count_data(); - // so that the call below can read a sensible value _heap_start = g1h->reserved_region().start(); set_non_marking_state(); @@ -716,10 +698,11 @@ void G1ConcurrentMark::cleanup_for_next_mark() { clear_bitmap(_nextMarkBitMap, _parallel_workers, true); - // Clear the liveness counting data. If the marking has been aborted, the abort() + // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_all_count_data(); + clear_all_live_data(_parallel_workers); + DEBUG_ONLY(verify_all_live_data()); } // Repeat the asserts from above. @@ -1107,14 +1090,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // marking due to overflowing the global mark stack. reset_marking_state(); } else { - { - GCTraceTime(Debug, gc, phases) trace("Aggregate Data", _gc_timer_cm); - - // Aggregate the per-task counting data that we have accumulated - // while marking. - aggregate_count_data(); - } - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); // We're done with marking. // This is the end of the marking cycle, we're expected all @@ -1150,17 +1125,81 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { _gc_tracer_cm->report_object_count_after_gc(&is_alive); } -// Base class of the closures that finalize and verify the -// liveness counting data. -class G1CMCountDataClosureBase: public HeapRegionClosure { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - +// Helper class that provides functionality to generate the Live Data Count +// information. +class G1LiveDataHelper VALUE_OBJ_CLASS_SPEC { +private: BitMap* _region_bm; BitMap* _card_bm; + // The card number of the bottom of the G1 heap. Used for converting addresses + // to bitmap indices quickly. + BitMap::idx_t _heap_card_bias; + + // Utility routine to set an exclusive range of bits on the given + // bitmap, optimized for very small ranges. + // There must be at least one bit to set. + inline void set_card_bitmap_range(BitMap* bm, + BitMap::idx_t start_idx, + BitMap::idx_t end_idx) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one bit"); + assert(end_idx <= bm->size(), "sanity"); + + // For small ranges use a simple loop; otherwise use set_range or + // use par_at_put_range (if parallel). The range is made up of the + // cards that are spanned by an object/mem region so 8 cards will + // allow up to object sizes up to 4K to be handled using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + bm->set_bit(i); + } + } else { + bm->set_range(start_idx, end_idx); + } + } + + // We cache the last mark set. This avoids setting the same bit multiple times. + // This is particularly interesting for dense bitmaps, as this avoids doing + // lots of work most of the time. + BitMap::idx_t _last_marked_bit_idx; + + // Mark the card liveness bitmap for the object spanning from start to end. + void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { + BitMap::idx_t start_idx = card_live_bitmap_index_for(start); + BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); + + assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); + + if (start_idx == _last_marked_bit_idx) { + start_idx++; + } + if (start_idx == end_idx) { + return; + } + + // Set the bits in the card bitmap for the cards spanned by this object. + set_card_bitmap_range(_card_bm, start_idx, end_idx); + _last_marked_bit_idx = end_idx - 1; + } + + void reset_mark_cache() { + _last_marked_bit_idx = (BitMap::idx_t)-1; + } + +public: + // Returns the index in the per-card liveness count bitmap + // for the given address + inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + BitMap::idx_t card_num = (BitMap::idx_t)(uintptr_t(addr) >> CardTableModRefBS::card_shift); + return card_num - _heap_card_bias; + } + // Takes a region that's not empty (i.e., it has at least one // live object in it and sets its corresponding bit on the region // bitmap to 1. @@ -1169,136 +1208,128 @@ protected: _region_bm->par_at_put(index, true); } -public: - G1CMCountDataClosureBase(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm): - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _region_bm(region_bm), _card_bm(card_bm) { } -}; + // Mark the range of bits covered by allocations done since the last marking + // in the given heap region, i.e. from NTAMS to top of the given region. + // Returns if there has been some allocation in this region since the last marking. + bool mark_allocated_since_marking(HeapRegion* hr) { + reset_mark_cache(); -// Closure that calculates the # live objects per region. Used -// for verification purposes during the cleanup pause. -class CalcLiveObjectsClosure: public G1CMCountDataClosureBase { - G1CMBitMapRO* _bm; - size_t _region_marked_bytes; + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); -public: - CalcLiveObjectsClosure(G1CMBitMapRO *bm, G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm), - _bm(bm), _region_marked_bytes(0) { } + assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + // Mark the allocated-since-marking portion... + if (ntams < top) { + mark_card_bitmap_range(ntams, top); + return true; + } else { + return false; + } + } + + // Mark the range of bits covered by live objects on the mark bitmap between + // bottom and NTAMS of the given region. + // Returns the number of live bytes marked within that area for the given + // heap region. + size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { + reset_mark_cache(); + + size_t marked_bytes = 0; - bool doHeapRegion(HeapRegion* hr) { HeapWord* ntams = hr->next_top_at_mark_start(); HeapWord* start = hr->bottom(); + if (ntams <= start) { + // Skip empty regions. + return 0; + } else if (hr->is_humongous()) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), "Preconditions not met - " "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, p2i(start), p2i(ntams), p2i(hr->end())); // Find the first marked object at or after "start". - start = _bm->getNextMarkedWordAddress(start, ntams); - - size_t marked_bytes = 0; - + start = mark_bitmap->getNextMarkedWordAddress(start, ntams); while (start < ntams) { oop obj = oop(start); int obj_sz = obj->size(); HeapWord* obj_end = start + obj_sz; - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(obj_end); + assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); - // Note: if we're looking at the last region in heap - obj_end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(obj_end) && !_ct_bs->is_card_aligned(obj_end)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - - // Set the bits in the card BM for the cards spanned by this object. - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); + mark_card_bitmap_range(start, obj_end); // Add the size of this object to the number of marked bytes. marked_bytes += (size_t)obj_sz * HeapWordSize; - // This will happen if we are handling a humongous object that spans - // several heap regions. - if (obj_end > hr->end()) { - break; - } // Find the next marked object after this one. - start = _bm->getNextMarkedWordAddress(obj_end, ntams); + start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); } - // Mark the allocated-since-marking portion... - HeapWord* top = hr->top(); - if (ntams < top) { - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); - - // This definitely means the region has live objects. - set_bit_for_region(hr); - } - - // Update the live region bitmap. - if (marked_bytes > 0) { - set_bit_for_region(hr); - } - - // Set the marked bytes for the current region so that - // it can be queried by a calling verification routine - _region_marked_bytes = marked_bytes; - - return false; + return marked_bytes; } - size_t region_marked_bytes() const { return _region_marked_bytes; } + G1LiveDataHelper(BitMap* region_bm, + BitMap* card_bm): + _region_bm(region_bm), + _card_bm(card_bm) { + //assert(region_bm != NULL, ""); + assert(card_bm != NULL, ""); + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_card_bias = + (BitMap::idx_t)(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> CardTableModRefBS::card_shift); + } }; -// Heap region closure used for verifying the counting data -// that was accumulated concurrently and aggregated during +// Heap region closure used for verifying the live count data +// that was created concurrently and finalized during // the remark pause. This closure is applied to the heap // regions during the STW cleanup pause. - -class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { +class G1VerifyLiveDataHRClosure: public HeapRegionClosure { +private: G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CalcLiveObjectsClosure _calc_cl; - BitMap* _region_bm; // Region BM to be verified - BitMap* _card_bm; // Card BM to be verified + G1CMBitMap* _mark_bitmap; + G1LiveDataHelper _calc_helper; + + BitMap* _act_region_bm; // Region BM to be verified + BitMap* _act_card_bm; // Card BM to be verified BitMap* _exp_region_bm; // Expected Region BM values BitMap* _exp_card_bm; // Expected card BM values int _failures; + // Updates the live data count for the given heap region and returns the number + // of bytes marked. + size_t create_live_data_count(HeapRegion* hr) { + size_t bytes_marked = _calc_helper.mark_marked_during_marking(_mark_bitmap, hr); + bool allocated_since_marking = _calc_helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || bytes_marked > 0) { + _calc_helper.set_bit_for_region(hr); + } + return bytes_marked; + } + public: - VerifyLiveObjectDataHRClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm, - BitMap* exp_region_bm, - BitMap* exp_card_bm) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _calc_cl(_cm->nextMarkBitMap(), g1h, exp_region_bm, exp_card_bm), - _region_bm(region_bm), _card_bm(card_bm), - _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), + G1VerifyLiveDataHRClosure(G1CollectedHeap* g1h, + G1CMBitMap* mark_bitmap, + BitMap* act_region_bm, + BitMap* act_card_bm, + BitMap* exp_region_bm, + BitMap* exp_card_bm) : + _g1h(g1h), + _mark_bitmap(mark_bitmap), + _calc_helper(exp_region_bm, exp_card_bm), + _act_region_bm(act_region_bm), + _act_card_bm(act_card_bm), + _exp_region_bm(exp_region_bm), + _exp_card_bm(exp_card_bm), _failures(0) { } int failures() const { return _failures; } @@ -1306,35 +1337,16 @@ public: bool doHeapRegion(HeapRegion* hr) { int failures = 0; - // Call the CalcLiveObjectsClosure to walk the marking bitmap for - // this region and set the corresponding bits in the expected region - // and card bitmaps. - bool res = _calc_cl.doHeapRegion(hr); - assert(res == false, "should be continuing"); - - // Verify the marked bytes for this region. - size_t exp_marked_bytes = _calc_cl.region_marked_bytes(); + // Walk the marking bitmap for this region and set the corresponding bits + // in the expected region and card bitmaps. + size_t exp_marked_bytes = create_live_data_count(hr); size_t act_marked_bytes = hr->next_marked_bytes(); + // Verify the marked bytes for this region. - if (exp_marked_bytes > act_marked_bytes) { - if (hr->is_starts_humongous()) { - // For start_humongous regions, the size of the whole object will be - // in exp_marked_bytes. - HeapRegion* region = hr; - int num_regions; - for (num_regions = 0; region != NULL; num_regions++) { - region = _g1h->next_region_in_humongous(region); - } - if ((num_regions-1) * HeapRegion::GrainBytes >= exp_marked_bytes) { - failures += 1; - } else if (num_regions * HeapRegion::GrainBytes < exp_marked_bytes) { - failures += 1; - } - } else { - // We're not OK if expected marked bytes > actual marked bytes. It means - // we have missed accounting some objects during the actual marking. - failures += 1; - } + if (exp_marked_bytes != act_marked_bytes) { + failures += 1; + } else if (exp_marked_bytes > HeapRegion::GrainBytes) { + failures += 1; } // Verify the bit, for this region, in the actual and expected @@ -1344,7 +1356,7 @@ public: BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); bool expected = _exp_region_bm->at(index); - bool actual = _region_bm->at(index); + bool actual = _act_region_bm->at(index); if (expected && !actual) { failures += 1; } @@ -1353,12 +1365,12 @@ public: // region match. We have an error if we have a set bit in the expected // bit map and the corresponding bit in the actual bitmap is not set. - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(hr->bottom()); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(hr->top()); + BitMap::idx_t start_idx = _calc_helper.card_live_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _calc_helper.card_live_bitmap_index_for(hr->top()); for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { expected = _exp_card_bm->at(i); - actual = _card_bm->at(i); + actual = _act_card_bm->at(i); if (expected && !actual) { failures += 1; @@ -1373,137 +1385,100 @@ public: } }; -class G1ParVerifyFinalCountTask: public AbstractGangTask { +class G1VerifyLiveDataTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; + G1CMBitMap* _mark_bitmap; BitMap* _actual_region_bm; BitMap* _actual_card_bm; - uint _n_workers; - - BitMap* _expected_region_bm; - BitMap* _expected_card_bm; + BitMap _expected_region_bm; + BitMap _expected_card_bm; int _failures; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm, - BitMap* expected_region_bm, BitMap* expected_card_bm) - : AbstractGangTask("G1 verify final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), - _failures(0), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { + G1VerifyLiveDataTask(G1CollectedHeap* g1h, + G1CMBitMap* bitmap, + BitMap* region_bm, + BitMap* card_bm, + uint n_workers) + : AbstractGangTask("G1 verify final counting"), + _g1h(g1h), + _mark_bitmap(bitmap), + _actual_region_bm(region_bm), + _actual_card_bm(card_bm), + _expected_region_bm(region_bm->size(), true /* in_resource_area */), + _expected_card_bm(card_bm->size(), true /* in_resource_area */), + _failures(0), + _hr_claimer(n_workers) { assert(VerifyDuringGC, "don't call this otherwise"); - assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); - assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); } void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); + G1VerifyLiveDataHRClosure cl(_g1h, + _mark_bitmap, + _actual_region_bm, + _actual_card_bm, + &_expected_region_bm, + &_expected_card_bm); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - VerifyLiveObjectDataHRClosure verify_cl(_g1h, - _actual_region_bm, _actual_card_bm, - _expected_region_bm, - _expected_card_bm); - - _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); - - Atomic::add(verify_cl.failures(), &_failures); + Atomic::add(cl.failures(), &_failures); } int failures() const { return _failures; } }; -// Closure that finalizes the liveness counting data. -// Used during the cleanup pause. -// Sets the bits corresponding to the interval [NTAMS, top] -// (which contains the implicitly live objects) in the -// card liveness bitmap. Also sets the bit for each region, -// containing live data, in the region liveness bitmap. +class G1FinalizeLiveDataTask: public AbstractGangTask { + // Finalizes the liveness counting data. + // Sets the bits corresponding to the interval [NTAMS, top] + // (which contains the implicitly live objects) in the + // card liveness bitmap. Also sets the bit for each region + // containing live data, in the region liveness bitmap. + class G1FinalizeCountDataClosure: public HeapRegionClosure { + private: + G1LiveDataHelper _helper; + public: + G1FinalizeCountDataClosure(G1CMBitMap* bitmap, + BitMap* region_bm, + BitMap* card_bm) : + HeapRegionClosure(), + _helper(region_bm, card_bm) { } -class FinalCountDataUpdateClosure: public G1CMCountDataClosureBase { - public: - FinalCountDataUpdateClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm) { } - - bool doHeapRegion(HeapRegion* hr) { - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* top = hr->top(); - - assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); - - // Mark the allocated-since-marking portion... - if (ntams < top) { - // This definitely means the region has live objects. - set_bit_for_region(hr); - - // Now set the bits in the card bitmap for [ntams, top) - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; + bool doHeapRegion(HeapRegion* hr) { + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || hr->next_marked_bytes() > 0) { + _helper.set_bit_for_region(hr); } - - assert(end_idx <= _card_bm->size(), - "oob: end_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - end_idx, _card_bm->size()); - assert(start_idx < _card_bm->size(), - "oob: start_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - start_idx, _card_bm->size()); - - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); + return false; } + }; - // Set the bit for the region if it contains live data - if (hr->next_marked_bytes() > 0) { - set_bit_for_region(hr); - } + G1CMBitMap* _bitmap; - return false; - } -}; - -class G1ParFinalCountTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; BitMap* _actual_region_bm; BitMap* _actual_card_bm; - uint _n_workers; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) - : AbstractGangTask("G1 final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { + G1FinalizeLiveDataTask(G1CMBitMap* bitmap, BitMap* region_bm, BitMap* card_bm, uint n_workers) : + AbstractGangTask("G1 final counting"), + _bitmap(bitmap), + _actual_region_bm(region_bm), + _actual_card_bm(card_bm), + _hr_claimer(n_workers) { } void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); + G1FinalizeCountDataClosure cl(_bitmap, + _actual_region_bm, + _actual_card_bm); - FinalCountDataUpdateClosure final_update_cl(_g1h, - _actual_region_bm, - _actual_card_bm); - - _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); + G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); } }; @@ -1637,31 +1612,29 @@ void G1ConcurrentMark::cleanup() { HeapRegionRemSet::reset_for_cleanup_tasks(); - // Do counting once more with the world stopped for good measure. - G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); - - g1h->workers()->run_task(&g1_par_count_task); - - if (VerifyDuringGC) { - // Verify that the counting data accumulated during marking matches - // that calculated by walking the marking bitmap. - - // Bitmaps to hold expected values - BitMap expected_region_bm(_region_bm.size(), true); - BitMap expected_card_bm(_card_bm.size(), true); - - G1ParVerifyFinalCountTask g1_par_verify_task(g1h, - &_region_bm, - &_card_bm, - &expected_region_bm, - &expected_card_bm); - - g1h->workers()->run_task(&g1_par_verify_task); - - guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); + { + // Finalize the live data. + G1FinalizeLiveDataTask cl(_nextMarkBitMap, + &_region_live_bm, + &_card_live_bm, + g1h->workers()->active_workers()); + g1h->workers()->run_task(&cl); + } + + if (VerifyDuringGC) { + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + ResourceMark rm; + G1VerifyLiveDataTask cl(G1CollectedHeap::heap(), + _nextMarkBitMap, + &_region_live_bm, + &_card_live_bm, + g1h->workers()->active_workers()); + g1h->workers()->run_task(&cl); + + guarantee(cl.failures() == 0, "Unexpected accounting failures"); } - size_t start_used_bytes = g1h->used(); g1h->collector_state()->set_mark_in_progress(false); double count_end = os::elapsedTime(); @@ -1696,7 +1669,7 @@ void G1ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - g1h->scrub_rem_set(&_region_bm, &_card_bm); + g1h->scrub_rem_set(&_region_live_bm, &_card_live_bm); _total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start); } @@ -2142,6 +2115,35 @@ void G1ConcurrentMark::swapMarkBitMaps() { _nextMarkBitMap = (G1CMBitMap*) temp; } +BitMap G1ConcurrentMark::allocate_large_bitmap(BitMap::idx_t size_in_bits) { + size_t size_in_words = BitMap::size_in_words(size_in_bits); + + BitMap::bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); + + return BitMap(map, size_in_bits); +} + +void G1ConcurrentMark::allocate_internal_bitmaps() { + double start_time = os::elapsedTime(); + + _region_live_bm = allocate_large_bitmap(_g1h->max_regions()); + + guarantee(_g1h->max_capacity() % CardTableModRefBS::card_size == 0, + "Heap capacity must be aligned to card size."); + _card_live_bm = allocate_large_bitmap(_g1h->max_capacity() / CardTableModRefBS::card_size); + + log_debug(gc, marking)("Allocating internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); +} + +void G1ConcurrentMark::pretouch_internal_bitmaps() { + double start_time = os::elapsedTime(); + + _region_live_bm.pretouch(); + _card_live_bm.pretouch(); + + log_debug(gc, marking)("Pre-touching internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); +} + // Closure for marking entries in SATB buffers. class G1CMSATBBufferClosure : public SATBBufferClosure { private: @@ -2160,7 +2162,7 @@ private: oop obj = static_cast(entry); assert(obj->is_oop(true /* ignore mark word */), "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)); - _task->make_reference_grey(obj, hr); + _task->make_reference_grey(obj); } } @@ -2402,165 +2404,117 @@ void G1ConcurrentMark::verify_no_cset_oops() { } #endif // PRODUCT -// Aggregate the counting data that was constructed concurrently -// with marking. -class AggregateCountDataHRClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - BitMap* _cm_card_bm; - uint _max_worker_id; +class G1CreateLiveDataTask: public AbstractGangTask { + // Aggregate the counting data that was constructed concurrently + // with marking. + class G1CreateLiveDataHRClosure: public HeapRegionClosure { + G1LiveDataHelper _helper; - public: - AggregateCountDataHRClosure(G1CollectedHeap* g1h, - BitMap* cm_card_bm, - uint max_worker_id) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { } + G1CMBitMap* _mark_bitmap; - bool doHeapRegion(HeapRegion* hr) { - HeapWord* start = hr->bottom(); - HeapWord* limit = hr->next_top_at_mark_start(); - HeapWord* end = hr->end(); + G1ConcurrentMark* _cm; + public: + G1CreateLiveDataHRClosure(G1ConcurrentMark* cm, + G1CMBitMap* mark_bitmap, + BitMap* cm_card_bm) : + HeapRegionClosure(), + _helper(NULL, cm_card_bm), + _mark_bitmap(mark_bitmap), + _cm(cm) { } - assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", " - "top: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end())); + bool doHeapRegion(HeapRegion* hr) { + size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); + if (marked_bytes > 0) { + hr->add_to_marked_bytes(marked_bytes); + } - assert(hr->next_marked_bytes() == 0, "Precondition"); - - if (start == limit) { - // NTAMS of this region has not been set so nothing to do. + if (_cm->do_yield_check() && _cm->has_aborted()) { + return true; + } return false; } + }; - // 'start' should be in the heap. - assert(_g1h->is_in_g1_reserved(start) && _ct_bs->is_card_aligned(start), "sanity"); - // 'end' *may* be just beyond the end of the heap (if hr is the last region) - assert(!_g1h->is_in_g1_reserved(end) || _ct_bs->is_card_aligned(end), "sanity"); - - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t limit_idx = _cm->card_bitmap_index_for(limit); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(end); - - // If ntams is not card aligned then we bump card bitmap index - // for limit so that we get the all the cards spanned by - // the object ending at ntams. - // Note: if this is the last region in the heap then ntams - // could be actually just beyond the end of the the heap; - // limit_idx will then correspond to a (non-existent) card - // that is also outside the heap. - if (_g1h->is_in_g1_reserved(limit) && !_ct_bs->is_card_aligned(limit)) { - limit_idx += 1; - } - - assert(limit_idx <= end_idx, "or else use atomics"); - - // Aggregate the "stripe" in the count data associated with hr. - uint hrm_index = hr->hrm_index(); - size_t marked_bytes = 0; - - for (uint i = 0; i < _max_worker_id; i += 1) { - size_t* marked_bytes_array = _cm->count_marked_bytes_array_for(i); - BitMap* task_card_bm = _cm->count_card_bitmap_for(i); - - // Fetch the marked_bytes in this region for task i and - // add it to the running total for this region. - marked_bytes += marked_bytes_array[hrm_index]; - - // Now union the bitmaps[0,max_worker_id)[start_idx..limit_idx) - // into the global card bitmap. - BitMap::idx_t scan_idx = task_card_bm->get_next_one_offset(start_idx, limit_idx); - - while (scan_idx < limit_idx) { - assert(task_card_bm->at(scan_idx) == true, "should be"); - _cm_card_bm->set_bit(scan_idx); - assert(_cm_card_bm->at(scan_idx) == true, "should be"); - - // BitMap::get_next_one_offset() can handle the case when - // its left_offset parameter is greater than its right_offset - // parameter. It does, however, have an early exit if - // left_offset == right_offset. So let's limit the value - // passed in for left offset here. - BitMap::idx_t next_idx = MIN2(scan_idx + 1, limit_idx); - scan_idx = task_card_bm->get_next_one_offset(next_idx, limit_idx); - } - } - - // Update the marked bytes for this region. - hr->add_to_marked_bytes(marked_bytes); - - // Next heap region - return false; - } -}; - -class G1AggregateCountDataTask: public AbstractGangTask { -protected: G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; BitMap* _cm_card_bm; - uint _max_worker_id; - uint _active_workers; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1AggregateCountDataTask(G1CollectedHeap* g1h, - G1ConcurrentMark* cm, - BitMap* cm_card_bm, - uint max_worker_id, - uint n_workers) : - AbstractGangTask("Count Aggregation"), - _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), - _max_worker_id(max_worker_id), - _active_workers(n_workers), - _hrclaimer(_active_workers) { + G1CreateLiveDataTask(G1CollectedHeap* g1h, + BitMap* cm_card_bm, + uint n_workers) : + AbstractGangTask("Create Live Data"), + _g1h(g1h), + _cm_card_bm(cm_card_bm), + _hr_claimer(n_workers) { } void work(uint worker_id) { - AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); + SuspendibleThreadSetJoiner sts_join; - _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); + G1CreateLiveDataHRClosure cl(_g1h->concurrent_mark(), _g1h->concurrent_mark()->nextMarkBitMap(), _cm_card_bm); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); } }; -void G1ConcurrentMark::aggregate_count_data() { - uint n_workers = _g1h->workers()->active_workers(); +void G1ConcurrentMark::create_live_data() { + uint n_workers = _parallel_workers->active_workers(); - G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, - _max_worker_id, n_workers); - - _g1h->workers()->run_task(&g1_par_agg_task); + G1CreateLiveDataTask cl(_g1h, + &_card_live_bm, + n_workers); + _parallel_workers->run_task(&cl); } -// Clear the per-worker arrays used to store the per-region counting data -void G1ConcurrentMark::clear_all_count_data() { - // Clear the global card bitmap - it will be filled during - // liveness count aggregation (during remark) and the - // final counting task. - _card_bm.clear(); - - // Clear the global region bitmap - it will be filled as part - // of the final counting task. - _region_bm.clear(); - - uint max_regions = _g1h->max_regions(); - assert(_max_worker_id > 0, "uninitialized"); - - for (uint i = 0; i < _max_worker_id; i += 1) { - BitMap* task_card_bm = count_card_bitmap_for(i); - size_t* marked_bytes_array = count_marked_bytes_array_for(i); - - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - assert(marked_bytes_array != NULL, "uninitialized"); - - memset(marked_bytes_array, 0, (size_t) max_regions * sizeof(size_t)); - task_card_bm->clear(); +class G1ClearAllLiveDataTask : public AbstractGangTask { + BitMap* _bitmap; + size_t _num_tasks; + size_t _cur_task; +public: + G1ClearAllLiveDataTask(BitMap* bitmap, size_t num_tasks) : + AbstractGangTask("Clear All Live Data"), + _bitmap(bitmap), + _num_tasks(num_tasks), + _cur_task(0) { } + + virtual void work(uint worker_id) { + while (true) { + size_t to_process = Atomic::add(1, &_cur_task) - 1; + if (to_process >= _num_tasks) { + break; + } + + BitMap::idx_t start = M * BitsPerByte * to_process; + BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap->size()); + _bitmap->clear_range(start, end); + } + } +}; + +void G1ConcurrentMark::clear_all_live_data(WorkGang* workers) { + double start_time = os::elapsedTime(); + + guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); + + size_t const num_chunks = align_size_up(_card_live_bm.size_in_words() * HeapWordSize, M) / M; + + G1ClearAllLiveDataTask cl(&_card_live_bm, num_chunks); + workers->run_task(&cl); + + // The region live bitmap is always very small, even for huge heaps. Clear + // directly. + _region_live_bm.clear(); + + + log_debug(gc, marking)("Clear Live Data took %.3fms", (os::elapsedTime() - start_time) * 1000.0); +} + +void G1ConcurrentMark::verify_all_live_data() { + assert(_card_live_bm.count_one_bits() == 0, "Master card bitmap not clear"); + assert(_region_live_bm.count_one_bits() == 0, "Master region bitmap not clear"); } void G1ConcurrentMark::print_stats() { @@ -2574,7 +2528,6 @@ void G1ConcurrentMark::print_stats() { } } -// abandon current marking iteration due to a Full GC void G1ConcurrentMark::abort() { if (!cmThread()->during_cycle() || _has_aborted) { // We haven't started a concurrent cycle or we have already aborted it. No need to do anything. @@ -2589,8 +2542,8 @@ void G1ConcurrentMark::abort() { // since VerifyDuringGC verifies the objects marked during // a full GC against the previous bitmap. - // Clear the liveness counting data - clear_all_count_data(); + clear_all_live_data(_g1h->workers()); + DEBUG_ONLY(verify_all_live_data()); // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { @@ -2634,7 +2587,7 @@ void G1ConcurrentMark::print_summary_info() { } print_ms_time_info(" ", "cleanups", _cleanup_times); - log.trace(" Final counting total time = %8.2f s (avg = %8.2f ms).", + log.trace(" Finalize live data total time = %8.2f s (avg = %8.2f ms).", _total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0)); if (G1ScrubRemSets) { log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).", @@ -3473,8 +3426,6 @@ void G1CMTask::do_marking_step(double time_target_ms, G1CMTask::G1CMTask(uint worker_id, G1ConcurrentMark* cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues) : _g1h(G1CollectedHeap::heap()), @@ -3483,9 +3434,7 @@ G1CMTask::G1CMTask(uint worker_id, _nextMarkBitMap(NULL), _hash_seed(17), _task_queue(task_queue), _task_queues(task_queues), - _cm_oop_closure(NULL), - _marked_bytes_array(marked_bytes), - _card_bm(card_bm) { + _cm_oop_closure(NULL) { guarantee(task_queue != NULL, "invariant"); guarantee(task_queues != NULL, "invariant"); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 1608c81f96f..fb621e34980 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -266,7 +266,7 @@ class ConcurrentMarkThread; class G1ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; friend class G1ParNoteEndTask; - friend class CalcLiveObjectsClosure; + friend class G1VerifyLiveDataClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; friend class G1CMKeepAliveAndDrainClosure; @@ -298,8 +298,14 @@ protected: G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap - BitMap _region_bm; - BitMap _card_bm; + // Liveness count data. After marking G1 iterates over the recently gathered mark + // bitmap and records rough information about liveness on card and region basis. + // This information can be used for e.g. remembered set scrubbing. + + // A set bit indicates whether the given region contains any live object. + BitMap _region_live_bm; + // A set bit indicates that the given card contains a live object. + BitMap _card_live_bm; // Heap bounds HeapWord* _heap_start; @@ -373,6 +379,14 @@ protected: void swapMarkBitMaps(); + // Allocates and returns a zero-ed out "large" bitmap of the given size in bits. + // It is always allocated using virtual memory. + BitMap allocate_large_bitmap(BitMap::idx_t size_in_bits); + // Allocates the memory for all bitmaps used by the concurrent marking. + void allocate_internal_bitmaps(); + // Pre-touches the internal bitmaps. + void pretouch_internal_bitmaps(); + // It resets the global marking data structures, as well as the // task local ones; should be called during initial mark. void reset(); @@ -461,23 +475,6 @@ protected: void enter_first_sync_barrier(uint worker_id); void enter_second_sync_barrier(uint worker_id); - // Live Data Counting data structures... - // These data structures are initialized at the start of - // marking. They are written to while marking is active. - // They are aggregated during remark; the aggregated values - // are then used to populate the _region_bm, _card_bm, and - // the total live bytes, which are then subsequently updated - // during cleanup. - - // An array of bitmaps (one bit map per task). Each bitmap - // is used to record the cards spanned by the live objects - // marked by that task/worker. - BitMap* _count_card_bitmaps; - - // Used to record the number of marked live bytes - // (for each region, by worker thread). - size_t** _count_marked_bytes; - // Card index of the bottom of the G1 heap. Used for biasing indices into // the card bitmaps. intptr_t _heap_bottom_card_num; @@ -563,18 +560,10 @@ public: // G1CollectedHeap // This notifies CM that a root during initial-mark needs to be - // grayed. It is MT-safe. word_size is the size of the object in - // words. It is passed explicitly as sometimes we cannot calculate - // it from the given object because it might be in an inconsistent - // state (e.g., in to-space and being copied). So the caller is - // responsible for dealing with this issue (e.g., get the size from - // the from-space image when the to-space image might be - // inconsistent) and always passing the size. hr is the region that + // grayed. It is MT-safe. hr is the region that // contains the object and it's passed optionally from callers who // might already have it (no point in recalculating it). inline void grayRoot(oop obj, - size_t word_size, - uint worker_id, HeapRegion* hr = NULL); // Prepare internal data structures for the next mark cycle. This includes clearing @@ -641,7 +630,7 @@ public: inline bool do_yield_check(uint worker_i = 0); - // Called to abort the marking cycle after a Full GC takes place. + // Abandon current marking iteration due to a Full GC. void abort(); bool has_aborted() { return _has_aborted; } @@ -652,75 +641,8 @@ public: void print_on_error(outputStream* st) const; - // Liveness counting - - // Utility routine to set an exclusive range of cards on the given - // card liveness bitmap - inline void set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par); - - // Returns the card number of the bottom of the G1 heap. - // Used in biasing indices into accounting card bitmaps. - intptr_t heap_bottom_card_num() const { - return _heap_bottom_card_num; - } - - // Returns the card bitmap for a given task or worker id. - BitMap* count_card_bitmap_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_card_bitmaps != NULL, "uninitialized"); - BitMap* task_card_bm = &_count_card_bitmaps[worker_id]; - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - return task_card_bm; - } - - // Returns the array containing the marked bytes for each region, - // for the given worker or task id. - size_t* count_marked_bytes_array_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_marked_bytes != NULL, "uninitialized"); - size_t* marked_bytes_array = _count_marked_bytes[worker_id]; - assert(marked_bytes_array != NULL, "uninitialized"); - return marked_bytes_array; - } - - // Returns the index in the liveness accounting card table bitmap - // for the given address - inline BitMap::idx_t card_bitmap_index_for(HeapWord* addr); - - // Counts the size of the given memory region in the the given - // marked_bytes array slot for the given HeapRegion. - // Sets the bits in the given card bitmap that are associated with the - // cards that are spanned by the memory region. - inline void count_region(MemRegion mr, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Counts the given object in the given task/worker counting - // data structures. - inline void count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size); - - // Attempts to mark the given object and, if successful, counts - // the object in the given task/worker counting structures. - inline bool par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Attempts to mark the given object and, if successful, counts - // the object in the task/worker counting structures for the - // given worker id. - inline bool par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id); + // Attempts to mark the given object on the next mark bitmap. + inline bool par_mark(oop obj); // Returns true if initialization was successfully completed. bool completed_initialization() const { @@ -730,19 +652,19 @@ public: ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } -protected: - // Clear all the per-task bitmaps and arrays used to store the - // counting data. - void clear_all_count_data(); +private: + // Clear (Reset) all liveness count data. + void clear_all_live_data(WorkGang* workers); - // Aggregates the counting data for each worker/task - // that was constructed while marking. Also sets - // the amount of marked bytes for each region and - // the top at concurrent mark count. - void aggregate_count_data(); + // Verify all of the above data structures that they are in initial state. + void verify_all_live_data(); + + // Aggregates the per-card liveness data based on the current marking. Also sets + // the amount of marked bytes for each region. + void create_live_data(); // Verification routine - void verify_count_data(); + void verify_live_data(); }; // A class representing a marking task. @@ -844,12 +766,6 @@ private: TruncatedSeq _marking_step_diffs_ms; - // Counting data structures. Embedding the task's marked_bytes_array - // and card bitmap into the actual task saves having to go through - // the ConcurrentMark object. - size_t* _marked_bytes_array; - BitMap* _card_bm; - // it updates the local fields after this task has claimed // a new region to scan void setup_for_region(HeapRegion* hr); @@ -936,9 +852,8 @@ public: // Grey the object by marking it. If not already marked, push it on // the local queue if below the finger. - // Precondition: obj is in region. // Precondition: obj is below region's NTAMS. - inline void make_reference_grey(oop obj, HeapRegion* region); + inline void make_reference_grey(oop obj); // Grey the object (by calling make_grey_reference) if required, // e.g. obj is below its containing region's NTAMS. @@ -976,8 +891,6 @@ public: G1CMTask(uint worker_id, G1ConcurrentMark *cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 4a934e0b15e..053de4b9673 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -29,138 +29,8 @@ #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/shared/taskqueue.inline.hpp" -// Utility routine to set an exclusive range of cards on the given -// card liveness bitmap -inline void G1ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par) { - - // Set the exclusive bit range [start_idx, end_idx). - assert((end_idx - start_idx) > 0, "at least one card"); - assert(end_idx <= card_bm->size(), "sanity"); - - // Silently clip the end index - end_idx = MIN2(end_idx, card_bm->size()); - - // For small ranges use a simple loop; otherwise use set_range or - // use par_at_put_range (if parallel). The range is made up of the - // cards that are spanned by an object/mem region so 8 cards will - // allow up to object sizes up to 4K to be handled using the loop. - if ((end_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { - if (is_par) { - card_bm->par_set_bit(i); - } else { - card_bm->set_bit(i); - } - } - } else { - // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive. - if (is_par) { - card_bm->par_at_put_range(start_idx, end_idx, true); - } else { - card_bm->set_range(start_idx, end_idx); - } - } -} - -// Returns the index in the liveness accounting card bitmap -// for the given address -inline BitMap::idx_t G1ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { - // Below, the term "card num" means the result of shifting an address - // by the card shift -- address 0 corresponds to card number 0. One - // must subtract the card num of the bottom of the heap to obtain a - // card table index. - intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift); - return card_num - heap_bottom_card_num(); -} - -// Counts the given memory region in the given task/worker -// counting data structures. -inline void G1ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - G1CollectedHeap* g1h = _g1h; - CardTableModRefBS* ct_bs = g1h->g1_barrier_set(); - - HeapWord* start = mr.start(); - HeapWord* end = mr.end(); - size_t region_size_bytes = mr.byte_size(); - uint index = hr->hrm_index(); - - assert(hr == g1h->heap_region_containing(start), "sanity"); - assert(marked_bytes_array != NULL, "pre-condition"); - assert(task_card_bm != NULL, "pre-condition"); - - // Add to the task local marked bytes for this region. - marked_bytes_array[index] += region_size_bytes; - - BitMap::idx_t start_idx = card_bitmap_index_for(start); - BitMap::idx_t end_idx = card_bitmap_index_for(end); - - // Note: if we're looking at the last region in heap - end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) { - // end of region is not card aligned - increment to cover - // all the cards spanned by the region. - end_idx += 1; - } - // The card bitmap is task/worker specific => no need to use - // the 'par' BitMap routines. - // Set bits in the exclusive bit range [start_idx, end_idx). - set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */); -} - -// Counts the given object in the given task/worker counting data structures. -inline void G1ConcurrentMark::count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size) { - assert(!hr->is_continues_humongous(), "Cannot enter count_object with continues humongous"); - if (!hr->is_starts_humongous()) { - MemRegion mr((HeapWord*)obj, word_size); - count_region(mr, hr, marked_bytes_array, task_card_bm); - } else { - do { - MemRegion mr(hr->bottom(), hr->top()); - count_region(mr, hr, marked_bytes_array, task_card_bm); - hr = _g1h->next_region_in_humongous(hr); - } while (hr != NULL); - } -} - -// Attempts to mark the given object and, if successful, counts -// the object in the given task/worker counting structures. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - // Update the task specific count data for the object. - count_object(obj, hr, marked_bytes_array, task_card_bm, obj->size()); - return true; - } - return false; -} - -// Attempts to mark the given object and, if successful, counts -// the object in the task/worker counting structures for the -// given worker id. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); - BitMap* task_card_bm = count_card_bitmap_for(worker_id); - count_object(obj, hr, marked_bytes_array, task_card_bm, word_size); - return true; - } - return false; +inline bool G1ConcurrentMark::par_mark(oop obj) { + return _nextMarkBitMap->parMark((HeapWord*)obj); } inline bool G1CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { @@ -294,10 +164,8 @@ inline void G1CMTask::process_grey_object(oop obj) { check_limits(); } - - -inline void G1CMTask::make_reference_grey(oop obj, HeapRegion* hr) { - if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { +inline void G1CMTask::make_reference_grey(oop obj) { + if (_cm->par_mark(obj)) { // No OrderAccess:store_load() is needed. It is implicit in the // CAS done in G1CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); @@ -348,7 +216,7 @@ inline void G1CMTask::deal_with_reference(oop obj) { // anything with it). HeapRegion* hr = _g1h->heap_region_containing(obj); if (!hr->obj_allocated_since_next_marking(obj)) { - make_reference_grey(obj, hr); + make_reference_grey(obj); } } } @@ -370,8 +238,7 @@ bool G1ConcurrentMark::isPrevMarked(oop p) const { return _prevMarkBitMap->isMarked(addr); } -inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, - uint worker_id, HeapRegion* hr) { +inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; if (hr == NULL) { @@ -386,7 +253,7 @@ inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, if (addr < hr->next_top_at_mark_start()) { if (!_nextMarkBitMap->isMarked(addr)) { - par_mark_and_count(obj, word_size, hr, worker_id); + par_mark(obj); } } } diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index 06721ee9295..82d655ed232 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -95,8 +95,6 @@ public: void do_object(oop obj) { HeapWord* obj_addr = (HeapWord*) obj; assert(_hr->is_in(obj_addr), "sanity"); - size_t obj_size = obj->size(); - HeapWord* obj_end = obj_addr + obj_size; if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. @@ -119,8 +117,10 @@ public: // explicitly and all objects in the CSet are considered // (implicitly) live. So, we won't mark them explicitly and // we'll leave them over NTAMS. - _cm->grayRoot(obj, obj_size, _worker_id, _hr); + _cm->grayRoot(obj, _hr); } + size_t obj_size = obj->size(); + _marked_bytes += (obj_size * HeapWordSize); obj->set_mark(markOopDesc::prototype()); @@ -138,6 +138,7 @@ public: // the collection set. So, we'll recreate such entries now. obj->oop_iterate(_update_rset_cl); + HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; _hr->cross_threshold(obj_addr, obj_end); } diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index 932bcbbfc4c..34db8d6c207 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -131,7 +131,7 @@ inline void G1RootRegionScanClosure::do_oop_nv(T* p) { if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj); - _cm->grayRoot(obj, obj->size(), _worker_id, hr); + _cm->grayRoot(obj, hr); } } @@ -246,7 +246,7 @@ void G1ParCopyHelper::mark_object(oop obj) { assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet"); // We know that the object is not moving so it's safe to read its size. - _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); + _cm->grayRoot(obj); } void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { @@ -261,7 +261,7 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { // worker so we cannot trust that its to-space image is // well-formed. So we have to read its size from its from-space // image which we know should not be changing. - _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); + _cm->grayRoot(to_obj); } template diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index ac78d2b0e8a..f015e4e9ee1 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -260,6 +260,9 @@ "The target number of mixed GCs after a marking cycle.") \ range(0, max_uintx) \ \ + experimental(bool, G1PretouchAuxiliaryMemory, false, \ + "Pre-touch large auxiliary data structures used by the GC.") \ + \ experimental(bool, G1EagerReclaimHumongousObjects, true, \ "Try to reclaim dead large objects at every young GC.") \ \ diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index fced8fbb522..7804c988487 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -68,6 +68,10 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { } } +void BitMap::pretouch() { + os::pretouch_memory((char*)word_addr(0), (char*)word_addr(size())); +} + void BitMap::set_range_within_word(idx_t beg, idx_t end) { // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index e57264b2e9a..0e46cea9917 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -135,12 +135,19 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // use the same value for "in_resource_area".) void resize(idx_t size_in_bits, bool in_resource_area = true); + // Pretouch the entire range of memory this BitMap covers. + void pretouch(); + // Accessing idx_t size() const { return _size; } idx_t size_in_words() const { return word_index(size() + BitsPerWord - 1); } + static idx_t size_in_words(size_t size_in_bits) { + return word_index(size_in_bits + BitsPerWord - 1); + } + bool at(idx_t index) const { verify_index(index); return (*word_addr(index) & bit_mask(index)) != 0; diff --git a/hotspot/test/gc/g1/Test2GbHeap.java b/hotspot/test/gc/g1/Test2GbHeap.java index 8aa2c4828ce..c0c6afa5f89 100644 --- a/hotspot/test/gc/g1/Test2GbHeap.java +++ b/hotspot/test/gc/g1/Test2GbHeap.java @@ -25,6 +25,9 @@ * @test Test2GbHeap * @bug 8031686 * @summary Regression test to ensure we can start G1 with 2gb heap. + * Skip test on 32 bit Windows: it typically does not support the many and large virtual memory reservations needed. + * @requires (vm.gc == "G1" | vm.gc == "null") + * @requires !((sun.arch.data.model == "32") & (os.family == "windows")) * @key gc * @key regression * @library /testlibrary @@ -48,17 +51,6 @@ public class Test2GbHeap { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testArguments.toArray(new String[0])); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // Avoid failing test for setups not supported. - if (output.getOutput().contains("Could not reserve enough space for 2097152KB object heap")) { - // Will fail on machines with too little memory (and Windows 32-bit VM), ignore such failures. - output.shouldHaveExitValue(1); - } else if (output.getOutput().contains("-XX:+UseG1GC not supported in this VM")) { - // G1 is not supported on embedded, ignore such failures. - output.shouldHaveExitValue(1); - } else { - // Normally everything should be fine. - output.shouldHaveExitValue(0); - } + output.shouldHaveExitValue(0); } } From 2904ea7d45992a6973374e4852e308bf5b38212b Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 6 Apr 2016 07:37:15 -0400 Subject: [PATCH 036/113] 8152846: Creation of ModuleEntryTable Investigate Need For OrderAccess::storestore() Remove the unneeded OrderAccess::storestore() call Reviewed-by: acorn, coleenp --- hotspot/src/share/vm/classfile/classLoaderData.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 0fb7a86af4f..0c0eb37196f 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -373,13 +373,10 @@ PackageEntryTable* ClassLoaderData::packages() { // Lazily create the package entry table at first request. if (_packages == NULL) { MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Check again if _packages has been allocated while we were getting this lock. - if (_packages != NULL) { - return _packages; + // Check if _packages got allocated while we were waiting for this lock. + if (_packages == NULL) { + _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } - // Ensure _packages is stable, since it is examined without a lock - OrderAccess::storestore(); - _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } return _packages; } From a009aa9ca73241bc8740e3056bce2918f17f12b3 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 6 Apr 2016 13:41:59 +0200 Subject: [PATCH 037/113] 8151386: Extract card live data out of G1ConcurrentMark Move card live data management out of G1ConcurrentMark into extra class G1CardLiveData managed by G1RemSet Reviewed-by: mgerdin, kbarrett --- .../share/vm/gc/g1/concurrentMarkThread.cpp | 1 + hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp | 552 +++++++++++++++++ hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp | 99 +++ .../share/vm/gc/g1/g1CardLiveData.inline.hpp | 52 ++ .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 15 +- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 3 +- .../share/vm/gc/g1/g1CollectedHeap.inline.hpp | 2 +- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 579 ++---------------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 32 +- .../vm/gc/g1/g1ConcurrentMark.inline.hpp | 10 + hotspot/src/share/vm/gc/g1/g1OopClosures.hpp | 6 +- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 50 +- hotspot/src/share/vm/gc/g1/g1RemSet.hpp | 21 +- .../src/share/vm/gc/g1/heapRegionRemSet.cpp | 22 +- .../src/share/vm/gc/g1/heapRegionRemSet.hpp | 8 +- hotspot/src/share/vm/utilities/bitMap.cpp | 2 +- hotspot/src/share/vm/utilities/bitMap.hpp | 7 +- 17 files changed, 848 insertions(+), 613 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 7eef582e3db..9727b023268 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1MMUTracker.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "gc/g1/vm_operations_g1.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp new file mode 100644 index 00000000000..009179150a9 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" +#include "gc/shared/workgroup.hpp" +#include "memory/universe.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/debug.hpp" + +G1CardLiveData::G1CardLiveData() : + _max_capacity(0), + _cards_per_region(0), + _live_regions(NULL), + _live_regions_size_in_bits(0), + _live_cards(NULL), + _live_cards_size_in_bits(0) { +} + +G1CardLiveData::~G1CardLiveData() { + free_large_bitmap(_live_cards, _live_cards_size_in_bits); + free_large_bitmap(_live_regions, _live_regions_size_in_bits); +} + +G1CardLiveData::bm_word_t* G1CardLiveData::allocate_large_bitmap(size_t size_in_bits) { + size_t size_in_words = BitMap::calc_size_in_words(size_in_bits); + + bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); + + return map; +} + +void G1CardLiveData::free_large_bitmap(bm_word_t* bitmap, size_t size_in_bits) { + MmapArrayAllocator::free(bitmap, size_in_bits / BitsPerWord); +} + +void G1CardLiveData::initialize(size_t max_capacity, uint num_max_regions) { + assert(max_capacity % num_max_regions == 0, + "Given capacity must be evenly divisible by region size."); + size_t region_size = max_capacity / num_max_regions; + assert(region_size % (G1SATBCardTableModRefBS::card_size * BitsPerWord) == 0, + "Region size must be evenly divisible by area covered by a single word."); + _max_capacity = max_capacity; + _cards_per_region = region_size / G1SATBCardTableModRefBS::card_size; + + _live_regions_size_in_bits = live_region_bitmap_size_in_bits(); + _live_regions = allocate_large_bitmap(_live_regions_size_in_bits); + _live_cards_size_in_bits = live_card_bitmap_size_in_bits(); + _live_cards = allocate_large_bitmap(_live_cards_size_in_bits); +} + +void G1CardLiveData::pretouch() { + live_cards_bm().pretouch(); + live_regions_bm().pretouch(); +} + +size_t G1CardLiveData::live_region_bitmap_size_in_bits() const { + return _max_capacity / (_cards_per_region << G1SATBCardTableModRefBS::card_shift); +} + +size_t G1CardLiveData::live_card_bitmap_size_in_bits() const { + return _max_capacity >> G1SATBCardTableModRefBS::card_shift; +} + +// Helper class that provides functionality to generate the Live Data Count +// information. +class G1CardLiveDataHelper VALUE_OBJ_CLASS_SPEC { +private: + BitMap _region_bm; + BitMap _card_bm; + + // The card number of the bottom of the G1 heap. + // Used in biasing indices into accounting card bitmaps. + BitMap::idx_t _heap_card_bias; + + // Utility routine to set an exclusive range of bits on the given + // bitmap, optimized for very small ranges. + // There must be at least one bit to set. + void set_card_bitmap_range(BitMap::idx_t start_idx, + BitMap::idx_t end_idx) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one bit"); + + // For small ranges use a simple loop; otherwise use set_range. + // The range is made up of the cards that are spanned by an object/mem + // region so 8 cards will allow up to object sizes up to 4K to be handled + // using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + _card_bm.set_bit(i); + } + } else { + _card_bm.set_range(start_idx, end_idx); + } + } + + // We cache the last mark set. This avoids setting the same bit multiple times. + // This is particularly interesting for dense bitmaps, as this avoids doing + // lots of work most of the time. + BitMap::idx_t _last_marked_bit_idx; + + // Mark the card liveness bitmap for the object spanning from start to end. + void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { + BitMap::idx_t start_idx = card_live_bitmap_index_for(start); + BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); + + assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); + + if (start_idx == _last_marked_bit_idx) { + start_idx++; + } + if (start_idx == end_idx) { + return; + } + + // Set the bits in the card bitmap for the cards spanned by this object. + set_card_bitmap_range(start_idx, end_idx); + _last_marked_bit_idx = end_idx - 1; + } + + void reset_mark_cache() { + _last_marked_bit_idx = (BitMap::idx_t)-1; + } + +public: + // Returns the index in the per-card liveness count bitmap + // for the given address + inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + BitMap::idx_t card_num = uintptr_t(addr) >> CardTableModRefBS::card_shift; + return card_num - _heap_card_bias; + } + + // Takes a region that's not empty (i.e., it has at least one + // live object in it and sets its corresponding bit on the region + // bitmap to 1. + void set_bit_for_region(HeapRegion* hr) { + _region_bm.par_set_bit(hr->hrm_index()); + } + + // Mark the range of bits covered by allocations done since the last marking + // in the given heap region, i.e. from NTAMS to top of the given region. + // Returns if there has been some allocation in this region since the last marking. + bool mark_allocated_since_marking(HeapRegion* hr) { + reset_mark_cache(); + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); + + assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + // Mark the allocated-since-marking portion... + if (ntams < top) { + mark_card_bitmap_range(ntams, top); + return true; + } else { + return false; + } + } + + // Mark the range of bits covered by live objects on the mark bitmap between + // bottom and NTAMS of the given region. + // Returns the number of live bytes marked within that area for the given + // heap region. + size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { + reset_mark_cache(); + + size_t marked_bytes = 0; + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* start = hr->bottom(); + + if (ntams <= start) { + // Skip empty regions. + return 0; + } + if (hr->is_humongous()) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } + + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), + "Preconditions not met - " + "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, + p2i(start), p2i(ntams), p2i(hr->end())); + + // Find the first marked object at or after "start". + start = mark_bitmap->getNextMarkedWordAddress(start, ntams); + while (start < ntams) { + oop obj = oop(start); + size_t obj_size = obj->size(); + HeapWord* obj_end = start + obj_size; + + assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); + + mark_card_bitmap_range(start, obj_end); + + // Add the size of this object to the number of marked bytes. + marked_bytes += obj_size * HeapWordSize; + + // Find the next marked object after this one. + start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); + } + + return marked_bytes; + } + + G1CardLiveDataHelper(G1CardLiveData* live_data, HeapWord* base_address) : + _region_bm(live_data->live_regions_bm()), + _card_bm(live_data->live_cards_bm()) { + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_card_bias = + uintptr_t(base_address) >> CardTableModRefBS::card_shift; + } +}; + +class G1CreateCardLiveDataTask: public AbstractGangTask { + // Aggregate the counting data that was constructed concurrently + // with marking. + class G1CreateLiveDataClosure : public HeapRegionClosure { + G1CardLiveDataHelper _helper; + + G1CMBitMap* _mark_bitmap; + + G1ConcurrentMark* _cm; + public: + G1CreateLiveDataClosure(G1CollectedHeap* g1h, + G1ConcurrentMark* cm, + G1CMBitMap* mark_bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()), + _mark_bitmap(mark_bitmap), + _cm(cm) { } + + bool doHeapRegion(HeapRegion* hr) { + size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); + if (marked_bytes > 0) { + hr->add_to_marked_bytes(marked_bytes); + } + + return (_cm->do_yield_check() && _cm->has_aborted()); + } + }; + + G1ConcurrentMark* _cm; + G1CardLiveData* _live_data; + HeapRegionClaimer _hr_claimer; + +public: + G1CreateCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* live_data, + uint n_workers) : + AbstractGangTask("G1 Create Live Data"), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + SuspendibleThreadSetJoiner sts_join; + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1ConcurrentMark* cm = g1h->concurrent_mark(); + G1CreateLiveDataClosure cl(g1h, cm, cm->nextMarkBitMap(), _live_data); + g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::create(WorkGang* workers, G1CMBitMap* mark_bitmap) { + uint n_workers = workers->active_workers(); + + G1CreateCardLiveDataTask cl(mark_bitmap, + this, + n_workers); + workers->run_task(&cl); +} + +class G1FinalizeCardLiveDataTask: public AbstractGangTask { + // Finalizes the liveness counting data. + // Sets the bits corresponding to the interval [NTAMS, top] + // (which contains the implicitly live objects) in the + // card liveness bitmap. Also sets the bit for each region + // containing live data, in the region liveness bitmap. + class G1FinalizeCardLiveDataClosure: public HeapRegionClosure { + private: + G1CardLiveDataHelper _helper; + public: + G1FinalizeCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()) { } + + bool doHeapRegion(HeapRegion* hr) { + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || hr->next_marked_bytes() > 0) { + _helper.set_bit_for_region(hr); + } + return false; + } + }; + + G1CMBitMap* _bitmap; + + G1CardLiveData* _live_data; + + HeapRegionClaimer _hr_claimer; + +public: + G1FinalizeCardLiveDataTask(G1CMBitMap* bitmap, G1CardLiveData* live_data, uint n_workers) : + AbstractGangTask("G1 Finalize Card Live Data"), + _bitmap(bitmap), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + G1FinalizeCardLiveDataClosure cl(G1CollectedHeap::heap(), _bitmap, _live_data); + + G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::finalize(WorkGang* workers, G1CMBitMap* mark_bitmap) { + // Finalize the live data. + G1FinalizeCardLiveDataTask cl(mark_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); +} + +class G1ClearCardLiveDataTask : public AbstractGangTask { + BitMap _bitmap; + size_t _num_chunks; + size_t _cur_chunk; +public: + G1ClearCardLiveDataTask(BitMap bitmap, size_t num_tasks) : + AbstractGangTask("G1 Clear Card Live Data"), + _bitmap(bitmap), + _num_chunks(num_tasks), + _cur_chunk(0) { + } + + static size_t chunk_size() { return M; } + + virtual void work(uint worker_id) { + while (true) { + size_t to_process = Atomic::add(1, &_cur_chunk) - 1; + if (to_process >= _num_chunks) { + break; + } + + BitMap::idx_t start = M * BitsPerByte * to_process; + BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap.size()); + _bitmap.clear_range(start, end); + } + } +}; + +void G1CardLiveData::clear(WorkGang* workers) { + guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); + + size_t const num_chunks = align_size_up(live_cards_bm().size_in_bytes(), G1ClearCardLiveDataTask::chunk_size()) / G1ClearCardLiveDataTask::chunk_size(); + + G1ClearCardLiveDataTask cl(live_cards_bm(), num_chunks); + workers->run_task(&cl); + + // The region live bitmap is always very small, even for huge heaps. Clear + // directly. + live_regions_bm().clear(); +} + +class G1VerifyCardLiveDataTask: public AbstractGangTask { + // Heap region closure used for verifying the live count data + // that was created concurrently and finalized during + // the remark pause. This closure is applied to the heap + // regions during the STW cleanup pause. + class G1VerifyCardLiveDataClosure: public HeapRegionClosure { + private: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + G1CardLiveDataHelper _helper; + + G1CardLiveData* _act_live_data; + + G1CardLiveData* _exp_live_data; + + int _failures; + + // Completely recreates the live data count for the given heap region and + // returns the number of bytes marked. + size_t create_live_data_count(HeapRegion* hr) { + size_t bytes_marked = _helper.mark_marked_during_marking(_mark_bitmap, hr); + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || bytes_marked > 0) { + _helper.set_bit_for_region(hr); + } + return bytes_marked; + } + public: + G1VerifyCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* mark_bitmap, + G1CardLiveData* act_live_data, + G1CardLiveData* exp_live_data) : + _g1h(g1h), + _mark_bitmap(mark_bitmap), + _helper(exp_live_data, g1h->reserved_region().start()), + _act_live_data(act_live_data), + _exp_live_data(exp_live_data), + _failures(0) { } + + int failures() const { return _failures; } + + bool doHeapRegion(HeapRegion* hr) { + int failures = 0; + + // Walk the marking bitmap for this region and set the corresponding bits + // in the expected region and card bitmaps. + size_t exp_marked_bytes = create_live_data_count(hr); + size_t act_marked_bytes = hr->next_marked_bytes(); + // Verify the marked bytes for this region. + + if (exp_marked_bytes != act_marked_bytes) { + failures += 1; + } else if (exp_marked_bytes > HeapRegion::GrainBytes) { + failures += 1; + } + + // Verify the bit, for this region, in the actual and expected + // (which was just calculated) region bit maps. + // We're not OK if the bit in the calculated expected region + // bitmap is set and the bit in the actual region bitmap is not. + uint index = hr->hrm_index(); + + bool expected = _exp_live_data->is_region_live(index); + bool actual = _act_live_data->is_region_live(index); + if (expected && !actual) { + failures += 1; + } + + // Verify that the card bit maps for the cards spanned by the current + // region match. We have an error if we have a set bit in the expected + // bit map and the corresponding bit in the actual bitmap is not set. + + BitMap::idx_t start_idx = _helper.card_live_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _helper.card_live_bitmap_index_for(hr->top()); + + for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { + expected = _exp_live_data->is_card_live_at(i); + actual = _act_live_data->is_card_live_at(i); + + if (expected && !actual) { + failures += 1; + } + } + + _failures += failures; + + // We could stop iteration over the heap when we + // find the first violating region by returning true. + return false; + } + }; +protected: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + + G1CardLiveData* _act_live_data; + + G1CardLiveData _exp_live_data; + + int _failures; + + HeapRegionClaimer _hr_claimer; + +public: + G1VerifyCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* act_live_data, + uint n_workers) + : AbstractGangTask("G1 Verify Card Live Data"), + _g1h(G1CollectedHeap::heap()), + _mark_bitmap(bitmap), + _act_live_data(act_live_data), + _exp_live_data(), + _failures(0), + _hr_claimer(n_workers) { + assert(VerifyDuringGC, "don't call this otherwise"); + _exp_live_data.initialize(_g1h->max_capacity(), _g1h->max_regions()); + } + + void work(uint worker_id) { + G1VerifyCardLiveDataClosure cl(_g1h, + _mark_bitmap, + _act_live_data, + &_exp_live_data); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + + Atomic::add(cl.failures(), &_failures); + } + + int failures() const { return _failures; } +}; + +void G1CardLiveData::verify(WorkGang* workers, G1CMBitMap* actual_bitmap) { + ResourceMark rm; + + G1VerifyCardLiveDataTask cl(actual_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); + + guarantee(cl.failures() == 0, "Unexpected accounting failures"); +} + +#ifndef PRODUCT +void G1CardLiveData::verify_is_clear() { + assert(live_cards_bm().count_one_bits() == 0, "Live cards bitmap must be clear."); + assert(live_regions_bm().count_one_bits() == 0, "Live regions bitmap must be clear."); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp new file mode 100644 index 00000000000..d76fa66d3c4 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP + +#include "gc/g1/g1CollectedHeap.hpp" +#include "utilities/bitMap.hpp" +#include "utilities/globalDefinitions.hpp" + +class G1CollectedHeap; +class G1CMBitMap; +class WorkGang; + +// Information about object liveness on the Java heap on a "card" basis. +// Can be used for various purposes, like as remembered set for completely +// coarsened remembered sets, scrubbing remembered sets or estimating liveness. +// This information is created as part of the concurrent marking cycle. +class G1CardLiveData VALUE_OBJ_CLASS_SPEC { + friend class G1CardLiveDataHelper; + friend class G1VerifyCardLiveDataTask; +private: + typedef BitMap::bm_word_t bm_word_t; + // Store some additional information about the covered area to be able to test. + size_t _max_capacity; + size_t _cards_per_region; + + // The per-card liveness bitmap. + bm_word_t* _live_cards; + size_t _live_cards_size_in_bits; + // The per-region liveness bitmap. + bm_word_t* _live_regions; + size_t _live_regions_size_in_bits; + // The bits in this bitmap contain for every card whether it contains + // at least part of at least one live object. + BitMap live_cards_bm() const { return BitMap(_live_cards, _live_cards_size_in_bits); } + // The bits in this bitmap indicate that a given region contains some live objects. + BitMap live_regions_bm() const { return BitMap(_live_regions, _live_regions_size_in_bits); } + + // Allocate a "large" bitmap from virtual memory with the given size in bits. + bm_word_t* allocate_large_bitmap(size_t size_in_bits); + void free_large_bitmap(bm_word_t* map, size_t size_in_bits); + + inline BitMap live_card_bitmap(uint region); + + inline bool is_card_live_at(BitMap::idx_t idx) const; + + size_t live_region_bitmap_size_in_bits() const; + size_t live_card_bitmap_size_in_bits() const; +public: + inline bool is_region_live(uint region) const; + + inline void remove_nonlive_cards(uint region, BitMap* bm); + inline void remove_nonlive_regions(BitMap* bm); + + G1CardLiveData(); + ~G1CardLiveData(); + + void initialize(size_t max_capacity, uint num_max_regions); + void pretouch(); + + // Create the initial liveness data based on the marking result from the bottom + // to the ntams of every region in the heap and the marks in the given bitmap. + void create(WorkGang* workers, G1CMBitMap* mark_bitmap); + // Finalize the liveness data. + void finalize(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify(WorkGang* workers, G1CMBitMap* actual_bitmap); + // Clear all data structures, prepare for next processing. + void clear(WorkGang* workers); + + void verify_is_clear() PRODUCT_RETURN; +}; + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP */ + diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp new file mode 100644 index 00000000000..fc14ed8bcf3 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP + +#include "gc/g1/g1CardLiveData.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +inline BitMap G1CardLiveData::live_card_bitmap(uint region) { + return BitMap(_live_cards + ((size_t)region * _cards_per_region >> LogBitsPerWord), _cards_per_region); +} + +inline bool G1CardLiveData::is_card_live_at(BitMap::idx_t idx) const { + return live_cards_bm().at(idx); +} + +inline bool G1CardLiveData::is_region_live(uint region) const { + return live_regions_bm().at(region); +} + +inline void G1CardLiveData::remove_nonlive_cards(uint region, BitMap* bm) { + bm->set_intersection(live_card_bitmap(region)); +} + +inline void G1CardLiveData::remove_nonlive_regions(BitMap* bm) { + bm->set_intersection(live_regions_bm()); +} + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP */ diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 03d4e76f3a8..2861baf232d 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1425,6 +1425,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { + GCTraceTime(Debug, gc)("Clear Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); @@ -1944,7 +1945,7 @@ jint G1CollectedHeap::initialize() { const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); - G1RemSet::initialize(max_regions()); + g1_rem_set()->initialize(max_capacity(), max_regions()); size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); @@ -4787,27 +4788,23 @@ public: class G1ParScrubRemSetTask: public AbstractGangTask { protected: G1RemSet* _g1rs; - BitMap* _region_bm; - BitMap* _card_bm; HeapRegionClaimer _hrclaimer; public: - G1ParScrubRemSetTask(G1RemSet* g1_rs, BitMap* region_bm, BitMap* card_bm, uint num_workers) : + G1ParScrubRemSetTask(G1RemSet* g1_rs, uint num_workers) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1_rs), - _region_bm(region_bm), - _card_bm(card_bm), _hrclaimer(num_workers) { } void work(uint worker_id) { - _g1rs->scrub(_region_bm, _card_bm, worker_id, &_hrclaimer); + _g1rs->scrub(worker_id, &_hrclaimer); } }; -void G1CollectedHeap::scrub_rem_set(BitMap* region_bm, BitMap* card_bm) { +void G1CollectedHeap::scrub_rem_set() { uint num_workers = workers()->active_workers(); - G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), region_bm, card_bm, num_workers); + G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), num_workers); workers()->run_task(&g1_par_scrub_rs_task); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 4bde7c70d04..e98d57af7fb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -992,7 +992,8 @@ public: // The rem set and barrier set. G1RemSet* g1_rem_set() const { return _g1_rem_set; } - void scrub_rem_set(BitMap* region_bm, BitMap* card_bm); + // Try to minimize the remembered set. + void scrub_rem_set(); unsigned get_gc_time_stamp() { return _gc_time_stamp; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index eaf329b3acd..040367b5be1 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -28,7 +28,7 @@ #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" -#include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index a181b467c7d..526387c018e 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -33,6 +33,7 @@ #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" @@ -48,7 +49,6 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/vmGCOperations.hpp" #include "logging/log.hpp" -#include "logging/logTag.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -356,8 +356,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _sleep_factor(0.0), _marking_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_live_bm(), - _card_live_bm(), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -499,12 +497,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* return; } - allocate_internal_bitmaps(); - - if (G1PretouchAuxiliaryMemory) { - pretouch_internal_bitmaps(); - } - _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); @@ -701,8 +693,8 @@ void G1ConcurrentMark::cleanup_for_next_mark() { // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_all_live_data(_parallel_workers); - DEBUG_ONLY(verify_all_live_data()); + clear_live_data(_parallel_workers); + DEBUG_ONLY(verify_live_data_clear()); } // Repeat the asserts from above. @@ -884,7 +876,7 @@ public: double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; _cm->clear_has_overflown(); - _cm->do_yield_check(worker_id); + _cm->do_yield_check(); jlong sleep_time_ms; if (!_cm->has_aborted() && the_task->has_aborted()) { @@ -934,10 +926,10 @@ uint G1ConcurrentMark::calc_parallel_marking_threads() { return n_conc_workers; } -void G1ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { +void G1ConcurrentMark::scanRootRegion(HeapRegion* hr) { // Currently, only survivors can be root regions. assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); - G1RootRegionScanClosure cl(_g1h, this, worker_id); + G1RootRegionScanClosure cl(_g1h, this); const uintx interval = PrefetchScanIntervalInBytes; HeapWord* curr = hr->bottom(); @@ -966,7 +958,7 @@ public: G1CMRootRegions* root_regions = _cm->root_regions(); HeapRegion* hr = root_regions->claim_next(); while (hr != NULL) { - _cm->scanRootRegion(hr, worker_id); + _cm->scanRootRegion(hr); hr = root_regions->claim_next(); } } @@ -1125,363 +1117,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { _gc_tracer_cm->report_object_count_after_gc(&is_alive); } -// Helper class that provides functionality to generate the Live Data Count -// information. -class G1LiveDataHelper VALUE_OBJ_CLASS_SPEC { -private: - BitMap* _region_bm; - BitMap* _card_bm; - - // The card number of the bottom of the G1 heap. Used for converting addresses - // to bitmap indices quickly. - BitMap::idx_t _heap_card_bias; - - // Utility routine to set an exclusive range of bits on the given - // bitmap, optimized for very small ranges. - // There must be at least one bit to set. - inline void set_card_bitmap_range(BitMap* bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx) { - - // Set the exclusive bit range [start_idx, end_idx). - assert((end_idx - start_idx) > 0, "at least one bit"); - assert(end_idx <= bm->size(), "sanity"); - - // For small ranges use a simple loop; otherwise use set_range or - // use par_at_put_range (if parallel). The range is made up of the - // cards that are spanned by an object/mem region so 8 cards will - // allow up to object sizes up to 4K to be handled using the loop. - if ((end_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { - bm->set_bit(i); - } - } else { - bm->set_range(start_idx, end_idx); - } - } - - // We cache the last mark set. This avoids setting the same bit multiple times. - // This is particularly interesting for dense bitmaps, as this avoids doing - // lots of work most of the time. - BitMap::idx_t _last_marked_bit_idx; - - // Mark the card liveness bitmap for the object spanning from start to end. - void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { - BitMap::idx_t start_idx = card_live_bitmap_index_for(start); - BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); - - assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); - - if (start_idx == _last_marked_bit_idx) { - start_idx++; - } - if (start_idx == end_idx) { - return; - } - - // Set the bits in the card bitmap for the cards spanned by this object. - set_card_bitmap_range(_card_bm, start_idx, end_idx); - _last_marked_bit_idx = end_idx - 1; - } - - void reset_mark_cache() { - _last_marked_bit_idx = (BitMap::idx_t)-1; - } - -public: - // Returns the index in the per-card liveness count bitmap - // for the given address - inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { - // Below, the term "card num" means the result of shifting an address - // by the card shift -- address 0 corresponds to card number 0. One - // must subtract the card num of the bottom of the heap to obtain a - // card table index. - BitMap::idx_t card_num = (BitMap::idx_t)(uintptr_t(addr) >> CardTableModRefBS::card_shift); - return card_num - _heap_card_bias; - } - - // Takes a region that's not empty (i.e., it has at least one - // live object in it and sets its corresponding bit on the region - // bitmap to 1. - void set_bit_for_region(HeapRegion* hr) { - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - _region_bm->par_at_put(index, true); - } - - // Mark the range of bits covered by allocations done since the last marking - // in the given heap region, i.e. from NTAMS to top of the given region. - // Returns if there has been some allocation in this region since the last marking. - bool mark_allocated_since_marking(HeapRegion* hr) { - reset_mark_cache(); - - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* top = hr->top(); - - assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); - - // Mark the allocated-since-marking portion... - if (ntams < top) { - mark_card_bitmap_range(ntams, top); - return true; - } else { - return false; - } - } - - // Mark the range of bits covered by live objects on the mark bitmap between - // bottom and NTAMS of the given region. - // Returns the number of live bytes marked within that area for the given - // heap region. - size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { - reset_mark_cache(); - - size_t marked_bytes = 0; - - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* start = hr->bottom(); - - if (ntams <= start) { - // Skip empty regions. - return 0; - } else if (hr->is_humongous()) { - mark_card_bitmap_range(start, hr->top()); - return pointer_delta(hr->top(), start, 1); - } - - assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(ntams), p2i(hr->end())); - - // Find the first marked object at or after "start". - start = mark_bitmap->getNextMarkedWordAddress(start, ntams); - while (start < ntams) { - oop obj = oop(start); - int obj_sz = obj->size(); - HeapWord* obj_end = start + obj_sz; - - assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); - - mark_card_bitmap_range(start, obj_end); - - // Add the size of this object to the number of marked bytes. - marked_bytes += (size_t)obj_sz * HeapWordSize; - - // Find the next marked object after this one. - start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); - } - - return marked_bytes; - } - - G1LiveDataHelper(BitMap* region_bm, - BitMap* card_bm): - _region_bm(region_bm), - _card_bm(card_bm) { - //assert(region_bm != NULL, ""); - assert(card_bm != NULL, ""); - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_card_bias = - (BitMap::idx_t)(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> CardTableModRefBS::card_shift); - } -}; - -// Heap region closure used for verifying the live count data -// that was created concurrently and finalized during -// the remark pause. This closure is applied to the heap -// regions during the STW cleanup pause. -class G1VerifyLiveDataHRClosure: public HeapRegionClosure { -private: - G1CollectedHeap* _g1h; - G1CMBitMap* _mark_bitmap; - G1LiveDataHelper _calc_helper; - - BitMap* _act_region_bm; // Region BM to be verified - BitMap* _act_card_bm; // Card BM to be verified - - BitMap* _exp_region_bm; // Expected Region BM values - BitMap* _exp_card_bm; // Expected card BM values - - int _failures; - - // Updates the live data count for the given heap region and returns the number - // of bytes marked. - size_t create_live_data_count(HeapRegion* hr) { - size_t bytes_marked = _calc_helper.mark_marked_during_marking(_mark_bitmap, hr); - bool allocated_since_marking = _calc_helper.mark_allocated_since_marking(hr); - if (allocated_since_marking || bytes_marked > 0) { - _calc_helper.set_bit_for_region(hr); - } - return bytes_marked; - } - -public: - G1VerifyLiveDataHRClosure(G1CollectedHeap* g1h, - G1CMBitMap* mark_bitmap, - BitMap* act_region_bm, - BitMap* act_card_bm, - BitMap* exp_region_bm, - BitMap* exp_card_bm) : - _g1h(g1h), - _mark_bitmap(mark_bitmap), - _calc_helper(exp_region_bm, exp_card_bm), - _act_region_bm(act_region_bm), - _act_card_bm(act_card_bm), - _exp_region_bm(exp_region_bm), - _exp_card_bm(exp_card_bm), - _failures(0) { } - - int failures() const { return _failures; } - - bool doHeapRegion(HeapRegion* hr) { - int failures = 0; - - // Walk the marking bitmap for this region and set the corresponding bits - // in the expected region and card bitmaps. - size_t exp_marked_bytes = create_live_data_count(hr); - size_t act_marked_bytes = hr->next_marked_bytes(); - // Verify the marked bytes for this region. - - if (exp_marked_bytes != act_marked_bytes) { - failures += 1; - } else if (exp_marked_bytes > HeapRegion::GrainBytes) { - failures += 1; - } - - // Verify the bit, for this region, in the actual and expected - // (which was just calculated) region bit maps. - // We're not OK if the bit in the calculated expected region - // bitmap is set and the bit in the actual region bitmap is not. - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - - bool expected = _exp_region_bm->at(index); - bool actual = _act_region_bm->at(index); - if (expected && !actual) { - failures += 1; - } - - // Verify that the card bit maps for the cards spanned by the current - // region match. We have an error if we have a set bit in the expected - // bit map and the corresponding bit in the actual bitmap is not set. - - BitMap::idx_t start_idx = _calc_helper.card_live_bitmap_index_for(hr->bottom()); - BitMap::idx_t end_idx = _calc_helper.card_live_bitmap_index_for(hr->top()); - - for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { - expected = _exp_card_bm->at(i); - actual = _act_card_bm->at(i); - - if (expected && !actual) { - failures += 1; - } - } - - _failures += failures; - - // We could stop iteration over the heap when we - // find the first violating region by returning true. - return false; - } -}; - -class G1VerifyLiveDataTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1CMBitMap* _mark_bitmap; - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - BitMap _expected_region_bm; - BitMap _expected_card_bm; - - int _failures; - - HeapRegionClaimer _hr_claimer; - -public: - G1VerifyLiveDataTask(G1CollectedHeap* g1h, - G1CMBitMap* bitmap, - BitMap* region_bm, - BitMap* card_bm, - uint n_workers) - : AbstractGangTask("G1 verify final counting"), - _g1h(g1h), - _mark_bitmap(bitmap), - _actual_region_bm(region_bm), - _actual_card_bm(card_bm), - _expected_region_bm(region_bm->size(), true /* in_resource_area */), - _expected_card_bm(card_bm->size(), true /* in_resource_area */), - _failures(0), - _hr_claimer(n_workers) { - assert(VerifyDuringGC, "don't call this otherwise"); - } - - void work(uint worker_id) { - G1VerifyLiveDataHRClosure cl(_g1h, - _mark_bitmap, - _actual_region_bm, - _actual_card_bm, - &_expected_region_bm, - &_expected_card_bm); - _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - - Atomic::add(cl.failures(), &_failures); - } - - int failures() const { return _failures; } -}; - -class G1FinalizeLiveDataTask: public AbstractGangTask { - // Finalizes the liveness counting data. - // Sets the bits corresponding to the interval [NTAMS, top] - // (which contains the implicitly live objects) in the - // card liveness bitmap. Also sets the bit for each region - // containing live data, in the region liveness bitmap. - class G1FinalizeCountDataClosure: public HeapRegionClosure { - private: - G1LiveDataHelper _helper; - public: - G1FinalizeCountDataClosure(G1CMBitMap* bitmap, - BitMap* region_bm, - BitMap* card_bm) : - HeapRegionClosure(), - _helper(region_bm, card_bm) { } - - bool doHeapRegion(HeapRegion* hr) { - bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); - if (allocated_since_marking || hr->next_marked_bytes() > 0) { - _helper.set_bit_for_region(hr); - } - return false; - } - }; - - G1CMBitMap* _bitmap; - - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - HeapRegionClaimer _hr_claimer; - -public: - G1FinalizeLiveDataTask(G1CMBitMap* bitmap, BitMap* region_bm, BitMap* card_bm, uint n_workers) : - AbstractGangTask("G1 final counting"), - _bitmap(bitmap), - _actual_region_bm(region_bm), - _actual_card_bm(card_bm), - _hr_claimer(n_workers) { - } - - void work(uint worker_id) { - G1FinalizeCountDataClosure cl(_bitmap, - _actual_region_bm, - _actual_card_bm); - - G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - } -}; - class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { G1CollectedHeap* _g1; size_t _freed_bytes; @@ -1613,26 +1248,13 @@ void G1ConcurrentMark::cleanup() { HeapRegionRemSet::reset_for_cleanup_tasks(); { - // Finalize the live data. - G1FinalizeLiveDataTask cl(_nextMarkBitMap, - &_region_live_bm, - &_card_live_bm, - g1h->workers()->active_workers()); - g1h->workers()->run_task(&cl); + GCTraceTime(Debug, gc)("Finalize Live Data"); + finalize_live_data(); } if (VerifyDuringGC) { - // Verify that the liveness count data created concurrently matches one created - // during this safepoint. - ResourceMark rm; - G1VerifyLiveDataTask cl(G1CollectedHeap::heap(), - _nextMarkBitMap, - &_region_live_bm, - &_card_live_bm, - g1h->workers()->active_workers()); - g1h->workers()->run_task(&cl); - - guarantee(cl.failures() == 0, "Unexpected accounting failures"); + GCTraceTime(Debug, gc)("Verify Live Data"); + verify_live_data(); } g1h->collector_state()->set_mark_in_progress(false); @@ -1669,7 +1291,7 @@ void G1ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - g1h->scrub_rem_set(&_region_live_bm, &_card_live_bm); + g1h->scrub_rem_set(); _total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start); } @@ -2115,35 +1737,6 @@ void G1ConcurrentMark::swapMarkBitMaps() { _nextMarkBitMap = (G1CMBitMap*) temp; } -BitMap G1ConcurrentMark::allocate_large_bitmap(BitMap::idx_t size_in_bits) { - size_t size_in_words = BitMap::size_in_words(size_in_bits); - - BitMap::bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); - - return BitMap(map, size_in_bits); -} - -void G1ConcurrentMark::allocate_internal_bitmaps() { - double start_time = os::elapsedTime(); - - _region_live_bm = allocate_large_bitmap(_g1h->max_regions()); - - guarantee(_g1h->max_capacity() % CardTableModRefBS::card_size == 0, - "Heap capacity must be aligned to card size."); - _card_live_bm = allocate_large_bitmap(_g1h->max_capacity() / CardTableModRefBS::card_size); - - log_debug(gc, marking)("Allocating internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); -} - -void G1ConcurrentMark::pretouch_internal_bitmaps() { - double start_time = os::elapsedTime(); - - _region_live_bm.pretouch(); - _card_live_bm.pretouch(); - - log_debug(gc, marking)("Pre-touching internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); -} - // Closure for marking entries in SATB buffers. class G1CMSATBBufferClosure : public SATBBufferClosure { private: @@ -2403,120 +1996,28 @@ void G1ConcurrentMark::verify_no_cset_oops() { } } #endif // PRODUCT - -class G1CreateLiveDataTask: public AbstractGangTask { - // Aggregate the counting data that was constructed concurrently - // with marking. - class G1CreateLiveDataHRClosure: public HeapRegionClosure { - G1LiveDataHelper _helper; - - G1CMBitMap* _mark_bitmap; - - G1ConcurrentMark* _cm; - public: - G1CreateLiveDataHRClosure(G1ConcurrentMark* cm, - G1CMBitMap* mark_bitmap, - BitMap* cm_card_bm) : - HeapRegionClosure(), - _helper(NULL, cm_card_bm), - _mark_bitmap(mark_bitmap), - _cm(cm) { } - - bool doHeapRegion(HeapRegion* hr) { - size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); - if (marked_bytes > 0) { - hr->add_to_marked_bytes(marked_bytes); - } - - if (_cm->do_yield_check() && _cm->has_aborted()) { - return true; - } - return false; - } - }; - - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - BitMap* _cm_card_bm; - HeapRegionClaimer _hr_claimer; - -public: - G1CreateLiveDataTask(G1CollectedHeap* g1h, - BitMap* cm_card_bm, - uint n_workers) : - AbstractGangTask("Create Live Data"), - _g1h(g1h), - _cm_card_bm(cm_card_bm), - _hr_claimer(n_workers) { - } - - void work(uint worker_id) { - SuspendibleThreadSetJoiner sts_join; - - G1CreateLiveDataHRClosure cl(_g1h->concurrent_mark(), _g1h->concurrent_mark()->nextMarkBitMap(), _cm_card_bm); - _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - } -}; - - void G1ConcurrentMark::create_live_data() { - uint n_workers = _parallel_workers->active_workers(); - - G1CreateLiveDataTask cl(_g1h, - &_card_live_bm, - n_workers); - _parallel_workers->run_task(&cl); + _g1h->g1_rem_set()->create_card_live_data(_parallel_workers, _nextMarkBitMap); } -class G1ClearAllLiveDataTask : public AbstractGangTask { - BitMap* _bitmap; - size_t _num_tasks; - size_t _cur_task; -public: - G1ClearAllLiveDataTask(BitMap* bitmap, size_t num_tasks) : - AbstractGangTask("Clear All Live Data"), - _bitmap(bitmap), - _num_tasks(num_tasks), - _cur_task(0) { - } - - virtual void work(uint worker_id) { - while (true) { - size_t to_process = Atomic::add(1, &_cur_task) - 1; - if (to_process >= _num_tasks) { - break; - } - - BitMap::idx_t start = M * BitsPerByte * to_process; - BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap->size()); - _bitmap->clear_range(start, end); - } - } -}; - -void G1ConcurrentMark::clear_all_live_data(WorkGang* workers) { - double start_time = os::elapsedTime(); - - guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); - - size_t const num_chunks = align_size_up(_card_live_bm.size_in_words() * HeapWordSize, M) / M; - - G1ClearAllLiveDataTask cl(&_card_live_bm, num_chunks); - workers->run_task(&cl); - - // The region live bitmap is always very small, even for huge heaps. Clear - // directly. - _region_live_bm.clear(); - - - log_debug(gc, marking)("Clear Live Data took %.3fms", (os::elapsedTime() - start_time) * 1000.0); +void G1ConcurrentMark::finalize_live_data() { + _g1h->g1_rem_set()->finalize_card_live_data(_g1h->workers(), _nextMarkBitMap); } -void G1ConcurrentMark::verify_all_live_data() { - assert(_card_live_bm.count_one_bits() == 0, "Master card bitmap not clear"); - assert(_region_live_bm.count_one_bits() == 0, "Master region bitmap not clear"); +void G1ConcurrentMark::verify_live_data() { + _g1h->g1_rem_set()->verify_card_live_data(_g1h->workers(), _nextMarkBitMap); } +void G1ConcurrentMark::clear_live_data(WorkGang* workers) { + _g1h->g1_rem_set()->clear_card_live_data(workers); +} + +#ifdef ASSERT +void G1ConcurrentMark::verify_live_data_clear() { + _g1h->g1_rem_set()->verify_card_live_data_is_clear(); +} +#endif + void G1ConcurrentMark::print_stats() { if (!log_is_enabled(Debug, gc, stats)) { return; @@ -2536,14 +2037,22 @@ void G1ConcurrentMark::abort() { // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next // concurrent bitmap clearing. - clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); - + { + GCTraceTime(Debug, gc)("Clear Next Bitmap"); + clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); + } // Note we cannot clear the previous marking bitmap here // since VerifyDuringGC verifies the objects marked during // a full GC against the previous bitmap. - clear_all_live_data(_g1h->workers()); - DEBUG_ONLY(verify_all_live_data()); + { + GCTraceTime(Debug, gc)("Clear Live Data"); + clear_live_data(_g1h->workers()); + } + DEBUG_ONLY({ + GCTraceTime(Debug, gc)("Verify Live Data Clear"); + verify_live_data_clear(); + }) // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { @@ -2610,16 +2119,6 @@ void G1ConcurrentMark::print_on_error(outputStream* st) const { _nextMarkBitMap->print_on_error(st, " Next Bits: "); } -// We take a break if someone is trying to stop the world. -bool G1ConcurrentMark::do_yield_check(uint worker_id) { - if (SuspendibleThreadSet::should_yield()) { - SuspendibleThreadSet::yield(); - return true; - } else { - return false; - } -} - // Closure for iteration over bitmaps class G1CMBitMapClosure : public BitMapClosure { private: diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index fb621e34980..36fb602de82 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -298,15 +298,6 @@ protected: G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap - // Liveness count data. After marking G1 iterates over the recently gathered mark - // bitmap and records rough information about liveness on card and region basis. - // This information can be used for e.g. remembered set scrubbing. - - // A set bit indicates whether the given region contains any live object. - BitMap _region_live_bm; - // A set bit indicates that the given card contains a live object. - BitMap _card_live_bm; - // Heap bounds HeapWord* _heap_start; HeapWord* _heap_end; @@ -379,14 +370,6 @@ protected: void swapMarkBitMaps(); - // Allocates and returns a zero-ed out "large" bitmap of the given size in bits. - // It is always allocated using virtual memory. - BitMap allocate_large_bitmap(BitMap::idx_t size_in_bits); - // Allocates the memory for all bitmaps used by the concurrent marking. - void allocate_internal_bitmaps(); - // Pre-touches the internal bitmaps. - void pretouch_internal_bitmaps(); - // It resets the global marking data structures, as well as the // task local ones; should be called during initial mark. void reset(); @@ -592,7 +575,7 @@ public: void scan_root_regions(); // Scan a single root region and mark everything reachable from it. - void scanRootRegion(HeapRegion* hr, uint worker_id); + void scanRootRegion(HeapRegion* hr); // Do concurrent phase of marking, to a tentative transitive closure. void mark_from_roots(); @@ -628,7 +611,7 @@ public: inline bool isPrevMarked(oop p) const; - inline bool do_yield_check(uint worker_i = 0); + inline bool do_yield_check(); // Abandon current marking iteration due to a Full GC. void abort(); @@ -654,16 +637,19 @@ public: private: // Clear (Reset) all liveness count data. - void clear_all_live_data(WorkGang* workers); + void clear_live_data(WorkGang* workers); +#ifdef ASSERT // Verify all of the above data structures that they are in initial state. - void verify_all_live_data(); + void verify_live_data_clear(); +#endif // Aggregates the per-card liveness data based on the current marking. Also sets // the amount of marked bytes for each region. void create_live_data(); - // Verification routine + void finalize_live_data(); + void verify_live_data(); }; @@ -852,7 +838,7 @@ public: // Grey the object by marking it. If not already marked, push it on // the local queue if below the finger. - // Precondition: obj is below region's NTAMS. + // obj is below its region's NTAMS. inline void make_reference_grey(oop obj); // Grey the object (by calling make_grey_reference) if required, diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 053de4b9673..b0401d35935 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -27,6 +27,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" #include "gc/shared/taskqueue.inline.hpp" inline bool G1ConcurrentMark::par_mark(oop obj) { @@ -258,4 +259,13 @@ inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { } } +inline bool G1ConcurrentMark::do_yield_check() { + if (SuspendibleThreadSet::should_yield()) { + SuspendibleThreadSet::yield(); + return true; + } else { + return false; + } +} + #endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index 05f90f75f4e..5de38f71bd2 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -186,11 +186,9 @@ class G1RootRegionScanClosure : public MetadataAwareOopClosure { private: G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; - uint _worker_id; public: - G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, - uint worker_id) : - _g1h(g1h), _cm(cm), _worker_id(worker_id) { } + G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm) : + _g1h(g1h), _cm(cm) { } template void do_oop_nv(T* p); virtual void do_oop( oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index eb091443887..12ed0506d94 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -38,6 +38,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -84,8 +85,16 @@ uint G1RemSet::num_par_rem_sets() { return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); } -void G1RemSet::initialize(uint max_regions) { +void G1RemSet::initialize(size_t capacity, uint max_regions) { G1FromCardCache::initialize(num_par_rem_sets(), max_regions); + { + GCTraceTime(Debug, gc, marking)("Initialize Card Live Data"); + _card_live_data.initialize(capacity, max_regions); + } + if (G1PretouchAuxiliaryMemory) { + GCTraceTime(Debug, gc, marking)("Pre-Touch Card Live Data"); + _card_live_data.pretouch(); + } } ScanRSClosure::ScanRSClosure(G1ParPushHeapRSClosure* oc, @@ -312,27 +321,24 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { _into_cset_dirty_card_queue_set.clear_n_completed_buffers(); } -class ScrubRSClosure: public HeapRegionClosure { +class G1ScrubRSClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - BitMap* _region_bm; - BitMap* _card_bm; - CardTableModRefBS* _ctbs; + G1CardLiveData* _live_data; public: - ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : + G1ScrubRSClosure(G1CardLiveData* live_data) : _g1h(G1CollectedHeap::heap()), - _region_bm(region_bm), _card_bm(card_bm), - _ctbs(_g1h->g1_barrier_set()) {} + _live_data(live_data) { } bool doHeapRegion(HeapRegion* r) { if (!r->is_continues_humongous()) { - r->rem_set()->scrub(_ctbs, _region_bm, _card_bm); + r->rem_set()->scrub(_live_data); } return false; } }; -void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { - ScrubRSClosure scrub_cl(region_bm, card_bm); +void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) { + G1ScrubRSClosure scrub_cl(&_card_live_data); _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); } @@ -580,3 +586,25 @@ void G1RemSet::prepare_for_verify() { assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); } } + +void G1RemSet::create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.create(workers, mark_bitmap); +} + +void G1RemSet::finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.finalize(workers, mark_bitmap); +} + +void G1RemSet::verify_card_live_data(WorkGang* workers, G1CMBitMap* bitmap) { + _card_live_data.verify(workers, bitmap); +} + +void G1RemSet::clear_card_live_data(WorkGang* workers) { + _card_live_data.clear(workers); +} + +#ifdef ASSERT +void G1RemSet::verify_card_live_data_is_clear() { + _card_live_data.verify_is_clear(); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp index 8aab4ca498c..381d5fd8f72 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_G1_G1REMSET_HPP #include "gc/g1/dirtyCardQueue.hpp" +#include "gc/g1/g1CardLiveData.hpp" #include "gc/g1/g1RemSetSummary.hpp" #include "gc/g1/heapRegion.hpp" #include "memory/allocation.hpp" @@ -48,9 +49,10 @@ class HeapRegionClaimer; // A G1RemSet in which each heap region has a rem set that records the // external heap references into it. Uses a mod ref bs to track updates, // so that they can be used to update the individual region remsets. - class G1RemSet: public CHeapObj { private: + G1CardLiveData _card_live_data; + G1RemSetSummary _prev_period_summary; // A DirtyCardQueueSet that is used to hold cards that contain @@ -83,7 +85,7 @@ public: static uint num_par_rem_sets(); // Initialize data that depends on the heap size being known. - static void initialize(uint max_regions); + void initialize(size_t capacity, uint max_regions); // This is called to reset dual hash tables after the gc pause // is finished and the initial hash table is no longer being @@ -140,7 +142,7 @@ public: // set entries that correspond to dead heap ranges. "worker_num" is the // parallel thread id of the current thread, and "hrclaimer" is the // HeapRegionClaimer that should be used. - void scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer* hrclaimer); + void scrub(uint worker_num, HeapRegionClaimer* hrclaimer); // Refine the card corresponding to "card_ptr". // If check_for_refs_into_cset is true, a true result is returned @@ -162,6 +164,19 @@ public: size_t conc_refine_cards() const { return _conc_refine_cards; } + + void create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + void finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify_card_live_data(WorkGang* workers, G1CMBitMap* actual_bitmap); + + void clear_card_live_data(WorkGang* workers); + +#ifdef ASSERT + void verify_card_live_data_is_clear(); +#endif }; class ScanRSClosure : public HeapRegionClosure { diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 26d5ce3e7e0..4fee9c4ecfc 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -26,6 +26,7 @@ #include "gc/g1/concurrentG1Refine.hpp" #include "gc/g1/g1BlockOffsetTable.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/space.inline.hpp" @@ -141,10 +142,8 @@ public: add_reference_work(from, /*parallel*/ false); } - void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) { - HeapWord* hr_bot = hr()->bottom(); - size_t hr_first_card_index = ctbs->index_for(hr_bot); - bm()->set_intersection_at_offset(*card_bm, hr_first_card_index); + void scrub(G1CardLiveData* live_data) { + live_data->remove_nonlive_cards(hr()->hrm_index(), &_bm); recount_occupied(); } @@ -515,14 +514,12 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { return max; } -void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { +void OtherRegionsTable::scrub(G1CardLiveData* live_data) { // First eliminated garbage regions from the coarse map. log_develop_trace(gc, remset, scrub)("Scrubbing region %u:", _hr->hrm_index()); - assert(_coarse_map.size() == region_bm->size(), "Precondition"); log_develop_trace(gc, remset, scrub)(" Coarse map: before = " SIZE_FORMAT "...", _n_coarse_entries); - _coarse_map.set_intersection(*region_bm); + live_data->remove_nonlive_regions(&_coarse_map); _n_coarse_entries = _coarse_map.count_one_bits(); log_develop_trace(gc, remset, scrub)(" after = " SIZE_FORMAT ".", _n_coarse_entries); @@ -534,7 +531,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, PerRegionTable* nxt = cur->collision_list_next(); // If the entire region is dead, eliminate. log_develop_trace(gc, remset, scrub)(" For other region %u:", cur->hr()->hrm_index()); - if (!region_bm->at((size_t) cur->hr()->hrm_index())) { + if (!live_data->is_region_live(cur->hr()->hrm_index())) { *prev = nxt; cur->set_collision_list_next(NULL); _n_fine_entries--; @@ -544,7 +541,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, } else { // Do fine-grain elimination. log_develop_trace(gc, remset, scrub)(" occ: before = %4d.", cur->occupied()); - cur->scrub(ctbs, card_bm); + cur->scrub(live_data); log_develop_trace(gc, remset, scrub)(" after = %4d.", cur->occupied()); // Did that empty the table completely? if (cur->occupied() == 0) { @@ -773,9 +770,8 @@ void HeapRegionRemSet::reset_for_par_iteration() { assert(verify_ready_for_par_iteration(), "post-condition"); } -void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { - _other_regions.scrub(ctbs, region_bm, card_bm); +void HeapRegionRemSet::scrub(G1CardLiveData* live_data) { + _other_regions.scrub(live_data); } // Code roots support diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp index 5a286bc2836..c884dab2484 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp @@ -35,6 +35,7 @@ class G1CollectedHeap; class G1BlockOffsetTable; +class G1CardLiveData; class HeapRegion; class HeapRegionRemSetIterator; class PerRegionTable; @@ -143,7 +144,7 @@ public: // Removes any entries shown by the given bitmaps to contain only dead // objects. Not thread safe. // Set bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // Returns whether this remembered set (and all sub-sets) does not contain any entry. bool is_empty() const; @@ -230,10 +231,9 @@ public: _other_regions.add_reference(from, tid); } - // Removes any entries in the remembered set shown by the given bitmaps to + // Removes any entries in the remembered set shown by the given card live data to // contain only dead objects. Not thread safe. - // One bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // The region is being reclaimed; clear its remset, and any mention of // entries for this region in other remsets. diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index 7804c988487..bb7ae8ede14 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -69,7 +69,7 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { } void BitMap::pretouch() { - os::pretouch_memory((char*)word_addr(0), (char*)word_addr(size())); + os::pretouch_memory(word_addr(0), word_addr(size())); } void BitMap::set_range_within_word(idx_t beg, idx_t end) { diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index 0e46cea9917..b925d66442f 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,11 +140,12 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // Accessing idx_t size() const { return _size; } + idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; } idx_t size_in_words() const { - return word_index(size() + BitsPerWord - 1); + return calc_size_in_words(size()); } - static idx_t size_in_words(size_t size_in_bits) { + static idx_t calc_size_in_words(size_t size_in_bits) { return word_index(size_in_bits + BitsPerWord - 1); } From af3081628b5fbb42ed672b4a035fab3f66e109c3 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 6 Apr 2016 20:43:03 +0900 Subject: [PATCH 038/113] 8152435: (CL)HSDB should be started with no argument Reviewed-by: dsamersoff --- .../classes/sun/jvm/hotspot/SAGetopt.java | 12 +++--- .../sun/jvm/hotspot/SAGetoptException.java | 33 ++++++++++++++++ .../classes/sun/jvm/hotspot/SALauncher.java | 39 +++++++++---------- 3 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java index 3d4ffb0171b..d23a057f584 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java @@ -55,11 +55,11 @@ public class SAGetopt { private void extractOptarg(String opt) { // Argument expected if (_optind > _argv.length) { - throw new RuntimeException("Not enough arguments for '" + opt + "'"); + throw new SAGetoptException("Not enough arguments for '" + opt + "'"); } if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') { - throw new RuntimeException("Argument is expected for '" + opt + "'"); + throw new SAGetoptException("Argument is expected for '" + opt + "'"); } _optarg = _argv[_optind]; @@ -72,7 +72,7 @@ public class SAGetopt { if (los.contains(ca[0])) { if (ca.length > 1) { - throw new RuntimeException("Argument is not expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is not expected for '" + ca[0] + "'"); } return carg; } @@ -87,14 +87,14 @@ public class SAGetopt { try { extractOptarg(ca[0]); } catch (ArrayIndexOutOfBoundsException e) { - throw new RuntimeException("Argument is expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is expected for '" + ca[0] + "'"); } } return ca[0]; } - throw new RuntimeException("Invalid option '" + ca[0] + "'"); + throw new SAGetoptException("Invalid option '" + ca[0] + "'"); } public String next(String optStr, String[] longOptStr) { @@ -148,7 +148,7 @@ public class SAGetopt { int chIndex = optStr.indexOf(ch); if (chIndex == -1) { - throw new RuntimeException("Invalid option '" + ch + "'"); + throw new SAGetoptException("Invalid option '" + ch + "'"); } if (_optopt >= carg.length()) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java new file mode 100644 index 00000000000..f6ba480ca33 --- /dev/null +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot; + +public class SAGetoptException extends IllegalArgumentException { + + public SAGetoptException(String message) { + super(message); + } + +} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java index 4b1f280a6d7..dfbbb6ff440 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java @@ -111,34 +111,31 @@ public class SALauncher { return launcherHelp(); } - private static void buildAttachArgs(ArrayList newArgs, - String pid, String exe, String core) { - if ((pid == null) && (exe == null)) { - throw new IllegalArgumentException( - "You have to set --pid or --exe."); + private static void buildAttachArgs(ArrayList newArgs, String pid, + String exe, String core, boolean allowEmpty) { + if (!allowEmpty && (pid == null) && (exe == null)) { + throw new SAGetoptException("You have to set --pid or --exe."); } if (pid != null) { // Attach to live process if (exe != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --exe"); + throw new SAGetoptException("Unnecessary argument: --exe"); } else if (core != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --core"); + throw new SAGetoptException("Unnecessary argument: --core"); } else if (!pid.matches("^\\d+$")) { - throw new IllegalArgumentException("Invalid pid: " + pid); + throw new SAGetoptException("Invalid pid: " + pid); } newArgs.add(pid); - } else { + } else if (exe != null) { if (exe.length() == 0) { - throw new IllegalArgumentException("You have to set --exe."); + throw new SAGetoptException("You have to set --exe."); } newArgs.add(exe); if ((core == null) || (core.length() == 0)) { - throw new IllegalArgumentException("You have to set --core."); + throw new SAGetoptException("You have to set --core."); } newArgs.add(core); @@ -170,7 +167,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -199,7 +196,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); HSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -237,7 +234,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JStack.main(newArgs.toArray(new String[newArgs.size()])); } @@ -287,7 +284,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JMap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -325,7 +322,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JInfo.main(newArgs.toArray(new String[newArgs.size()])); } @@ -358,7 +355,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JSnap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -416,8 +413,8 @@ public class SALauncher { return; } - throw new IllegalArgumentException("Unknown tool: " + args[0]); - } catch (Exception e) { + throw new SAGetoptException("Unknown tool: " + args[0]); + } catch (SAGetoptException e) { System.err.println(e.getMessage()); toolHelp(args[0]); } From c282f259646f0648c1dabe0252de7572cd78e3ba Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 6 Apr 2016 11:40:45 -0700 Subject: [PATCH 039/113] 8152329: jvm should treat the "Multi-Release" jar manifest attribute name as case insensitive Reviewed-by: iklam, jiangli, mseledtsov --- hotspot/src/share/vm/classfile/classLoader.cpp | 12 ++++++++++-- hotspot/src/share/vm/classfile/classLoader.hpp | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index bdf18bc55e0..a8a86765970 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -233,6 +233,7 @@ ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_ strcpy(copy, zip_name); _zip_name = copy; _is_boot_append = is_boot_append; + _multi_versioned = _unknown; } ClassPathZipEntry::~ClassPathZipEntry() { @@ -330,13 +331,20 @@ u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TR bool ClassPathZipEntry::is_multiple_versioned(TRAPS) { assert(DumpSharedSpaces, "called only at dump time"); + if (_multi_versioned != _unknown) { + return (_multi_versioned == _yes) ? true : false; + } jint size; - char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false); + char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, true, CHECK_false); if (buffer != NULL) { - if (strstr(buffer, "Multi-Release: true") != NULL) { + char* p = buffer; + for ( ; *p; ++p) *p = tolower(*p); + if (strstr(buffer, "multi-release: true") != NULL) { + _multi_versioned = _yes; return true; } } + _multi_versioned = _no; return false; } #endif // INCLUDE_CDS diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 8ac282727d5..fc1d335b7ab 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -101,10 +101,17 @@ typedef struct { class ClassPathZipEntry: public ClassPathEntry { + enum { + _unknown = 0, + _yes = 1, + _no = 2 + }; private: jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive bool _is_boot_append; // entry coming from -Xbootclasspath/a + u1 _multi_versioned; // indicates if the jar file has multi-versioned entries. + // It can have value of "_unknown", "_yes", or "_no" public: bool is_jrt() { return false; } bool is_jar_file() const { return true; } From f22c068365fdb645e21786cd190874021f89b4b5 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Thu, 7 Apr 2016 10:55:54 +0200 Subject: [PATCH 040/113] 8152312: ParNew: Restore preserved marks in parallel Reviewed-by: tschatzl --- .../share/vm/gc/serial/defNewGeneration.cpp | 5 +- .../src/share/vm/gc/shared/preservedMarks.cpp | 75 ++++++++++++++----- .../src/share/vm/gc/shared/preservedMarks.hpp | 37 +++++++-- .../vm/gc/shared/preservedMarks.inline.hpp | 52 ++++++++++++- 4 files changed, 137 insertions(+), 32 deletions(-) diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index a9b404604b0..247c7e3e49a 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -692,7 +692,7 @@ void DefNewGeneration::collect(bool full, _promo_failure_scan_stack.clear(true); // Clear cached segments. remove_forwarding_pointers(); - log_debug(gc)("Promotion failed"); + log_info(gc, promotion)("Promotion failed"); // Add to-space to the list of space to compact // when a promotion failure has occurred. In that // case there can be live objects in to-space @@ -739,8 +739,7 @@ void DefNewGeneration::remove_forwarding_pointers() { eden()->object_iterate(&rspc); from()->object_iterate(&rspc); - // Now restore saved marks, if any. - _preserved_marks_set.restore(); + _preserved_marks_set.restore(GenCollectedHeap::heap()->workers()); } void DefNewGeneration::handle_promotion_failure(oop old) { diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp index e6950ff78b6..96d124e2259 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp @@ -24,24 +24,30 @@ #include "precompiled.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shared/workgroup.hpp" #include "memory/allocation.inline.hpp" -#include "oops/oop.inline.hpp" void PreservedMarks::restore() { - // First, iterate over the stack and restore all marks. - StackIterator iter(_stack); - while (!iter.is_empty()) { - OopAndMarkOop elem = iter.next(); + while (!_stack.is_empty()) { + const OopAndMarkOop elem = _stack.pop(); elem.set_mark(); } - - // Second, reclaim all the stack memory - _stack.clear(true /* clear_cache */); + assert_empty(); } +#ifndef PRODUCT +void PreservedMarks::assert_empty() { + assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT, + _stack.size()); + assert(_stack.cache_size() == 0, + "stack expected to have no cached segments, cache size = "SIZE_FORMAT, + _stack.cache_size()); +} +#endif // ndef PRODUCT + void RemoveForwardedPointerClosure::do_object(oop obj) { if (obj->is_forwarded()) { - obj->init_mark(); + PreservedMarks::init_forwarded_mark(obj); } } @@ -61,15 +67,48 @@ void PreservedMarksSet::init(uint num) { assert_empty(); } -void PreservedMarksSet::restore() { - size_t total_size = 0; - for (uint i = 0; i < _num; i += 1) { - total_size += get(i)->size(); - get(i)->restore(); - } - assert_empty(); +class ParRestoreTask : public AbstractGangTask { +private: + PreservedMarksSet* const _preserved_marks_set; + SequentialSubTasksDone _sub_tasks; + volatile size_t* const _total_size_addr; - log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); +public: + virtual void work(uint worker_id) { + uint task_id = 0; + while (!_sub_tasks.is_task_claimed(/* reference */ task_id)) { + PreservedMarks* const preserved_marks = _preserved_marks_set->get(task_id); + const size_t size = preserved_marks->size(); + preserved_marks->restore(); + // Only do the atomic add if the size is > 0. + if (size > 0) { + Atomic::add(size, _total_size_addr); + } + } + _sub_tasks.all_tasks_completed(); + } + + ParRestoreTask(uint worker_num, + PreservedMarksSet* preserved_marks_set, + volatile size_t* total_size_addr) + : AbstractGangTask("Parallel Preserved Mark Restoration"), + _preserved_marks_set(preserved_marks_set), + _total_size_addr(total_size_addr) { + _sub_tasks.set_n_threads(worker_num); + _sub_tasks.set_n_tasks(preserved_marks_set->num()); + } +}; + +void PreservedMarksSet::restore_internal(WorkGang* workers, + volatile size_t* total_size_addr) { + assert(workers != NULL, "pre-condition"); + ParRestoreTask task(workers->active_workers(), this, total_size_addr); + workers->run_task(&task); +} + +// temporary, used by PS +void PreservedMarksSet::restore() { + restore(NULL); } void PreservedMarksSet::reclaim() { @@ -92,7 +131,7 @@ void PreservedMarksSet::reclaim() { void PreservedMarksSet::assert_empty() { assert(_stacks != NULL && _num > 0, "should have been initialized"); for (uint i = 0; i < _num; i += 1) { - assert(get(i)->is_empty(), "stack should be empty"); + get(i)->assert_empty(); } } #endif // ndef PRODUCT diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp index 729f0666b17..6ab52ba0fb4 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp @@ -44,6 +44,8 @@ public: }; typedef Stack OopAndMarkOopStack; +class WorkGang; + class PreservedMarks VALUE_OBJ_CLASS_SPEC { private: OopAndMarkOopStack _stack; @@ -52,13 +54,19 @@ private: inline void push(oop obj, markOop m); public: - bool is_empty() const { return _stack.is_empty(); } size_t size() const { return _stack.size(); } inline void push_if_necessary(oop obj, markOop m); - // Iterate over the stack, restore the preserved marks, then reclaim - // the memory taken up by stack chunks. + // Iterate over the stack, restore all preserved marks, and + // reclaim the memory taken up by the stack segments. void restore(); - ~PreservedMarks() { assert(is_empty(), "should have been cleared"); } + + inline static void init_forwarded_mark(oop obj); + + // Assert the stack is empty and has no cached segments. + void assert_empty() PRODUCT_RETURN; + + inline PreservedMarks(); + ~PreservedMarks() { assert_empty(); } }; class RemoveForwardedPointerClosure: public ObjectClosure { @@ -82,7 +90,12 @@ private: // or == NULL if they have not. Padded* _stacks; + // Internal version of restore() that uses a WorkGang for parallelism. + void restore_internal(WorkGang* workers, volatile size_t* total_size_addr); + public: + uint num() const { return _num; } + // Return the i'th stack. PreservedMarks* get(uint i = 0) const { assert(_num > 0 && _stacks != NULL, "stacks should have been initialized"); @@ -92,13 +105,23 @@ public: // Allocate stack array. void init(uint num); - // Iterate over all stacks, restore all preserved marks, then - // reclaim the memory taken up by stack chunks. + + // Itrerate over all stacks, restore all presered marks, and reclaim + // the memory taken up by the stack segments. If the executor is + // NULL, restoration will be done serially. If the executor is not + // NULL, restoration could be done in parallel (when it makes + // sense). Supported executors: WorkGang (Serial, CMS, G1) + template + inline void restore(E* executor); + + // Do the restoration serially. Temporary, to be used by PS until we + // can support GCTaskManager in restore(E*). void restore(); + // Reclaim stack array. void reclaim(); - // Assert all the stacks are empty. + // Assert all the stacks are empty and have no cached segments. void assert_empty() PRODUCT_RETURN; PreservedMarksSet(bool in_c_heap) diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp index 32c83115a69..fc1039ad40b 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp @@ -22,13 +22,13 @@ * */ -#include "gc/shared/preservedMarks.hpp" -#include "oops/markOop.inline.hpp" -#include "utilities/stack.inline.hpp" - #ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP #define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP +#include "gc/shared/preservedMarks.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/stack.inline.hpp" + inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const { return m->must_be_preserved_for_promotion_failure(obj); } @@ -45,4 +45,48 @@ inline void PreservedMarks::push_if_necessary(oop obj, markOop m) { } } +inline void PreservedMarks::init_forwarded_mark(oop obj) { + obj->init_mark(); +} + +template +inline void PreservedMarksSet::restore(E* executor) { + volatile size_t total_size = 0; + +#ifdef ASSERT + // This is to make sure the total_size we'll calculate below is correct. + size_t total_size_before = 0; + for (uint i = 0; i < _num; i += 1) { + total_size_before += get(i)->size(); + } +#endif // def ASSERT + + if (executor == NULL) { + for (uint i = 0; i < _num; i += 1) { + total_size += get(i)->size(); + get(i)->restore(); + } + } else { + // Right now, if the executor is not NULL we do the work in + // parallel. In the future we might want to do the restoration + // serially, if there's only a small number of marks per stack. + restore_internal(executor, &total_size); + } + assert_empty(); + + assert(total_size == total_size_before, + "total_size = " SIZE_FORMAT " before = " SIZE_FORMAT, + total_size, total_size_before); + + log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); +} + +inline PreservedMarks::PreservedMarks() + : _stack(OopAndMarkOopStack::default_segment_size(), + // This stack should be used very infrequently so there's + // no point in caching stack segments (there will be a + // waste of space most of the time). So we set the max + // cache size to 0. + 0 /* max_cache_size */) { } + #endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP From 2b7a70a9d3d9b4ca94605d22d3d4f3c78a5c8d8b Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Thu, 7 Apr 2016 17:42:30 +0400 Subject: [PATCH 041/113] 8152432: Implement setting jtreg @requires properties vm.flavor, vm.bits, vm.compMode Reviewed-by: iignatyev --- hotspot/test/TEST.ROOT | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 55979b0a554..29c9696e7be 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -30,6 +30,10 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] + +# Source files for classes that will be used at the beginning of each test suite run, +# to determine additional characteristics of the system for use with the @requires tag. +requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java requires.properties=sun.arch.data.model # Tests using jtreg 4.2 b01 features From 412ce42184a379abe9a75b8ffb25055073d4b23d Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 7 Apr 2016 15:58:24 +0300 Subject: [PATCH 042/113] 8148376: Test for PLAB behavior at evacuation failure Reviewed-by: tschatzl, dfazunen --- .../gc/g1/plab/TestPLABEvacuationFailure.java | 203 ++++++++++++++++++ .../g1/plab/lib/AppPLABEvacuationFailure.java | 54 +++++ 2 files changed, 257 insertions(+) create mode 100644 hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java create mode 100644 hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java diff --git a/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java new file mode 100644 index 00000000000..5bcad7f2404 --- /dev/null +++ b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test TestPLABEvacuationFailure + * @bug 8148376 + * @summary Checks PLAB statistics on evacuation failure + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary / + * @modules java.management + * @build gc.g1.plab.lib.LogParser + * gc.g1.plab.lib.AppPLABEvacuationFailure + * @run main gc.g1.plab.TestPLABEvacuationFailure + */ +package gc.g1.plab; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Utils; + +import gc.g1.plab.lib.LogParser; +import gc.g1.plab.lib.AppPLABEvacuationFailure; +import gc.g1.plab.lib.PlabInfo; + +/** + * The test runs the AppPLABEvacuationFailure application to provoke a number of + * Evacuation Failures, parses GC log and analyzes PLAB statistics. The test checks + * that both fields 'failure_waste' and 'failure_used' for Evacuation Failure statistic + * are non zero, and zero for other statistics. + */ +public class TestPLABEvacuationFailure { + + /* PLAB statistics fields which are checked. + * Test expects to find 0 in this fields in survivor statistics. + * Expects to find 0 in old statistics for GC when evacuation failure + * did not happen. And expects to find not 0 in old statistics in case when + * GC causes to evacuation failure. + */ + private static final List FAILURE_STAT_FIELDS = new ArrayList<>(Arrays.asList( + "failure used", + "failure wasted")); + + private static final String[] COMMON_OPTIONS = { + "-Xlog:gc=debug,gc+plab=debug,gc+phases=trace", + "-XX:+UseG1GC", + "-XX:InitiatingHeapOccupancyPercent=100", + "-XX:-G1UseAdaptiveIHOP", + "-XX:G1HeapRegionSize=1m"}; + + private static final Pattern GC_ID_PATTERN = Pattern.compile("GC\\((\\d+)\\)"); + private static List evacuationFailureIDs; + private static LogParser logParser; + private static String appPlabEvacFailureOutput; + + public static void main(String[] args) throws Throwable { + // ParallelGCBufferWastePct, PLAB Size, ParallelGCBufferWastePct, MaxHeapSize, is plab fixed. + runTest(10, 1024, 3, 16, true); + runTest(15, 2048, 4, 256, true); + runTest(20, 65536, 7, 128, false); + runTest(25, 1024, 3, 16, true); + runTest(30, 16384, 7, 256, false); + runTest(10, 65536, 4, 32, false); + } + + private static void runTest(int wastePct, int plabSize, int parGCThreads, int heapSize, boolean plabIsFixed) throws Throwable { + System.out.println("Test case details:"); + System.out.println(" Heap size : " + heapSize + "M"); + System.out.println(" Initial PLAB size : " + plabSize); + System.out.println(" Parallel GC buffer waste pct : " + wastePct); + System.out.println(" Parallel GC threads : " + parGCThreads); + System.out.println(" PLAB size is fixed: " + (plabIsFixed ? "yes" : "no")); + // Set up test GC and PLAB options + List testOptions = new ArrayList<>(); + Collections.addAll(testOptions, COMMON_OPTIONS); + Collections.addAll(testOptions, Utils.getTestJavaOpts()); + Collections.addAll(testOptions, + "-XX:ParallelGCThreads=" + parGCThreads, + "-XX:ParallelGCBufferWastePct=" + wastePct, + "-XX:OldPLABSize=" + plabSize, + "-XX:YoungPLABSize=" + plabSize, + "-XX:" + (plabIsFixed ? "-" : "+") + "ResizePLAB", + "-XX:MaxHeapSize=" + heapSize + "m"); + testOptions.add(AppPLABEvacuationFailure.class.getName()); + OutputAnalyzer out = ProcessTools.executeTestJvm(testOptions.toArray(new String[testOptions.size()])); + + appPlabEvacFailureOutput = out.getOutput(); + if (out.getExitValue() != 0) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("Expect exit code 0."); + } + // Get list of GC ID on evacuation failure + evacuationFailureIDs = getGcIdPlabEvacFailures(out); + logParser = new LogParser(appPlabEvacFailureOutput); + checkResults(); + } + + private static void checkResults() { + + if (evacuationFailureIDs.isEmpty()) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("AppPLABEvacuationFailure did not reach Evacuation Failure."); + } + + Map valuesToCheck = getNonEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that SURVIVOR PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getNonEvacFailureOldStats(); + checkValuesIsZero(valuesToCheck, "Expect that OLD PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that failure statistics should be 0 in SURVIVOR PLAB statistics at evacuation failure"); + + valuesToCheck = getEvacFailureOldStats(); + checkValuesIsNotZero(valuesToCheck, "Expect that failure statistics should not be 0 in OLD PLAB statistics at evacuation failure"); + } + + /** + * Checks logItems for non-zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, true); + } + + /** + * Checks logItems for zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsNotZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, false); + } + + private static void checkValues(Map logItems, String errorMessage, boolean expectZero) { + logItems.entrySet() + .forEach(item -> item.getValue() + .values() + .forEach(items -> { + if (expectZero != (items == 0)) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException(errorMessage); + } + }) + ); + } + + /** + * For tracking PLAB statistics for specified PLAB type - survivor and old + */ + private static Map getNonEvacFailureSurvivorStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getNonEvacFailureOldStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureSurvivorStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureOldStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static List getGcIdPlabEvacFailures(OutputAnalyzer out) { + return out.asLines().stream() + .filter(line -> line.contains("Evacuation Failure")) + .map(line -> LogParser.getGcIdFromLine(line, GC_ID_PATTERN)) + .collect(Collectors.toList()); + } +} diff --git a/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java new file mode 100644 index 00000000000..25d797ecda5 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package gc.g1.plab.lib; + +import java.util.ArrayList; + +/** + * Application that provokes Evacuation Failure + */ +public class AppPLABEvacuationFailure { + + public static final int CHUNK = 10000; + public static ArrayList arr = new ArrayList<>(); + + public static void main(String[] args) { + System.gc(); + // First attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + // Second attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + } +} From 0202ef201cc0bc4a2d209e8fd978dbea9b7c4bc5 Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 7 Apr 2016 16:01:16 +0300 Subject: [PATCH 043/113] 8153516: Hotspot TEST.group has error in GC groups definition Reviewed-by: tschatzl, dfazunen --- hotspot/test/TEST.groups | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 527de350443..fd320ecf20f 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -386,7 +386,8 @@ hotspot_jprt = \ :hotspot_fast_compiler_2 \ :hotspot_fast_compiler_3 \ :hotspot_fast_compiler_closed \ - :hotspot_fast_gc \ + :hotspot_fast_gc_1 \ + :hotspot_fast_gc_2 \ :hotspot_fast_gc_closed \ :hotspot_fast_gc_gcold \ :hotspot_fast_runtime \ From a9cf95480ff53ae3345554488298297aba0f3345 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 7 Apr 2016 15:17:08 +0200 Subject: [PATCH 044/113] 8153734: TestHumongousReferenceObject.java occasionally crashes with "unable to allocate heap of 1g" on win32 Decrease the heap size used in the test from 1g to 128M. Reviewed-by: dfazunen, sjohanss --- .../test/gc/TestHumongousReferenceObject.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/test/gc/TestHumongousReferenceObject.java b/hotspot/test/gc/TestHumongousReferenceObject.java index 728b8911de8..7e09abfe274 100644 --- a/hotspot/test/gc/TestHumongousReferenceObject.java +++ b/hotspot/test/gc/TestHumongousReferenceObject.java @@ -27,26 +27,26 @@ import jdk.internal.vm.annotation.Contended; * @test * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries on G1, with references in them works. * @requires vm.gc == "null" - * @bug 8151499 + * @bug 8151499 8153734 * @modules java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject */ public class TestHumongousReferenceObject { /* Due to 300 fields with 8K @Contended padding around each field, it takes 2.4M bytes per instance. With small G1 regions, it is bound to cross regions. G1 should properly (card) mark the object nevertheless. - With 1G heap, it is enough to allocate ~400 of these objects to provoke at least one GC. + With 128M heap, it is enough to allocate ~100 of these objects to provoke at least one GC. */ static volatile Object instance; public static void main(String[] args) { - for (int c = 0; c < 400; c++) { + for (int c = 0; c < 100; c++) { instance = new TestHumongousReferenceObject(); } } From 24a9e0ac188a37dc57cc4d1bb8d8635abb4c4f89 Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Thu, 7 Apr 2016 17:43:35 +0400 Subject: [PATCH 045/113] 8152432: Implement setting jtreg @requires properties vm.flavor, vm.bits, vm.compMode Reviewed-by: iignatyev --- test/jtreg-ext/requires/VMProps.java | 136 +++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 test/jtreg-ext/requires/VMProps.java diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java new file mode 100644 index 00000000000..ef7de8faf39 --- /dev/null +++ b/test/jtreg-ext/requires/VMProps.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package requires; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * The Class to be invoked by jtreg prior Test Suite execution to + * collect information about VM. + * Properties set by this Class will be available in the @requires expressions. + */ +public class VMProps implements Callable> { + + /** + * Collects information about VM properties. + * This method will be invoked by jtreg. + * + * @return Map of property-value pairs. + */ + @Override + public Map call() { + Map map = new HashMap<>(); + map.put("vm.flavor", vmFlavor()); + map.put("vm.compMode", vmCompMode()); + map.put("vm.bits", vmBits()); + dump(map); + return map; + } + + /** + * @return VM type value extracted from the "java.vm.name" property. + */ + protected String vmFlavor() { + // E.g. "Java HotSpot(TM) 64-Bit Server VM" + String vmName = System.getProperty("java.vm.name"); + if (vmName == null) { + return null; + } + + Pattern startP = Pattern.compile(".* (\\S+) VM"); + Matcher m = startP.matcher(vmName); + if (m.matches()) { + return m.group(1).toLowerCase(); + } + return null; + } + + /** + * @return VM compilation mode extracted from the "java.vm.info" property. + */ + protected String vmCompMode() { + // E.g. "mixed mode" + String vmInfo = System.getProperty("java.vm.info"); + if (vmInfo == null) { + return null; + } + int k = vmInfo.toLowerCase().indexOf(" mode"); + if (k < 0) { + return null; + } + vmInfo = vmInfo.substring(0, k); + switch (vmInfo) { + case "mixed" : return "Xmixed"; + case "compiled" : return "Xcomp"; + case "interpreted" : return "Xint"; + default: return null; + } + } + + /** + * @return VM bitness, the value of the "sun.arch.data.model" property. + */ + protected String vmBits() { + return System.getProperty("sun.arch.data.model"); + } + + /** + * Dumps the map to the file if the file name is given as the property. + * This functionality could be helpful to know context in the real + * execution. + * + * @param map + */ + protected void dump(Map map) { + String dumpFileName = System.getProperty("vmprops.dump"); + if (dumpFileName == null) { + return; + } + List lines = new ArrayList<>(); + map.forEach((k,v) -> lines.add(k + ":" + v)); + try { + Files.write(Paths.get(dumpFileName), lines); + } catch (IOException e) { + throw new RuntimeException("Failed to dump properties into '" + + dumpFileName + "'", e); + } + } + + /** + * This method is for the testing purpose only. + * @param args + */ + public static void main(String args[]) { + Map map = new VMProps().call(); + map.forEach((k,v) -> System.out.println(k + ": '" + v + "'")); + } +} From 02d268d76065f5c12d79bca25ed95482e812b17d Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 7 Apr 2016 13:11:15 -0400 Subject: [PATCH 046/113] 8152896: Convert PrintCompressedOopsMode to Unified Logging Converted -XX:+PrintCompressedOopsMode to -Xlog:gc+heap+coops and aliased old option Reviewed-by: coleenp, sjohanss, kvn, hseigel --- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/memory/universe.cpp | 10 ++- hotspot/src/share/vm/memory/virtualspace.cpp | 38 ++++----- hotspot/src/share/vm/runtime/arguments.cpp | 16 ++-- hotspot/src/share/vm/runtime/globals.hpp | 3 - .../CompressedClassPointers.java | 5 +- .../CompressedOops/UseCompressedOops.java | 3 +- .../runtime/logging/CompressedOopsTest.java | 82 +++++++++++++++++++ 8 files changed, 113 insertions(+), 45 deletions(-) create mode 100644 hotspot/test/runtime/logging/CompressedOopsTest.java diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 78cb944c345..5e4fcc6a142 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -48,6 +48,7 @@ LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(constraints) \ + LOG_TAG(coops) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ LOG_TAG(defaultmethods) \ diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index f33afa87ea2..11037c539f0 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -747,8 +747,10 @@ jint Universe::initialize_heap() { Universe::set_narrow_ptrs_base(Universe::narrow_oop_base()); - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - Universe::print_compressed_oops_mode(tty); + if (log_is_enabled(Info, gc, heap, coops)) { + ResourceMark rm; + outputStream* logst = Log(gc, heap, coops)::info_stream(); + Universe::print_compressed_oops_mode(logst); } // Tell tests in which mode we run. @@ -776,8 +778,8 @@ jint Universe::initialize_heap() { } void Universe::print_compressed_oops_mode(outputStream* st) { - st->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", - p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); + st->print("Heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", + p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); st->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode())); diff --git a/hotspot/src/share/vm/memory/virtualspace.cpp b/hotspot/src/share/vm/memory/virtualspace.cpp index 76f45090ec2..31fddb745c7 100644 --- a/hotspot/src/share/vm/memory/virtualspace.cpp +++ b/hotspot/src/share/vm/memory/virtualspace.cpp @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "memory/virtualspace.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -78,10 +80,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address, // Different reserve address may be acceptable in other cases // but for compressed oops heap should be at requested address. assert(UseCompressedOops, "currently requested address used only for compressed oops"); - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); - } + log_debug(gc, heap, coops)("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); // OS ignored requested address. Try different address. if (special) { if (!os::release_memory_special(base, size)) { @@ -143,10 +142,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } } } @@ -286,11 +282,10 @@ void ReservedHeapSpace::establish_noaccess_prefix() { if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE, _special)) { fatal("cannot protect protection page"); } - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Protected page at the reserved heap base: " - PTR_FORMAT " / " INTX_FORMAT " bytes", p2i(_base), _noaccess_prefix); - } + log_debug(gc, heap, coops)("Protected page at the reserved heap base: " + PTR_FORMAT " / " INTX_FORMAT " bytes", + p2i(_base), + _noaccess_prefix); assert(Universe::narrow_oop_use_implicit_null_checks() == true, "not initialized?"); } else { Universe::set_narrow_oop_use_implicit_null_checks(false); @@ -321,10 +316,10 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, bool special = large && !os::can_commit_large_page_memory(); char* base = NULL; - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address " PTR_FORMAT " heap of size " SIZE_FORMAT_HEX ".\n", - p2i(requested_address), size); - } + log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT + " heap of size " SIZE_FORMAT_HEX, + p2i(requested_address), + size); if (special) { base = os::reserve_memory_special(size, alignment, requested_address, false); @@ -343,10 +338,7 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, // Failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } // Optimistically assume that the OSes returns an aligned base pointer. @@ -558,9 +550,7 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Last, desperate try without any placement. if (_base == NULL) { - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX ".\n", size + noaccess_prefix); - } + log_trace(gc, heap, coops)("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX, size + noaccess_prefix); initialize(size + noaccess_prefix, alignment, large, NULL, false); } } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d82452bceeb..67cf5784d0d 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -407,7 +407,9 @@ static AliasedFlag const aliased_jvm_flags[] = { { NULL, NULL} }; +// NOTE: A compatibility request will be necessary for each alias to be removed. static AliasedLoggingFlag const aliased_logging_flags[] = { + { "PrintCompressedOopsMode", LogLevel::Info, true, LOG_TAGS(gc, heap, coops) }, { "TraceBiasedLocking", LogLevel::Info, true, LOG_TAGS(biasedlocking) }, { "TraceClassLoading", LogLevel::Info, true, LOG_TAGS(classload) }, { "TraceClassLoadingPreorder", LogLevel::Debug, true, LOG_TAGS(classload, preorder) }, @@ -2184,15 +2186,11 @@ void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) { if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) { // matches compressed oops printing flags - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - jio_fprintf(defaultStream::error_stream(), - "HeapBaseMinAddress must be at least " SIZE_FORMAT - " (" SIZE_FORMAT "G) which is greater than value given " - SIZE_FORMAT "\n", - DefaultHeapBaseMinAddress, - DefaultHeapBaseMinAddress/G, - HeapBaseMinAddress); - } + log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least " SIZE_FORMAT + " (" SIZE_FORMAT "G) which is greater than value given " SIZE_FORMAT, + DefaultHeapBaseMinAddress, + DefaultHeapBaseMinAddress/G, + HeapBaseMinAddress); FLAG_SET_ERGO(size_t, HeapBaseMinAddress, DefaultHeapBaseMinAddress); } } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 105e02d8be5..12408be3ab9 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -641,9 +641,6 @@ public: "region.") \ range(1, max_uintx) \ \ - diagnostic(bool, PrintCompressedOopsMode, false, \ - "Print compressed oops base address and encoding mode") \ - \ lp64_product(intx, ObjectAlignmentInBytes, 8, \ "Default object alignment in bytes, 8 is minimum") \ range(8, 256) \ diff --git a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java index 54616e4b176..158f2fc90cd 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java +++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,8 +85,7 @@ public class CompressedClassPointers { public static void heapBaseMinAddressTest() throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:HeapBaseMinAddress=1m", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=debug", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("HeapBaseMinAddress must be at least"); diff --git a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java index ac60e764e75..707bf2f4a6e 100644 --- a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java +++ b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,6 @@ public class UseCompressedOops { ArrayList args = new ArrayList<>(); // Always run with these three: - args.add("-XX:+UnlockDiagnosticVMOptions"); args.add("-XX:+PrintCompressedOopsMode"); args.add("-Xms32m"); diff --git a/hotspot/test/runtime/logging/CompressedOopsTest.java b/hotspot/test/runtime/logging/CompressedOopsTest.java new file mode 100644 index 00000000000..fed2233674c --- /dev/null +++ b/hotspot/test/runtime/logging/CompressedOopsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149991 + * @requires (sun.arch.data.model == "64") + * @summary -Xlog:gc+heap+coops=info should have output from the code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver CompressedOopsTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class CompressedOopsTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[gc,heap,coops] Heap address"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[gc,heap,coops]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=off", + InnerClass.class.getName()); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + "-XX:-PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Compressed Oops (gc+heap+coops) test"); + } + } +} From 0d3e7977aebcb1eb717735cb5faf0903c728fdd7 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 7 Apr 2016 16:37:35 -0400 Subject: [PATCH 047/113] 8151939: VM_Version_init() print buffer is too small Increase buffer size, use logging to print out version and os information Reviewed-by: kvn, rprotacio, mockner --- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 41 +++++---- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 46 +++++----- hotspot/src/os/aix/vm/os_aix.cpp | 6 +- hotspot/src/os/bsd/vm/os_bsd.cpp | 24 +----- hotspot/src/os/linux/vm/os_linux.cpp | 32 ++----- hotspot/src/os/solaris/vm/os_solaris.cpp | 40 +++------ hotspot/src/os/windows/vm/os_windows.cpp | 86 +++++-------------- hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp | 6 +- hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp | 20 ++--- .../src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp | 8 +- .../linux_aarch64/vm/os_linux_aarch64.cpp | 8 +- .../src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp | 6 +- .../os_cpu/linux_sparc/vm/os_linux_sparc.cpp | 8 +- .../linux_sparc/vm/vm_version_linux_sparc.cpp | 6 +- .../src/os_cpu/linux_x86/vm/os_linux_x86.cpp | 30 ++----- .../os_cpu/linux_zero/vm/os_linux_zero.cpp | 6 +- .../solaris_sparc/vm/os_solaris_sparc.cpp | 9 +- .../vm/vm_version_solaris_sparc.cpp | 20 ++--- .../os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 21 ++--- hotspot/src/share/vm/logging/log.cpp | 8 +- hotspot/src/share/vm/runtime/vm_version.cpp | 11 +-- .../runtime/logging/OsCpuLoggingTest.java | 64 ++++++++++++++ 22 files changed, 206 insertions(+), 300 deletions(-) create mode 100644 hotspot/test/runtime/logging/OsCpuLoggingTest.java diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 34041ed9943..93c8d40891e 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -368,36 +369,38 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } - if (PrintMiscellaneous && Verbose) { - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); - tty->print("Allocation"); + if (log_is_enabled(Info, os, cpu)) { + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0) { - tty->print_cr(": no prefetching"); + log->print(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCH"); + log->print("PREFETCH"); } else if (AllocatePrefetchInstr == 1) { - tty->print("BIS"); + log->print("BIS"); } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } } @@ -408,7 +411,7 @@ void VM_Version::print_features() { int VM_Version::determine_features() { if (UseV8InstrsOnly) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-V8"); } + log_info(os, cpu)("Version is Forced-V8"); return generic_v8_m; } @@ -416,7 +419,7 @@ int VM_Version::determine_features() { if (features == unknown_m) { features = generic_v9_m; - warning("Cannot recognize SPARC version. Default to V9"); + log_info(os)("Cannot recognize SPARC version. Default to V9"); } assert(is_T_family(features) == is_niagara(features), "Niagara should be T series"); @@ -424,12 +427,12 @@ int VM_Version::determine_features() { if (is_T_family(features)) { // Happy to accomodate... } else { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Niagara"); } + log_info(os, cpu)("Version is Forced-Niagara"); features |= T_family_m; } } else { if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Not-Niagara"); } + log_info(os, cpu)("Version is Forced-Not-Niagara"); features &= ~(T_family_m | T1_model_m); } else { // Happy to accomodate... diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 94c7e156d7e..6d871ce92de 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -1223,59 +1224,60 @@ void VM_Version::get_processor_features() { } #ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("Logical CPUs per core: %u", + if (log_is_enabled(Info, os, cpu)) { + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("Logical CPUs per core: %u", logical_processors_per_package()); - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print("UseSSE=%d", (int) UseSSE); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print("UseSSE=%d", (int) UseSSE); if (UseAVX > 0) { - tty->print(" UseAVX=%d", (int) UseAVX); + log->print(" UseAVX=%d", (int) UseAVX); } if (UseAES) { - tty->print(" UseAES=1"); + log->print(" UseAES=1"); } #ifdef COMPILER2 if (MaxVectorSize > 0) { - tty->print(" MaxVectorSize=%d", (int) MaxVectorSize); + log->print(" MaxVectorSize=%d", (int) MaxVectorSize); } #endif - tty->cr(); - tty->print("Allocation"); + log->cr(); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { - tty->print_cr(": no prefetching"); + log->print_cr(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (UseSSE == 0 && supports_3dnow_prefetch()) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } else if (UseSSE >= 1) { if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCHNTA"); + log->print("PREFETCHNTA"); } else if (AllocatePrefetchInstr == 1) { - tty->print("PREFETCHT0"); + log->print("PREFETCHT0"); } else if (AllocatePrefetchInstr == 2) { - tty->print("PREFETCHT2"); + log->print("PREFETCHT2"); } else if (AllocatePrefetchInstr == 3) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } #endif // !PRODUCT diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 31002c5bd60..22e016b65f2 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -3612,14 +3612,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 getrlimit failed"); + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 setrlimit failed"); + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 9cf4f74d2cf..ce3f6e005fd 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3459,25 +3459,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -3519,9 +3507,7 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; @@ -3534,9 +3520,7 @@ jint os::init_2(void) { status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d8811d46528..228ac835ffb 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2163,7 +2163,7 @@ static bool print_model_name_and_flags(outputStream* st, char* buf, size_t bufle bool model_name_printed = false; if (strstr(buf, "model name") != NULL) { if (!model_name_printed) { - st->print_raw("\nCPU Model and flags from /proc/cpuinfo:\n"); + st->print_raw("CPU Model and flags from /proc/cpuinfo:\n"); st->print_raw(buf); model_name_printed = true; } else { @@ -4671,25 +4671,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -4732,10 +4720,8 @@ jint os::init_2(void) { #endif Linux::libpthread_init(); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[HotSpot is running with %s, %s]\n", - Linux::glibc_version(), Linux::libpthread_version()); - } + log_info(os)("HotSpot is running with %s, %s", + Linux::glibc_version(), Linux::libpthread_version()); if (UseNUMA) { if (!Linux::libnuma_init()) { @@ -4776,16 +4762,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index d64b56a3a5a..68f4a58c30a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2754,13 +2754,13 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { pd_unmap_memory(addr, bytes); } - if (PrintMiscellaneous && Verbose) { + if (log_is_enabled(Warning, os)) { char buf[256]; buf[0] = '\0'; if (addr == NULL) { jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err)); } - warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " + log_info(os)("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT "%s", bytes, requested_addr, addr, buf); } @@ -2790,9 +2790,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { assert(i > 0, "gap adjustment code problem"); have_adjusted_gap = true; // adjust the gap only once, just in case gap = actual_gap; - if (PrintMiscellaneous && Verbose) { - warning("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); - } + log_info(os)("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); unmap_memory(base[i], bytes); unmap_memory(base[i-1], size[i-1]); i-=2; @@ -2824,8 +2822,8 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { } else { size_t bottom_overlap = base[i] + bytes - requested_addr; if (bottom_overlap >= 0 && bottom_overlap < bytes) { - if (PrintMiscellaneous && Verbose && bottom_overlap == 0) { - warning("attempt_reserve_memory_at: possible alignment bug"); + if (bottom_overlap == 0) { + log_info(os)("attempt_reserve_memory_at: possible alignment bug"); } unmap_memory(requested_addr, bottom_overlap); size[i] = bytes - bottom_overlap; @@ -4355,8 +4353,8 @@ static pset_getloadavg_type pset_getloadavg_ptr = NULL; void init_pset_getloadavg_ptr(void) { pset_getloadavg_ptr = (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg"); - if (PrintMiscellaneous && Verbose && pset_getloadavg_ptr == NULL) { - warning("pset_getloadavg function not found"); + if (pset_getloadavg_ptr == NULL) { + log_warning(os)("pset_getloadavg function not found"); } } @@ -4439,25 +4437,13 @@ jint os::init_2(void) { } os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)Solaris::mmap_chunk(NULL, page_size, MAP_PRIVATE, PROT_READ | PROT_WRITE); guarantee(mem_serialize_page != NULL, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Check minimum allowable stack size for thread creation and to initialize @@ -4537,16 +4523,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index f85eb0f273c..53e4528c0cc 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2436,14 +2436,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s", addr, - page_start, (res ? "success" : os::strerror(errno))); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s", p2i(addr), + p2i(page_start), (res ? "success" : os::strerror(errno))); // Set last_addr so if we fault again at the same address, we don't // end up in an endless loop. @@ -2896,12 +2892,12 @@ static bool numa_interleaving_init() { NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity); if (numa_node_list_holder.build()) { - if (PrintMiscellaneous && Verbose) { - tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); + if (log_is_enabled(Debug, os, cpu)) { + Log(os, cpu) log; + log.debug("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); for (int i = 0; i < numa_node_list_holder.get_count(); i++) { - tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); + log.debug(" %d ", numa_node_list_holder.get_node_list_entry(i)); } - tty->print("\n"); } success = true; } else { @@ -4119,13 +4115,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); @@ -4135,13 +4125,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Setup Windows Exceptions @@ -4769,10 +4753,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFile() failed: GetLastError->%ld.", GetLastError()); return NULL; } @@ -4790,10 +4771,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*) VirtualAlloc(addr, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualAlloc() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualAlloc() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4807,10 +4785,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, // number of bytes were read before returning. bool res = ReadFile(hFile, base, (DWORD)bytes, &bytes_read, &overlapped) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("ReadFile() failed: GetLastError->%ld.", err); - } + log_info(os)("ReadFile() failed: GetLastError->%ld.", GetLastError()); release_memory(base, bytes); CloseHandle(hFile); return NULL; @@ -4819,10 +4794,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL /* file_name */); if (hMap == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFileMapping() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4831,20 +4803,14 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*)MapViewOfFileEx(hMap, access, 0, (DWORD)file_offset, (DWORD)bytes, addr); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("MapViewOfFileEx() failed: GetLastError->%ld.", err); - } + log_info(os)("MapViewOfFileEx() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hMap); CloseHandle(hFile); return NULL; } if (CloseHandle(hMap) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hMap) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hMap) failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return base; } @@ -4856,10 +4822,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, bool res = VirtualProtect(base, bytes, exec_access, &old_protect) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualProtect() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualProtect() failed: GetLastError->%ld.", GetLastError()); // Don't consider this a hard error, on IA32 even if the // VirtualProtect fails, we should still be able to execute CloseHandle(hFile); @@ -4868,10 +4831,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, } if (CloseHandle(hFile) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hFile) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hFile) failed: GetLastError->%ld.", GetLastError()); return base; } @@ -4904,10 +4864,7 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, bool os::pd_unmap_memory(char* addr, size_t bytes) { MEMORY_BASIC_INFORMATION mem_info; if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualQuery() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualQuery() failed: GetLastError->%ld.", GetLastError()); return false; } @@ -4924,10 +4881,7 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) { BOOL result = UnmapViewOfFile(addr); if (result == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("UnmapViewOfFile() failed: GetLastError->%ld.", err); - } + log_info(os)("UnmapViewOfFile() failed: GetLastError->%ld.", GetLastError()); return false; } return true; diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index f109a111047..537595f95ad 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -184,9 +184,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec if (os::Aix::chained_handler(sig, info, ucVoid)) { return 1; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return 1; } } diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index f8e7dc509b9..73acdebfb47 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -469,11 +469,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -728,14 +724,10 @@ JVM_handle_bsd_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp index c3801dfab64..72d57858e09 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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. * @@ -159,11 +159,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp index 4e47e27628f..2a354fbb72c 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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. * @@ -270,11 +270,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index b7318c22c08..117bf1067f3 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -198,9 +198,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 30b321dc228..44a5a7df1f9 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,11 +561,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp index f9c596e4d79..c6bb5033db6 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,12 +66,12 @@ int VM_Version::platform_features(int features) { features = generic_v9_m; if (detect_niagara()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on Niagara"); } + log_info(os, cpu)("Detected Linux on Niagara"); features = niagara1_m | T_family_m; } if (detect_M_family()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on M family"); } + log_info(os, cpu)("Detected Linux on M family"); features = sun4v_m | generic_v9_m | M_family_m | T_family_m; } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index ec6ba97235a..0eb7a9e511f 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,11 +287,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -542,14 +538,10 @@ JVM_handle_linux_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end @@ -645,12 +637,8 @@ bool os::supports_sse() { int major = strtol(uts.release,&minor_string,10); int minor = strtol(minor_string+1,NULL,10); bool result = (major > 2 || (major==2 && minor >= 4)); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("OS version is %d.%d, which %s support SSE/SSE2\n", + log_info(os)("OS version is %d.%d, which %s support SSE/SSE2", major,minor, result ? "DOES" : "does NOT"); - } -#endif return result; #endif // AMD64 } @@ -939,9 +927,7 @@ void os::workaround_expand_exec_shield_cs_limit() { MemTracker::record_virtual_memory_type((address)codebuf, mtInternal); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[CS limit NX emulation work-around, exec code at: %p]", codebuf); - } + log_info(os)("[CS limit NX emulation work-around, exec code at: %p]", codebuf); // Some code to exec: the 'ret' instruction codebuf[0] = 0xC3; diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index b1e93a82dc8..abd52961976 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -154,11 +154,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index 5fd0e0a78af..da39ee79790 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,12 +338,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 837607e6781..def37cd0b63 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "runtime/os.hpp" @@ -361,15 +362,10 @@ int VM_Version::platform_features(int features) { assert(avn <= 2, "should return two or less av's"); uint_t av = avs[0]; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("getisax(2) returned: " PTR32_FORMAT, av); - if (avn > 1) { - tty->print(", " PTR32_FORMAT, avs[1]); - } - tty->cr(); + log_info(os, cpu)("getisax(2) returned: " PTR32_FORMAT, av); + if (avn > 1) { + log_info(os, cpu)(" " PTR32_FORMAT, avs[1]); } -#endif if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; if (av & AV_SPARC_DIV32) features |= hardware_div32_m; @@ -464,11 +460,7 @@ int VM_Version::platform_features(int features) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); has_implementation = true; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("cpu_info.implementation: %s", implementation); - } -#endif + log_info(os, cpu)("cpu_info.implementation: %s", implementation); features |= parse_features(implementation); break; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 79a7f19a281..0784f3f25f7 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -403,12 +403,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -640,14 +635,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 3d676219d89..6c6566b386e 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -377,7 +377,7 @@ void Test_loghandle_on() { assert(log_handle.is_debug(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.debug("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -408,7 +408,7 @@ void Test_loghandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.debug("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. @@ -440,7 +440,7 @@ static void Test_logtargethandle_on() { assert(log_handle.is_enabled(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.print("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -471,7 +471,7 @@ static void Test_logtargethandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.print("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index cf2bf5a4644..c36098a31f7 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" @@ -274,12 +275,12 @@ unsigned int Abstract_VM_Version::jvm_version() { void VM_Version_init() { VM_Version::initialize(); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - char buf[512]; - os::print_cpu_info(tty, buf, sizeof(buf)); + if (log_is_enabled(Info, os, cpu)) { + char buf[1024]; + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + os::print_cpu_info(log, buf, sizeof(buf)); } -#endif } unsigned int Abstract_VM_Version::nof_parallel_worker_threads( diff --git a/hotspot/test/runtime/logging/OsCpuLoggingTest.java b/hotspot/test/runtime/logging/OsCpuLoggingTest.java new file mode 100644 index 00000000000..ab23e194f8f --- /dev/null +++ b/hotspot/test/runtime/logging/OsCpuLoggingTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8151939 + * @summary os+cpu output should contain some os,cpu information + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver OsCpuLoggingTest + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.*; + +public class OsCpuLoggingTest { + + static void analyzeOutputForOsLog(OutputAnalyzer output) throws Exception { + // Aix has it's own logging + if (!Platform.isAix()) { + output.shouldContain("SafePoint Polling address"); + } + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForOsCpuLog(OutputAnalyzer output) throws Exception { + output.shouldContain("CPU:total"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+cpu", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsCpuLog(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsLog(output); + } +} From 10c7cac93e527336865caa6398572766487a22d4 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Thu, 7 Apr 2016 15:33:25 -0700 Subject: [PATCH 048/113] 8152180: SIGFPE in CMSCollector::preclean with big CMSScheduleRemarkSamplingRatio Rephrased the calculation routine to avoid an overflow for CMSScheduleRemarkSamplingRatio Reviewed-by: jwilhelm, drwhite --- hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 42fd21dc65d..1e7a4991dd3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -3598,7 +3598,7 @@ void CMSCollector::preclean() { size_t capacity = get_eden_capacity(); // Don't start sampling unless we will get sufficiently // many samples. - if (used < (capacity/(CMSScheduleRemarkSamplingRatio * 100) + if (used < (((capacity / CMSScheduleRemarkSamplingRatio) / 100) * CMSScheduleRemarkEdenPenetration)) { _start_sampling = true; } else { From 25f35cda7d82c3c1fd3d0b4470806e48cd6dca99 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Thu, 7 Apr 2016 15:34:21 -0700 Subject: [PATCH 049/113] 8152182: Possible overflow in initialzation of _rescan_task_size and _marking_task_size Add constraints for CMSRescanMultiple and CMSConcMarkMultiple flags Reviewed-by: jwilhelm, jmasa --- .../vm/gc/cms/compactibleFreeListSpace.cpp | 5 +++ .../vm/gc/cms/compactibleFreeListSpace.hpp | 2 + .../runtime/commandLineFlagConstraintsGC.cpp | 45 +++++++++++++++++++ .../runtime/commandLineFlagConstraintsGC.hpp | 2 + hotspot/src/share/vm/runtime/globals.hpp | 8 +++- 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index ac9d84e5d12..c048f08b4a1 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -2836,6 +2836,11 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n par_get_chunk_of_blocks_dictionary(word_sz, n, fl); } +const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { + const size_t ergo_max = _old_gen->reserved().word_size() / (CardTableModRefBS::card_size_in_words * BitsPerWord); + return ergo_max; +} + // Set up the space's par_seq_tasks structure for work claiming // for parallel rescan. See CMSParRemarkTask where this is currently used. // XXX Need to suitably abstract and generalize this and the next diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index eeaa07ce280..92a2764afd0 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -345,6 +345,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Support for parallelization of rescan and marking. const size_t rescan_task_size() const { return _rescan_task_size; } const size_t marking_task_size() const { return _marking_task_size; } + // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. + const size_t max_flag_size_for_task_size() const; SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } void initialize_sequential_subtasks_for_rescan(int n_threads); void initialize_sequential_subtasks_for_marking(int n_threads, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp index 4390644d708..5dce24113af 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp @@ -457,6 +457,51 @@ Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) { } } +static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) { +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen(); + const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size(); + if (value > ergo_max) { + CommandLineError::print(verbose, + "%s (" SIZE_FORMAT ") must be " + "less than or equal to ergonomic maximum (" SIZE_FORMAT ") " + "which is based on the maximum size of the old generation of the Java heap\n", + name, value, ergo_max); + return Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return Flag::SUCCESS; +} + +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) { + Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose); + +#if INCLUDE_ALL_GCS + if (status == Flag::SUCCESS && UseConcMarkSweepGC) { + // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size() + // to be aligned to CardTableModRefBS::card_size * BitsPerWord. + // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize' + // because rescan_task_size() is CardTableModRefBS::card_size / HeapWordSize * BitsPerWord. + if (value % HeapWordSize != 0) { + CommandLineError::print(verbose, + "CMSRescanMultiple (" SIZE_FORMAT ") must be " + "a multiple of " SIZE_FORMAT "\n", + value, HeapWordSize); + status = Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return status; +} + +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) { + return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose); +} + Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp index ee8bf3f668b..9470a1c4ec4 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp @@ -60,6 +60,8 @@ Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose); Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose); Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose); Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose); +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose); +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose); Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose); Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose); Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index be97e61c9b0..49e24ed385a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1806,13 +1806,17 @@ public: "enough work per iteration") \ range(0, max_intx) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSRescanMultiple, 32, \ "Size (in cards) of CMS parallel rescan task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSConcMarkMultiple, 32, \ "Size (in cards) of CMS concurrent MT marking task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit) \ \ product(bool, CMSAbortSemantics, false, \ "Whether abort-on-overflow semantics is implemented") \ From 2d2abce433c95b7edaf3e77b1a337650007750c1 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Fri, 8 Apr 2016 12:26:29 -0700 Subject: [PATCH 050/113] 8153123: Streamline StackWalker code Reviewed-by: coleenp, dfuchs, mchung, redestad --- hotspot/make/share/makefiles/mapfile-vers | 3 +- hotspot/makefiles/symbols/symbols-unix | 3 +- .../src/share/vm/classfile/javaClasses.cpp | 110 +++------------- .../src/share/vm/classfile/javaClasses.hpp | 22 +--- hotspot/src/share/vm/prims/jvm.cpp | 62 +++------ hotspot/src/share/vm/prims/jvm.h | 11 +- hotspot/src/share/vm/prims/stackwalk.cpp | 120 +++++++----------- hotspot/src/share/vm/prims/stackwalk.hpp | 19 ++- hotspot/src/share/vm/runtime/globals.hpp | 3 - 9 files changed, 91 insertions(+), 262 deletions(-) diff --git a/hotspot/make/share/makefiles/mapfile-vers b/hotspot/make/share/makefiles/mapfile-vers index a937f93b84c..f7d08e50b98 100644 --- a/hotspot/make/share/makefiles/mapfile-vers +++ b/hotspot/make/share/makefiles/mapfile-vers @@ -41,7 +41,6 @@ JVM_DumpAllStacks; JVM_DumpThreads; JVM_FillInStackTrace; - JVM_FillStackFrames; JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromBootLoader; @@ -157,13 +156,13 @@ JVM_SetClassSigners; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetMethodInfo; JVM_SetThreadPriority; JVM_Sleep; JVM_StartThread; JVM_StopThread; JVM_SuspendThread; JVM_SupportsCX8; + JVM_ToStackTraceElement; JVM_TotalMemory; JVM_UnloadLibrary; JVM_Yield; diff --git a/hotspot/makefiles/symbols/symbols-unix b/hotspot/makefiles/symbols/symbols-unix index 5d876710e65..406d6f99db3 100644 --- a/hotspot/makefiles/symbols/symbols-unix +++ b/hotspot/makefiles/symbols/symbols-unix @@ -58,7 +58,6 @@ JVM_DoPrivileged JVM_DumpAllStacks JVM_DumpThreads JVM_FillInStackTrace -JVM_FillStackFrames JVM_FindClassFromCaller JVM_FindClassFromClass JVM_FindLibraryEntry @@ -169,7 +168,6 @@ JVM_ReleaseUTF JVM_ResumeThread JVM_SetArrayElement JVM_SetClassSigners -JVM_SetMethodInfo JVM_SetNativeThreadName JVM_SetPrimitiveArrayElement JVM_SetThreadPriority @@ -178,6 +176,7 @@ JVM_StartThread JVM_StopThread JVM_SupportsCX8 JVM_SuspendThread +JVM_ToStackTraceElement JVM_TotalMemory JVM_UnloadLibrary JVM_Yield diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index f61e466e8f2..5365e1df8d6 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2187,43 +2187,19 @@ void java_lang_StackTraceElement::fill_in(Handle element, } Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { - if (MemberNameInStackFrame) { - Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); - Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); - // we should expand MemberName::name when Throwable uses StackTrace - // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); - return method; - } else { - short mid = stackFrame->short_field(_mid_offset); - short version = stackFrame->short_field(_version_offset); - return holder->method_with_orig_idnum(mid, version); - } -} - -Symbol* java_lang_StackFrameInfo::get_file_name(Handle stackFrame, InstanceKlass* holder) { - if (MemberNameInStackFrame) { - return holder->source_file_name(); - } else { - short version = stackFrame->short_field(_version_offset); - return Backtrace::get_source_file_name(holder, version); - } + Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); + Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); + // we should expand MemberName::name when Throwable uses StackTrace + // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); + return method; } void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) { // set Method* or mid/cpref - if (MemberNameInStackFrame) { - oop mname = stackFrame->obj_field(_memberName_offset); - InstanceKlass* ik = method->method_holder(); - CallInfo info(method(), ik); - MethodHandles::init_method_MemberName(mname, info); - } else { - int mid = method->orig_method_idnum(); - int cpref = method->name_index(); - assert((jushort)mid == mid, "mid should be short"); - assert((jushort)cpref == cpref, "cpref should be short"); - java_lang_StackFrameInfo::set_mid(stackFrame(), (short)mid); - java_lang_StackFrameInfo::set_cpref(stackFrame(), (short)cpref); - } + oop mname = stackFrame->obj_field(_memberName_offset); + InstanceKlass* ik = method->method_holder(); + CallInfo info(method(), ik); + MethodHandles::init_method_MemberName(mname, info); // set bci java_lang_StackFrameInfo::set_bci(stackFrame(), bci); // method may be redefined; store the version @@ -2232,52 +2208,23 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho java_lang_StackFrameInfo::set_version(stackFrame(), (short)version); } -void java_lang_StackFrameInfo::fill_methodInfo(Handle stackFrame, TRAPS) { +void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) { ResourceMark rm(THREAD); - oop k = stackFrame->obj_field(_declaringClass_offset); - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k)); + Handle k (THREAD, stackFrame->obj_field(_declaringClass_offset)); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k())); Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); - int bci = stackFrame->int_field(_bci_offset); - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : NULL; - if (MemberNameInStackFrame) { - assert(sym != NULL, "MemberName must have method name"); - } else { - // The method can be NULL if the requested class version is gone - if (sym == NULL) { - short cpref = stackFrame->short_field(_cpref_offset); - sym = holder->constants()->symbol_at(cpref); - } - } - - // set method name - oop methodname = StringTable::intern(sym, CHECK); - java_lang_StackFrameInfo::set_methodName(stackFrame(), methodname); - - // set file name and line number - Symbol* source = get_file_name(stackFrame, holder); - if (source != NULL) { - oop filename = StringTable::intern(source, CHECK); - java_lang_StackFrameInfo::set_fileName(stackFrame(), filename); - } - - // if the method has been redefined, the bci is no longer applicable short version = stackFrame->short_field(_version_offset); - if (version_matches(method, version)) { - int line_number = Backtrace::get_line_number(method, bci); - java_lang_StackFrameInfo::set_lineNumber(stackFrame(), line_number); - } + short bci = stackFrame->short_field(_bci_offset); + int cpref = method->name_index(); + java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK); } void java_lang_StackFrameInfo::compute_offsets() { Klass* k = SystemDictionary::StackFrameInfo_klass(); compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature()); compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature()); - compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::int_signature()); - compute_offset(_methodName_offset, k, vmSymbols::methodName_name(), vmSymbols::string_signature()); - compute_offset(_fileName_offset, k, vmSymbols::fileName_name(), vmSymbols::string_signature()); - compute_offset(_lineNumber_offset, k, vmSymbols::lineNumber_name(), vmSymbols::int_signature()); + compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature()); STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } @@ -3690,12 +3637,7 @@ int java_lang_StackTraceElement::moduleVersion_offset; int java_lang_StackFrameInfo::_declaringClass_offset; int java_lang_StackFrameInfo::_memberName_offset; int java_lang_StackFrameInfo::_bci_offset; -int java_lang_StackFrameInfo::_methodName_offset; -int java_lang_StackFrameInfo::_fileName_offset; -int java_lang_StackFrameInfo::_lineNumber_offset; -int java_lang_StackFrameInfo::_mid_offset; int java_lang_StackFrameInfo::_version_offset; -int java_lang_StackFrameInfo::_cpref_offset; int java_lang_LiveStackFrameInfo::_monitors_offset; int java_lang_LiveStackFrameInfo::_locals_offset; int java_lang_LiveStackFrameInfo::_operands_offset; @@ -3741,34 +3683,14 @@ void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) { element->obj_field_put(_declaringClass_offset, value); } -void java_lang_StackFrameInfo::set_mid(oop element, short value) { - element->short_field_put(_mid_offset, value); -} - void java_lang_StackFrameInfo::set_version(oop element, short value) { element->short_field_put(_version_offset, value); } -void java_lang_StackFrameInfo::set_cpref(oop element, short value) { - element->short_field_put(_cpref_offset, value); -} - void java_lang_StackFrameInfo::set_bci(oop element, int value) { element->int_field_put(_bci_offset, value); } -void java_lang_StackFrameInfo::set_fileName(oop element, oop value) { - element->obj_field_put(_fileName_offset, value); -} - -void java_lang_StackFrameInfo::set_methodName(oop element, oop value) { - element->obj_field_put(_methodName_offset, value); -} - -void java_lang_StackFrameInfo::set_lineNumber(oop element, int value) { - element->int_field_put(_lineNumber_offset, value); -} - void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) { element->obj_field_put(_monitors_offset, value); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 560bab7d5f8..4ff32acd6c1 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1364,25 +1364,16 @@ class Backtrace: AllStatic { // Interface to java.lang.StackFrameInfo objects #define STACKFRAMEINFO_INJECTED_FIELDS(macro) \ - macro(java_lang_StackFrameInfo, mid, short_signature, false) \ - macro(java_lang_StackFrameInfo, version, short_signature, false) \ - macro(java_lang_StackFrameInfo, cpref, short_signature, false) + macro(java_lang_StackFrameInfo, version, short_signature, false) class java_lang_StackFrameInfo: AllStatic { private: static int _declaringClass_offset; static int _memberName_offset; static int _bci_offset; - static int _methodName_offset; - static int _fileName_offset; - static int _lineNumber_offset; - - static int _mid_offset; static int _version_offset; - static int _cpref_offset; static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS); - static Symbol* get_file_name(Handle stackFrame, InstanceKlass* holder); public: // Setters @@ -1390,19 +1381,12 @@ public: static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci); static void set_bci(oop info, int value); - // set method info in an instance of StackFrameInfo - static void fill_methodInfo(Handle info, TRAPS); - static void set_methodName(oop info, oop value); - static void set_fileName(oop info, oop value); - static void set_lineNumber(oop info, int value); - - // these injected fields are only used if -XX:-MemberNameInStackFrame set - static void set_mid(oop info, short value); static void set_version(oop info, short value); - static void set_cpref(oop info, short value); static void compute_offsets(); + static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS); + // Debugging friend class JavaClasses; }; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7665065c9df..2bf88e40b22 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -534,7 +534,6 @@ JVM_END JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_CallStackWalk"); JavaThread* jt = (JavaThread*) THREAD; @@ -543,78 +542,51 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index + frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL); } Handle result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, - start_index, classes_array_h, - frames_array_h, CHECK_NULL); + start_index, frames_array_h, CHECK_NULL); return JNIHandles::make_local(env, result()); JVM_END JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_MoreStackWalk"); JavaThread* jt = (JavaThread*) THREAD; - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index+frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers"); } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count, - start_index, classes_array_h, - frames_array_h, THREAD); + start_index, frames_array_h, THREAD); JVM_END -JVM_ENTRY(void, JVM_FillStackFrames(JNIEnv *env, jclass stackStream, - jint start_index, - jobjectArray frames, - jint from_index, jint to_index)) - JVMWrapper("JVM_FillStackFrames"); - if (TraceStackWalk) { - tty->print("JVM_FillStackFrames() start_index=%d from_index=%d to_index=%d\n", - start_index, from_index, to_index); - } - - JavaThread* jt = (JavaThread*) THREAD; - - objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); - objArrayHandle frames_array_h(THREAD, fa); - - if (frames_array_h->length() < to_index) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array length not matched"); - } - - for (int i = from_index; i < to_index; i++) { - Handle stackFrame(THREAD, frames_array_h->obj_at(i)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, CHECK); - } -JVM_END - -JVM_ENTRY(void, JVM_SetMethodInfo(JNIEnv *env, jobject frame)) - JVMWrapper("JVM_SetMethodInfo"); - Handle stackFrame(THREAD, JNIHandles::resolve(frame)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, THREAD); +JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack)) + JVMWrapper("JVM_ToStackTraceElement"); + Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame)); + Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack)); + java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); JVM_END // java.lang.Object /////////////////////////////////////////////// diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index dafc3955101..5a055995d1c 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -209,7 +209,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements) */ enum { JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2, - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10, JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20, JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100 }; @@ -217,23 +216,15 @@ enum { JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT jint JNICALL JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT void JNICALL -JVM_FillStackFrames(JNIEnv* env, jclass cls, - jint start_index, - jobjectArray frames, - jint from_index, jint toIndex); - -JNIEXPORT void JNICALL -JVM_SetMethodInfo(JNIEnv* env, jobject frame); +JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); /* * java.lang.Thread diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index 3e292641a79..d772620dcf5 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -37,22 +37,22 @@ #include "utilities/globalDefinitions.hpp" // setup and cleanup actions -void StackWalkAnchor::setup_magic_on_entry(objArrayHandle classes_array) { - classes_array->obj_at_put(magic_pos, _thread->threadObj()); +void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) { + frames_array->obj_at_put(magic_pos, _thread->threadObj()); _anchor = address_value(); - assert(check_magic(classes_array), "invalid magic"); + assert(check_magic(frames_array), "invalid magic"); } -bool StackWalkAnchor::check_magic(objArrayHandle classes_array) { - oop m1 = classes_array->obj_at(magic_pos); +bool StackWalkAnchor::check_magic(objArrayHandle frames_array) { + oop m1 = frames_array->obj_at(magic_pos); jlong m2 = _anchor; if (m1 == _thread->threadObj() && m2 == address_value()) return true; return false; } -bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { - bool ok = check_magic(classes_array); - classes_array->obj_at_put(magic_pos, NULL); +bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) { + bool ok = check_magic(frames_array); + frames_array->obj_at_put(magic_pos, NULL); _anchor = 0L; return ok; } @@ -62,18 +62,18 @@ bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { // Parameters: // thread Current Java thread. // magic Magic value used for each stack walking -// classes_array User-supplied buffers. The 0th element is reserved +// frames_array User-supplied buffers. The 0th element is reserved // to this StackWalkAnchor to use // StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, - objArrayHandle classes_array) + objArrayHandle frames_array) { assert(thread != NULL && thread->is_Java_thread(), ""); - oop m1 = classes_array->obj_at(magic_pos); + oop m1 = frames_array->obj_at(magic_pos); if (m1 != thread->threadObj()) return NULL; if (magic == 0L) return NULL; StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic; - if (!anchor->is_valid_in(thread, classes_array)) return NULL; + if (!anchor->is_valid_in(thread, frames_array)) return NULL; return anchor; } @@ -88,24 +88,24 @@ StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, // vfst vFrameStream. // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. -// frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames_array Buffer to store Class or StackFrame in, starting at start_index. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS) { if (TraceStackWalk) { tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d", - max_nframes, start_index, classes_array->length()); + max_nframes, start_index, frames_array->length()); } assert(max_nframes > 0, "invalid max_nframes"); - assert(start_index + max_nframes <= classes_array->length(), "oob"); + assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !vfst.at_end(); vfst.next()) { @@ -129,14 +129,18 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, tty->print_cr(" bci=%d", bci); } - classes_array->obj_at_put(index, method->method_holder()->java_mirror()); // fill in StackFrameInfo and initialize MemberName if (live_frame_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get live frame"); Handle stackFrame(frames_array->obj_at(index)); fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0); } else if (need_method_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get stack frame"); Handle stackFrame(frames_array->obj_at(index)); fill_stackframe(stackFrame, method, bci); + } else { + assert (use_frames_array(mode) == false, "Bad mode for get caller class"); + frames_array->obj_at_put(index, method->method_holder()->java_mirror()); } if (++frames_decoded >= max_nframes) break; } @@ -279,15 +283,15 @@ void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& meth // skip_frames Number of frames to be skipped. // frame_count Number of frames to be traversed. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // // Returns Object returned from AbstractStackWalker::doStackWalk call. // oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; @@ -296,10 +300,8 @@ oop StackWalk::walk(Handle stackStream, jlong mode, mode, skip_frames, frame_count); } - if (need_method_info(mode)) { - if (frames_array.is_null()) { - THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); - } + if (frames_array.is_null()) { + THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); @@ -313,48 +315,17 @@ oop StackWalk::walk(Handle stackStream, jlong mode, vframeStream& vfst = anchor.vframe_stream(); { - // Skip all methods from AbstractStackWalker and StackWalk (enclosing method) - if (!fill_in_stacktrace(mode)) { - while (!vfst.at_end()) { - InstanceKlass* ik = vfst.method()->method_holder(); - if (ik != stackWalker_klass && - ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { - break; - } - - if (TraceStackWalk) { - tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + while (!vfst.at_end()) { + InstanceKlass* ik = vfst.method()->method_holder(); + if (ik != stackWalker_klass && + ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { + break; } - } - // For exceptions, skip Throwable::fillInStackTrace and methods - // of the exception class and superclasses - if (fill_in_stacktrace(mode)) { - bool skip_to_fillInStackTrace = false; - bool skip_throwableInit_check = false; - while (!vfst.at_end() && !skip_throwableInit_check) { - InstanceKlass* ik = vfst.method()->method_holder(); - Method* method = vfst.method(); - if (!skip_to_fillInStackTrace) { - if (ik == SystemDictionary::Throwable_klass() && - method->name() == vmSymbols::fillInStackTrace_name()) { - // this frame will be skipped - skip_to_fillInStackTrace = true; - } - } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) && - method->name() == vmSymbols::object_initializer_name())) { - // there are none or we've seen them all - either way stop checking - skip_throwableInit_check = true; - break; - } - - if (TraceStackWalk) { - tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + if (TraceStackWalk) { + tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); } + vfst.next(); } // stack frame has been traversed individually and resume stack walk @@ -372,7 +343,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode, int end_index = start_index; int numFrames = 0; if (!vfst.at_end()) { - numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + numFrames = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); @@ -392,12 +363,12 @@ oop StackWalk::walk(Handle stackStream, jlong mode, args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object - anchor.setup_magic_on_entry(classes_array); + anchor.setup_magic_on_entry(frames_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects - bool ok = anchor.cleanup_magic_on_exit(classes_array); + bool ok = anchor.cleanup_magic_on_exit(frames_array); // Throw pending exception if we must (void) (CHECK_NULL); @@ -419,31 +390,28 @@ oop StackWalk::walk(Handle stackStream, jlong mode, // magic Must be valid value to continue the stack walk // frame_count Number of frames to be decoded. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. // // Returns the end index of frame filled in the buffer. // jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; - StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array); + StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array); if (existing_anchor == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } - if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) { + if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L); } if (TraceStackWalk) { tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d", - frame_count, p2i(existing_anchor), start_index, classes_array->length()); + frame_count, p2i(existing_anchor), start_index, frames_array->length()); } int end_index = start_index; if (frame_count <= 0) { @@ -451,14 +419,14 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, } int count = frame_count + start_index; - assert (classes_array->length() >= count, "not enough space in buffers"); + assert (frames_array->length() >= count, "not enough space in buffers"); StackWalkAnchor& anchor = (*existing_anchor); vframeStream& vfst = anchor.vframe_stream(); if (!vfst.at_end()) { vfst.next(); // this was the last frame decoded in the previous batch if (!vfst.at_end()) { - int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + int n = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_0); if (n < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); diff --git a/hotspot/src/share/vm/prims/stackwalk.hpp b/hotspot/src/share/vm/prims/stackwalk.hpp index 1fa906815be..2eb41aeb711 100644 --- a/hotspot/src/share/vm/prims/stackwalk.hpp +++ b/hotspot/src/share/vm/prims/stackwalk.hpp @@ -45,12 +45,12 @@ public: vframeStream& vframe_stream() { return _vfst; } JavaThread* thread() { return _thread; } - void setup_magic_on_entry(objArrayHandle classes_array); - bool check_magic(objArrayHandle classes_array); - bool cleanup_magic_on_exit(objArrayHandle classes_array); + void setup_magic_on_entry(objArrayHandle frames_array); + bool check_magic(objArrayHandle frames_array); + bool cleanup_magic_on_exit(objArrayHandle frames_array); - bool is_valid_in(Thread* thread, objArrayHandle classes_array) { - return (_thread == thread && check_magic(classes_array)); + bool is_valid_in(Thread* thread, objArrayHandle frames_array) { + return (_thread == thread && check_magic(frames_array)); } jlong address_value() { @@ -64,7 +64,6 @@ class StackWalk : public AllStatic { private: static int fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS); @@ -82,20 +81,18 @@ private: static inline bool live_frame_info(int mode) { return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0; } - static inline bool fill_in_stacktrace(int mode) { - return (mode & JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE) != 0; - } public: + static inline bool use_frames_array(int mode) { + return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; + } static oop walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); static jint moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); }; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 49e24ed385a..044e26e3ccf 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2958,9 +2958,6 @@ public: develop(bool, TraceStackWalk, false, \ "Trace stack walking") \ \ - product(bool, MemberNameInStackFrame, true, \ - "Use MemberName in StackFrame") \ - \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ NOT_EMBEDDED(diagnostic(intx, GuaranteedSafepointInterval, 1000, \ From 28edd79d641a53032589868b3a6ee9441a7b8966 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Thu, 7 Apr 2016 22:03:04 -0700 Subject: [PATCH 051/113] 8145221: Use trampolines for i2i and i2c entries in Methods that are stored in CDS archive This optimization reduces the size of the RW region of the CDS archive. It also reduces the amount of pages in the RW region that are actually written into during runtime. Co-authored-by: Ioi Lam Co-authored-by: Goetz Lindenmaier Reviewed-by: dlong, iklam, jiangli --- .../cpu/aarch64/vm/sharedRuntime_aarch64.cpp | 10 +++ hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 12 +++ .../cpu/sparc/vm/metaspaceShared_sparc.cpp | 2 - .../src/cpu/sparc/vm/sharedRuntime_sparc.cpp | 10 +++ .../src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 8 ++ .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 8 ++ .../src/cpu/zero/vm/sharedRuntime_zero.cpp | 9 ++ .../src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp | 9 ++ .../linux_aarch64/vm/thread_linux_aarch64.cpp | 9 ++ .../linux_sparc/vm/thread_linux_sparc.cpp | 9 ++ .../os_cpu/linux_x86/vm/thread_linux_x86.cpp | 9 ++ .../solaris_sparc/vm/thread_solaris_sparc.cpp | 9 ++ .../solaris_x86/vm/thread_solaris_x86.cpp | 9 ++ .../windows_x86/vm/thread_windows_x86.cpp | 9 ++ .../vm/interpreter/abstractInterpreter.cpp | 33 ++++++- .../vm/interpreter/abstractInterpreter.hpp | 12 +++ .../templateInterpreterGenerator.cpp | 1 + hotspot/src/share/vm/memory/filemap.cpp | 10 +++ hotspot/src/share/vm/memory/filemap.hpp | 16 ++++ .../src/share/vm/memory/metaspaceShared.cpp | 30 ++++++- .../src/share/vm/memory/metaspaceShared.hpp | 25 ++++-- hotspot/src/share/vm/oops/constMethod.hpp | 30 +++++++ hotspot/src/share/vm/oops/method.cpp | 85 +++++++++++++------ hotspot/src/share/vm/oops/method.hpp | 29 +++++-- .../src/share/vm/runtime/sharedRuntime.cpp | 45 +++++++++- .../src/share/vm/runtime/sharedRuntime.hpp | 16 ++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 1 - 27 files changed, 408 insertions(+), 47 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index 0aeba4cb33c..760256da378 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -198,6 +198,16 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { bool SharedRuntime::is_wide_vector(int size) { return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ mov(rscratch1, destination); + __ br(rscratch1); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index 49df282945d..ee8685f4f0a 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -483,6 +483,18 @@ bool SharedRuntime::is_wide_vector(int size) { assert(size <= 8, "%d bytes vectors are not supported", size); return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return Assembler::load_const_size + 8; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + Register Rtemp = R12; + __ load_const(Rtemp, destination); + __ mtctr(Rtemp); + __ bctr(); +} + #ifdef COMPILER2 static int reg2slot(VMReg r) { return r->reg2stack() + SharedRuntime::out_preserve_stack_slots(); diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp index 28f606be3b0..cc0141c283e 100644 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp @@ -65,8 +65,6 @@ void MetaspaceShared::generate_vtable_methods(void** vtbl_list, *vtable = dummy_vtable; *md_top += vtable_bytes; - guarantee(*md_top <= md_end, "Insufficient space for vtables."); - // Get ready to generate dummy methods. CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index ab9fed0d5d1..6727c14d63b 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -324,6 +324,16 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 8; } +size_t SharedRuntime::trampoline_size() { + return 40; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ set((intptr_t)destination, G3_scratch); + __ JMP(G3_scratch, 0); + __ delayed()->nop(); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index abe9a369eaa..3763b058b8b 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -355,6 +355,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index a5c8f82e6ef..8fca552dd34 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -391,6 +391,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp index 3fbe12e94f9..0fb36b01b75 100644 --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp @@ -132,6 +132,15 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha return generate_empty_runtime_stub("resolve_blob"); } +size_t SharedRuntime::trampoline_size() { + ShouldNotCallThis(); + return 0; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + ShouldNotCallThis(); + return; +} int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, diff --git a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp index c4f991aa650..df36e6edbe1 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp index cd6f71efe2c..07206d873d7 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -66,6 +67,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #ifdef COMPILER2 diff --git a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp index dac85519a0c..c571507e675 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // we were running Java code when SIGPROF came in if (isInJava) { // If we have a last_Java_sp, then the SIGPROF signal caught us diff --git a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp index 55e5bbac4e2..3075dd19dd3 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -65,6 +66,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp index 9964114a787..ddbaa702063 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -77,6 +78,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); // we were running Java code when SIGPROF came in diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp index d41f3e7167f..48af49f7497 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -70,6 +71,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // If sp and fp are nonsense just leave them out if (!jt->on_local_stack((address)ret_sp)) { diff --git a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp index 08afec24834..ba5be5736cf 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -72,6 +73,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp index 96fb64403cd..3717ae061d9 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/interpreter.hpp" @@ -32,6 +33,7 @@ #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" #include "memory/allocation.inline.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" #include "oops/methodData.hpp" @@ -93,6 +95,7 @@ address AbstractInterpreter::_native_entry_begin = NU address AbstractInterpreter::_native_entry_end = NULL; address AbstractInterpreter::_slow_signature_handler; address AbstractInterpreter::_entry_table [AbstractInterpreter::number_of_method_entries]; +address AbstractInterpreter::_cds_entry_table [AbstractInterpreter::number_of_method_entries]; address AbstractInterpreter::_native_abi_to_tosca [AbstractInterpreter::number_of_result_handlers]; //------------------------------------------------------------------------------------------------------------------------ @@ -204,14 +207,41 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m) return zerolocals; } +#if INCLUDE_CDS + +address AbstractInterpreter::get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) { + const size_t trampoline_size = SharedRuntime::trampoline_size(); + address addr = MetaspaceShared::cds_i2i_entry_code_buffers((size_t)(AbstractInterpreter::number_of_method_entries) * trampoline_size); + addr += (size_t)(kind) * trampoline_size; + + return addr; +} + +void AbstractInterpreter::update_cds_entry_table(AbstractInterpreter::MethodKind kind) { + if (DumpSharedSpaces || UseSharedSpaces) { + address trampoline = get_trampoline_code_buffer(kind); + _cds_entry_table[kind] = trampoline; + + CodeBuffer buffer(trampoline, (int)(SharedRuntime::trampoline_size())); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, _entry_table[kind]); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } +} + +#endif void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kind, address entry) { assert(kind >= method_handle_invoke_FIRST && kind <= method_handle_invoke_LAST, "late initialization only for MH entry points"); assert(_entry_table[kind] == _entry_table[abstract], "previous value must be AME entry"); _entry_table[kind] = entry; -} + update_cds_entry_table(kind); +} // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). @@ -416,5 +446,6 @@ void AbstractInterpreter::initialize_method_handle_entries() { for (int i = method_handle_invoke_FIRST; i <= method_handle_invoke_LAST; i++) { MethodKind kind = (MethodKind) i; _entry_table[kind] = _entry_table[Interpreter::abstract]; + Interpreter::update_cds_entry_table(kind); } } diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 8be852bae60..db31ac83400 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -113,6 +113,7 @@ class AbstractInterpreter: AllStatic { // method entry points static address _entry_table[number_of_method_entries]; // entry points for a given method + static address _cds_entry_table[number_of_method_entries]; // entry points for methods in the CDS archive static address _native_abi_to_tosca[number_of_result_handlers]; // for native method result handlers static address _slow_signature_handler; // the native method generic (slow) signature handler @@ -132,6 +133,17 @@ class AbstractInterpreter: AllStatic { static address entry_for_kind(MethodKind k) { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; } static address entry_for_method(methodHandle m) { return entry_for_kind(method_kind(m)); } + static address entry_for_cds_method(methodHandle m) { + MethodKind k = method_kind(m); + assert(0 <= k && k < number_of_method_entries, "illegal kind"); + return _cds_entry_table[k]; + } + + // used by class data sharing + static void update_cds_entry_table(MethodKind kind) NOT_CDS_RETURN; + + static address get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) NOT_CDS_RETURN_(0); + // used for bootstrapping method handles: static void set_entry_for_kind(MethodKind k, address e); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index 0fbe6f8ddac..a10981c48af 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -212,6 +212,7 @@ void TemplateInterpreterGenerator::generate_all() { #define method_entry(kind) \ { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ + Interpreter::update_cds_entry_table(Interpreter::kind); \ } // all non-native method kinds diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 606b7bd6960..ec3b9462959 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -959,6 +959,16 @@ bool FileMapInfo::is_in_shared_space(const void* p) { return false; } +// Check if a given address is within one of the shared regions (ro, rw, md, mc) +bool FileMapInfo::is_in_shared_region(const void* p, int idx) { + assert((idx >= MetaspaceShared::ro) && (idx <= MetaspaceShared::mc), "invalid region index"); + char* base = _header->region_addr(idx); + if (p >= base && p < base + _header->_space[idx]._used) { + return true; + } + return false; +} + void FileMapInfo::print_shared_spaces() { tty->print_cr("Shared Spaces:"); for (int i = 0; i < MetaspaceShared::n_regions; i++) { diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index 7cb179434b9..2c02b427f0b 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -107,6 +107,8 @@ public: int _narrow_klass_shift; // save narrow klass base and shift address _narrow_klass_base; char* _misc_data_patching_start; + address _cds_i2i_entry_code_buffers; + size_t _cds_i2i_entry_code_buffers_size; struct space_info { int _crc; // crc checksum of the current space @@ -195,6 +197,19 @@ public: char* misc_data_patching_start() { return _header->_misc_data_patching_start; } void set_misc_data_patching_start(char* p) { _header->_misc_data_patching_start = p; } + address cds_i2i_entry_code_buffers() { + return _header->_cds_i2i_entry_code_buffers; + } + void set_cds_i2i_entry_code_buffers(address addr) { + _header->_cds_i2i_entry_code_buffers = addr; + } + size_t cds_i2i_entry_code_buffers_size() { + return _header->_cds_i2i_entry_code_buffers_size; + } + void set_cds_i2i_entry_code_buffers_size(size_t s) { + _header->_cds_i2i_entry_code_buffers_size = s; + } + static FileMapInfo* current_info() { CDS_ONLY(return _current_info;) NOT_CDS(return NULL;) @@ -234,6 +249,7 @@ public: // Return true if given address is in the mapped shared space. bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); void print_shared_spaces() NOT_CDS_RETURN; static size_t shared_spaces_size() { diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 36efacfc4ab..fa4d31a54be 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -59,6 +59,8 @@ bool MetaspaceShared::_link_classes_made_progress; bool MetaspaceShared::_check_classes_made_progress; bool MetaspaceShared::_has_error_classes; bool MetaspaceShared::_archive_loading_failed = false; +address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL; +size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0; SharedMiscRegion MetaspaceShared::_mc; SharedMiscRegion MetaspaceShared::_md; @@ -129,6 +131,21 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { soc->do_tag(666); } +address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) { + if (DumpSharedSpaces) { + if (_cds_i2i_entry_code_buffers == NULL) { + _cds_i2i_entry_code_buffers = (address)misc_data_space_alloc(total_size); + _cds_i2i_entry_code_buffers_size = total_size; + } + } else if (UseSharedSpaces) { + assert(_cds_i2i_entry_code_buffers != NULL, "must already been initialized"); + } else { + return NULL; + } + + assert(_cds_i2i_entry_code_buffers_size == total_size, "must not change"); + return _cds_i2i_entry_code_buffers; +} // CDS code for dumping shared archive. @@ -576,6 +593,8 @@ void VM_PopulateDumpSharedSpace::doit() { &md_top, md_end, &mc_top, mc_end); + guarantee(md_top <= md_end, "Insufficient space for vtables."); + // Reorder the system dictionary. (Moving the symbols affects // how the hash table indices are calculated.) // Not doing this either. @@ -668,6 +687,8 @@ void VM_PopulateDumpSharedSpace::doit() { FileMapInfo* mapinfo = new FileMapInfo(); mapinfo->populate_header(MetaspaceShared::max_alignment()); mapinfo->set_misc_data_patching_start((char*)vtbl_list); + mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers()); + mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size()); for (int pass=1; pass<=2; pass++) { if (pass == 1) { @@ -686,7 +707,7 @@ void VM_PopulateDumpSharedSpace::doit() { mapinfo->write_region(MetaspaceShared::md, _md_vs.low(), pointer_delta(md_top, _md_vs.low(), sizeof(char)), SharedMiscDataSize, - false, false); + false, true); mapinfo->write_region(MetaspaceShared::mc, _mc_vs.low(), pointer_delta(mc_top, _mc_vs.low(), sizeof(char)), SharedMiscCodeSize, @@ -980,6 +1001,11 @@ bool MetaspaceShared::is_in_shared_space(const void* p) { return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p); } +// Return true if given address is in the misc data region +bool MetaspaceShared::is_in_shared_region(const void* p, int idx) { + return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_region(p, idx); +} + bool MetaspaceShared::is_string_region(int idx) { return (idx >= MetaspaceShared::first_string && idx < MetaspaceShared::first_string + MetaspaceShared::max_strings); @@ -1053,6 +1079,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { void MetaspaceShared::initialize_shared_spaces() { FileMapInfo *mapinfo = FileMapInfo::current_info(); + _cds_i2i_entry_code_buffers = mapinfo->cds_i2i_entry_code_buffers(); + _cds_i2i_entry_code_buffers_size = mapinfo->cds_i2i_entry_code_buffers_size(); char* buffer = mapinfo->misc_data_patching_start(); // Skip over (reserve space for) a list of addresses of C++ vtables diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index c78f78122cf..e759464591d 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -50,17 +50,14 @@ #define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(9*M)) // the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on -// MetaspaceShared::generate_vtable_methods(). -// The minimum size only accounts for the vtable methods. Any size less than the -// minimum required size would cause vm crash when allocating the vtable methods. -#define SHARED_MISC_SIZE_FOR(size) (DEFAULT_VTBL_VIRTUALS_COUNT*DEFAULT_VTBL_LIST_SIZE*size) +// the sizes required for dumping the archive using the default classlist. The sizes +// are multiplied by 1.5 for a safety margin. #define DEFAULT_SHARED_MISC_DATA_SIZE (NOT_LP64(2*M) LP64_ONLY(4*M)) -#define MIN_SHARED_MISC_DATA_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))) +#define MIN_SHARED_MISC_DATA_SIZE (NOT_LP64(1*M) LP64_ONLY(1200*K)) #define DEFAULT_SHARED_MISC_CODE_SIZE (120*K) -#define MIN_SHARED_MISC_CODE_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))+SHARED_MISC_SIZE_FOR(DEFAULT_VTBL_METHOD_SIZE)+DEFAULT_VTBL_COMMON_CODE_SIZE) - +#define MIN_SHARED_MISC_CODE_SIZE (NOT_LP64(63*K) LP64_ONLY(69*K)) #define DEFAULT_COMBINED_SIZE (DEFAULT_SHARED_READ_WRITE_SIZE+DEFAULT_SHARED_READ_ONLY_SIZE+DEFAULT_SHARED_MISC_DATA_SIZE+DEFAULT_SHARED_MISC_CODE_SIZE) // the max size is the MAX size (ie. 0x7FFFFFFF) - the total size of @@ -128,6 +125,8 @@ class MetaspaceShared : AllStatic { static bool _check_classes_made_progress; static bool _has_error_classes; static bool _archive_loading_failed; + static address _cds_i2i_entry_code_buffers; + static size_t _cds_i2i_entry_code_buffers_size; // Used only during dumping. static SharedMiscRegion _md; @@ -185,6 +184,9 @@ class MetaspaceShared : AllStatic { // Return true if given address is in the mapped shared space. static bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + // Return true if given address is in the shared region corresponding to the idx + static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); + static bool is_string_region(int idx) NOT_CDS_RETURN_(false); static void generate_vtable_methods(void** vtbl_list, @@ -218,6 +220,15 @@ class MetaspaceShared : AllStatic { static char* misc_code_space_alloc(size_t num_bytes) { return _mc.alloc(num_bytes); } static char* misc_data_space_alloc(size_t num_bytes) { return _md.alloc(num_bytes); } + static address cds_i2i_entry_code_buffers(size_t total_size); + + static address cds_i2i_entry_code_buffers() { + return _cds_i2i_entry_code_buffers; + } + static size_t cds_i2i_entry_code_buffers_size() { + return _cds_i2i_entry_code_buffers_size; + } + static SharedMiscRegion* misc_code_region() { assert(DumpSharedSpaces, "used during dumping only"); return &_mc; diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 7d959fb516b..01df3b1a3d8 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -121,6 +121,7 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { }; class KlassSizeStats; +class AdapterHandlerEntry; // Class to collect the sizes of ConstMethod inline tables #define INLINE_TABLES_DO(do_element) \ @@ -201,6 +202,12 @@ private: // Raw stackmap data for the method Array* _stackmap_data; + // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. + union { + AdapterHandlerEntry* _adapter; + AdapterHandlerEntry** _adapter_trampoline; + }; + int _constMethod_size; u2 _flags; @@ -276,6 +283,29 @@ public: void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS); bool has_stackmap_table() const { return _stackmap_data != NULL; } + // adapter + void set_adapter_entry(AdapterHandlerEntry* adapter) { + assert(!is_shared(), "shared methods have fixed adapter_trampoline"); + _adapter = adapter; + } + void set_adapter_trampoline(AdapterHandlerEntry** trampoline) { + assert(DumpSharedSpaces, "must be"); + assert(*trampoline == NULL, "must be NULL during dump time, to be initialized at run time"); + _adapter_trampoline = trampoline; + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + assert(is_shared(), "must be"); + *_adapter_trampoline = adapter; + assert(this->adapter() == adapter, "must be"); + } + AdapterHandlerEntry* adapter() { + if (is_shared()) { + return *_adapter_trampoline; + } else { + return _adapter; + } + } + void init_fingerprint() { const uint64_t initval = UCONST64(0x8000000000000000); _fingerprint = initval; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index efaaaa5009a..b3f2b868b64 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -38,6 +38,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/constMethod.hpp" @@ -123,18 +124,18 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) { } address Method::get_i2c_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_i2c_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_i2c_entry(); } address Method::get_c2i_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_entry(); } address Method::get_c2i_unverified_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_unverified_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_unverified_entry(); } char* Method::name_and_sig_as_C_string() const { @@ -892,10 +893,10 @@ void Method::clear_code() { // this may be NULL if c2i adapters have not been made yet // Only should happen at allocate time. - if (_adapter == NULL) { + if (adapter() == NULL) { _from_compiled_entry = NULL; } else { - _from_compiled_entry = _adapter->get_c2i_entry(); + _from_compiled_entry = adapter()->get_c2i_entry(); } OrderAccess::storestore(); _from_interpreted_entry = _i2i_entry; @@ -903,47 +904,68 @@ void Method::clear_code() { _code = NULL; } +#if INCLUDE_CDS // Called by class data sharing to remove any entry points (which are not shared) void Method::unlink_method() { _code = NULL; - _i2i_entry = NULL; - _from_interpreted_entry = NULL; + + assert(DumpSharedSpaces, "dump time only"); + // Set the values to what they should be at run time. Note that + // this Method can no longer be executed during dump time. + _i2i_entry = Interpreter::entry_for_cds_method(this); + _from_interpreted_entry = _i2i_entry; + if (is_native()) { *native_function_addr() = NULL; set_signature_handler(NULL); } NOT_PRODUCT(set_compiled_invocation_count(0);) - _adapter = NULL; - _from_compiled_entry = NULL; + + CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter(); + constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline()); + _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline(); + assert(*((int*)_from_compiled_entry) == 0, "must be NULL during dump time, to be initialized at run time"); + // In case of DumpSharedSpaces, _method_data should always be NULL. - // - // During runtime (!DumpSharedSpaces), when we are cleaning a - // shared class that failed to load, this->link_method() may - // have already been called (before an exception happened), so - // this->_method_data may not be NULL. - assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); + assert(_method_data == NULL, "unexpected method data?"); set_method_data(NULL); clear_method_counters(); } +#endif // Called when the method_holder is getting linked. Setup entrypoints so the method // is ready to be called from interpreter, compiler, and vtables. void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. - if (_i2i_entry != NULL) return; + if (is_shared()) { + if (adapter() != NULL) return; + } else { + if (_i2i_entry != NULL) return; - assert(_adapter == NULL, "init'd to NULL" ); + assert(adapter() == NULL, "init'd to NULL" ); + } assert( _code == NULL, "nothing compiled yet" ); // Setup interpreter entrypoint assert(this == h_method(), "wrong h_method()" ); - address entry = Interpreter::entry_for_method(h_method); + address entry; + + if (this->is_shared()) { + entry = Interpreter::entry_for_cds_method(h_method); + } else { + entry = Interpreter::entry_for_method(h_method); + } assert(entry != NULL, "interpreter entry must be non-null"); - // Sets both _i2i_entry and _from_interpreted_entry - set_interpreter_entry(entry); + if (is_shared()) { + assert(entry == _i2i_entry && entry == _from_interpreted_entry, + "should be correctly set during dump time"); + } else { + // Sets both _i2i_entry and _from_interpreted_entry + set_interpreter_entry(entry); + } // Don't overwrite already registered native entries. if (is_native() && !has_native_function()) { @@ -975,8 +997,13 @@ address Method::make_adapters(methodHandle mh, TRAPS) { THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for adapters"); } - mh->set_adapter_entry(adapter); - mh->_from_compiled_entry = adapter->get_c2i_entry(); + if (mh->is_shared()) { + assert(mh->adapter() == adapter, "must be"); + assert(mh->_from_compiled_entry != NULL, "must be"); // FIXME, the instructions also not NULL + } else { + mh->set_adapter_entry(adapter); + mh->_from_compiled_entry = adapter->get_c2i_entry(); + } return adapter->get_c2i_entry(); } @@ -992,6 +1019,14 @@ void Method::restore_unshareable_info(TRAPS) { } } +volatile address Method::from_compiled_entry_no_trampoline() const { + nmethod *code = (nmethod *)OrderAccess::load_ptr_acquire(&_code); + if (code) { + return code->verified_entry_point(); + } else { + return adapter()->get_c2i_entry(); + } +} // The verified_code_entry() must be called when a invoke is resolved // on this method. diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 8fc7b133a16..d7a705fd84f 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -93,8 +93,6 @@ class Method : public Metadata { #endif // Entry point for calling both from and to the interpreter. address _i2i_entry; // All-args-on-stack calling convention - // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. - AdapterHandlerEntry* _adapter; // Entry point for calling from compiled code, to compiled code if it exists // or else the interpreter. volatile address _from_compiled_entry; // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry() @@ -137,6 +135,7 @@ class Method : public Metadata { static address make_adapters(methodHandle mh, TRAPS); volatile address from_compiled_entry() const { return (address)OrderAccess::load_ptr_acquire(&_from_compiled_entry); } + volatile address from_compiled_entry_no_trampoline() const; volatile address from_interpreted_entry() const{ return (address)OrderAccess::load_ptr_acquire(&_from_interpreted_entry); } // access flag @@ -431,15 +430,23 @@ class Method : public Metadata { nmethod* volatile code() const { assert( check_code(), "" ); return (nmethod *)OrderAccess::load_ptr_acquire(&_code); } void clear_code(); // Clear out any compiled code static void set_code(methodHandle mh, nmethod* code); - void set_adapter_entry(AdapterHandlerEntry* adapter) { _adapter = adapter; } + void set_adapter_entry(AdapterHandlerEntry* adapter) { + constMethod()->set_adapter_entry(adapter); + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + constMethod()->update_adapter_trampoline(adapter); + } + address get_i2c_entry(); address get_c2i_entry(); address get_c2i_unverified_entry(); - AdapterHandlerEntry* adapter() { return _adapter; } + AdapterHandlerEntry* adapter() const { + return constMethod()->adapter(); + } // setup entry points void link_method(const methodHandle& method, TRAPS); - // clear entry points. Used by sharing code - void unlink_method(); + // clear entry points. Used by sharing code during dump time + void unlink_method() NOT_CDS_RETURN; // vtable index enum VtableIndexFlag { @@ -465,7 +472,15 @@ class Method : public Metadata { // interpreter entry address interpreter_entry() const { return _i2i_entry; } // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry - void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; } + void set_interpreter_entry(address entry) { + assert(!is_shared(), "shared method's interpreter entry should not be changed at run time"); + if (_i2i_entry != entry) { + _i2i_entry = entry; + } + if (_from_interpreted_entry != entry) { + _from_interpreted_entry = entry; + } + } // native function (used for native methods only) enum { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 89d0f2c66d3..d38d493f198 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -38,6 +38,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "logging/log.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/klass.hpp" @@ -1788,7 +1789,7 @@ void SharedRuntime::check_member_name_argument_is_last_argument(const methodHand IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc)) Method* moop(method); - address entry_point = moop->from_compiled_entry(); + address entry_point = moop->from_compiled_entry_no_trampoline(); // It's possible that deoptimization can occur at a call site which hasn't // been resolved yet, in which case this function will be called from @@ -2351,12 +2352,15 @@ class AdapterHandlerTable : public BasicHashtable { public: AdapterHandlerTable() - : BasicHashtable(293, sizeof(AdapterHandlerEntry)) { } + : BasicHashtable(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { } // Create a new entry suitable for insertion in the table AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) { AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); + if (DumpSharedSpaces) { + ((CDSAdapterHandlerEntry*)entry)->init(); + } return entry; } @@ -2519,6 +2523,28 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger } AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) { + AdapterHandlerEntry* entry = get_adapter0(method); + if (method->is_shared()) { + MutexLocker mu(AdapterHandlerLibrary_lock); + if (method->adapter() == NULL) { + method->update_adapter_trampoline(entry); + } + address trampoline = method->from_compiled_entry(); + if (*(int*)trampoline == 0) { + CodeBuffer buffer(trampoline, (int)SharedRuntime::trampoline_size()); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, entry->get_c2i_entry()); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } + } + + return entry; +} + +AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter0(const methodHandle& method) { // Use customized signature handler. Need to lock around updates to // the AdapterHandlerTable (it is not safe for concurrent readers // and a single writer: this could be fixed if it becomes a @@ -2535,7 +2561,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth // make sure data structure is initialized initialize(); - if (CodeCacheExtensions::skip_compiler_support()) { + // during dump time, always generate adapters, even if the + // compiler has been turned off. + if (!DumpSharedSpaces && CodeCacheExtensions::skip_compiler_support()) { // adapters are useless and should not be used, including the // abstract_method_handler. However, some callers check that // an adapter was installed. @@ -3017,6 +3045,17 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const { } +#if INCLUDE_CDS + +void CDSAdapterHandlerEntry::init() { + assert(DumpSharedSpaces, "used during dump time only"); + _c2i_entry_trampoline = (address)MetaspaceShared::misc_data_space_alloc(SharedRuntime::trampoline_size()); + _adapter_trampoline = (AdapterHandlerEntry**)MetaspaceShared::misc_data_space_alloc(sizeof(AdapterHandlerEntry*)); +}; + +#endif // INCLUDE_CDS + + #ifndef PRODUCT void AdapterHandlerLibrary::print_statistics() { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index b3f87cdc7c6..68baebc4686 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -398,6 +398,10 @@ class SharedRuntime: AllStatic { static void convert_ints_to_longints(int i2l_argcnt, int& in_args_count, BasicType*& in_sig_bt, VMRegPair*& in_regs); + static size_t trampoline_size(); + + static void generate_trampoline(MacroAssembler *masm, address destination); + // Generate I2C and C2I adapters. These adapters are simple argument marshalling // blobs. Unlike adapters in the tiger and earlier releases the code in these // blobs does not create a new frame and are therefore virtually invisible @@ -680,6 +684,17 @@ class AdapterHandlerEntry : public BasicHashtableEntry { void print_adapter_on(outputStream* st) const; }; +class CDSAdapterHandlerEntry: public AdapterHandlerEntry { + address _c2i_entry_trampoline; // allocated from shared spaces "MC" region + AdapterHandlerEntry** _adapter_trampoline; // allocated from shared spaces "MD" region + +public: + address get_c2i_entry_trampoline() const { return _c2i_entry_trampoline; } + AdapterHandlerEntry** get_adapter_trampoline() const { return _adapter_trampoline; } + void init() NOT_CDS_RETURN; +}; + + class AdapterHandlerLibrary: public AllStatic { private: static BufferBlob* _buffer; // the temporary code buffer in CodeCache @@ -687,6 +702,7 @@ class AdapterHandlerLibrary: public AllStatic { static AdapterHandlerEntry* _abstract_method_handler; static BufferBlob* buffer_blob(); static void initialize(); + static AdapterHandlerEntry* get_adapter0(const methodHandle& method); public: diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index d7e1f5cb07c..943bf9c83ea 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -400,7 +400,6 @@ typedef CompactHashtable SymbolCompactHashTable; nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \ volatile_nonstatic_field(Method, _code, nmethod*) \ nonstatic_field(Method, _i2i_entry, address) \ - nonstatic_field(Method, _adapter, AdapterHandlerEntry*) \ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ volatile_nonstatic_field(Method, _from_interpreted_entry, address) \ volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \ From 67ed0253791b39a59de25d70937b528186296b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Lid=C3=A9n?= Date: Fri, 8 Apr 2016 08:51:45 +0200 Subject: [PATCH 052/113] 8152989: serviceability/tmtools/jstat/GcCauseTest02.java fails with OOME Reviewed-by: dsamersoff, sjohanss, dfazunen --- .../serviceability/tmtools/jstat/GcCapacityTest.java | 4 ++-- .../serviceability/tmtools/jstat/GcCauseTest01.java | 2 +- .../serviceability/tmtools/jstat/GcCauseTest02.java | 4 ++-- .../serviceability/tmtools/jstat/GcCauseTest03.java | 4 ++-- .../test/serviceability/tmtools/jstat/GcNewTest.java | 4 ++-- .../test/serviceability/tmtools/jstat/GcTest01.java | 2 +- .../test/serviceability/tmtools/jstat/GcTest02.java | 10 ++-------- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index 6ec4db9829b..ec6d1bc2f4d 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -27,13 +27,13 @@ import utils.*; * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. - * @ignore 8149778 * @library /test/lib/share/classes * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcCapacityTest + * @ignore 8149778 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCapacityTest */ public class GcCapacityTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java index 55ee941e38c..508b7865a3c 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java @@ -34,7 +34,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcCauseTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCauseTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java index bc8f0058034..95200d453c5 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest02 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java index 1ebb98b00b5..94514d4b634 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest03 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest03 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java index e91ee8ecdf6..bdb06c1e6b2 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcNewTest + * @run main/othervm -XX:+UsePerfData -Xmx128M GcNewTest */ public class GcNewTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java index ee731adb144..2a6b0c544a8 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java @@ -37,7 +37,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java index c2e55229688..bcdc258c934 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcTest02 */ public class GcTest02 { @@ -58,10 +58,4 @@ public class GcTest02 { // Assert that space has been utilized acordingly JstatResults.assertSpaceUtilization(measurement2, targetMemoryUsagePercent); } - - private static void assertThat(boolean result, String message) { - if (!result) { - throw new RuntimeException(message); - }; - } } From 890207217fbce11ee25a3bc61643b9ece636458c Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Fri, 8 Apr 2016 00:38:00 -0700 Subject: [PATCH 053/113] 8146093: [sparc only] compiler/interpreter/7116216/StackOverflow.java Program terminates with signal 11, Segmentation fault. in __1cLRegisterMap2t6MpnKJavaThread_b_v_ () Reviewed-by: dcubed, coleenp --- .../sparc/vm/templateInterpreterGenerator_sparc.cpp | 2 +- .../src/share/vm/interpreter/interpreterRuntime.cpp | 13 +------------ .../src/share/vm/interpreter/interpreterRuntime.hpp | 2 -- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index 153bd2b2319..008fcee7a6a 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -616,7 +616,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe // compute the beginning of the protected zone minus the requested frame size __ sub( Rscratch, Rscratch2, Rscratch ); - __ set( JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size(), Rscratch2 ); + __ set(MAX2(JavaThread::stack_shadow_zone_size(), JavaThread::stack_guard_zone_size()), Rscratch2 ); __ add( Rscratch, Rscratch2, Rscratch ); // Add in the size of the frame (which is the same as subtracting it from the diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 2de3339c33e..4ddc09a77eb 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -313,18 +313,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* thread) THROW_HANDLE(exception); IRT_END -IRT_ENTRY(address, InterpreterRuntime::check_ReservedStackAccess_annotated_methods(JavaThread* thread)) - frame fr = thread->last_frame(); - assert(fr.is_java_frame(), "Must be a Java frame"); - frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); - if (activation.sp() != NULL) { - thread->disable_stack_reserved_zone(); - thread->set_reserved_stack_activation((address)activation.unextended_sp()); - } - return (address)activation.sp(); -IRT_END - - IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) +IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) Handle exception = get_preinitialized_exception( SystemDictionary::StackOverflowError_klass(), CHECK); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 02fc2cf3b2e..2039adba2a0 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -91,8 +91,6 @@ class InterpreterRuntime: AllStatic { // Quicken instance-of and check-cast bytecodes static void quicken_io_cc(JavaThread* thread); - static address check_ReservedStackAccess_annotated_methods(JavaThread* thread); - // Exceptions thrown by the interpreter static void throw_AbstractMethodError(JavaThread* thread); static void throw_IncompatibleClassChangeError(JavaThread* thread); From e709aa268df64b2dc000433a1d9621a2fb0940f0 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 8 Apr 2016 13:14:23 +0200 Subject: [PATCH 054/113] 8152666: The new Hotspot Build System Co-authored-by: Magnus Ihse Bursie Co-authored-by: Ingemar Aberg Reviewed-by: ihse, dcubed, erikj --- common/autoconf/basics.m4 | 7 +- common/autoconf/build-performance.m4 | 3 + common/autoconf/buildjdk-spec.gmk.in | 11 + common/autoconf/compare.sh.in | 1 + common/autoconf/configure | 2 +- common/autoconf/configure.ac | 14 +- common/autoconf/flags.m4 | 860 +++++--- common/autoconf/generated-configure.sh | 2630 ++++++++++++++++++++---- common/autoconf/help.m4 | 13 +- common/autoconf/hotspot-spec.gmk.in | 13 +- common/autoconf/hotspot.m4 | 491 +++-- common/autoconf/jdk-options.m4 | 30 +- common/autoconf/jdk-version.m4 | 1 + common/autoconf/lib-std.m4 | 16 +- common/autoconf/libraries.m4 | 4 +- common/autoconf/platform.m4 | 245 +-- common/autoconf/spec.gmk.in | 74 +- common/autoconf/toolchain.m4 | 11 + common/autoconf/version-numbers | 1 + common/bin/compare.sh | 52 +- common/bin/compare_exceptions.sh.incl | 122 +- common/conf/jib-profiles.js | 8 +- make/Jprt.gmk | 21 +- make/Main.gmk | 13 +- make/common/MakeBase.gmk | 12 +- make/common/NativeCompilation.gmk | 141 +- make/jprt.properties | 8 +- 27 files changed, 3729 insertions(+), 1075 deletions(-) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 753d170beb2..f295a46d3c4 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -749,8 +749,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], BASIC_PREPEND_TO_PATH([PATH],$EXTRA_PATH) if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi AC_MSG_CHECKING([for sysroot]) @@ -777,7 +777,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], # Create a default ./build/target-variant-debuglevel output root. if test "x${CONF_NAME}" = x; then AC_MSG_RESULT([in default location]) - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else AC_MSG_RESULT([in build directory with custom name]) fi @@ -1037,6 +1037,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], BASIC_PATH_PROGS(HG, hg) BASIC_PATH_PROGS(STAT, stat) BASIC_PATH_PROGS(TIME, time) + BASIC_PATH_PROGS(DTRACE, dtrace) BASIC_PATH_PROGS(PATCH, [gpatch patch]) # Check if it's GNU time IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index a3c69e02d08..0de3a9ee7f8 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -364,6 +364,9 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS], elif test "x$ICECC" != "x"; then AC_MSG_RESULT([no, does not work effectively with icecc]) USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + AC_MSG_RESULT([no, does not work with Solaris Studio]) + USE_PRECOMPILED_HEADER=0 else AC_MSG_RESULT([yes]) fi diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in index f92602edc34..89167a388fb 100644 --- a/common/autoconf/buildjdk-spec.gmk.in +++ b/common/autoconf/buildjdk-spec.gmk.in @@ -57,6 +57,12 @@ OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@ OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@ OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@ +HOTSPOT_TARGET_OS := @HOTSPOT_BUILD_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_BUILD_OS_TYPE@ +HOTSPOT_TARGET_CPU := @HOTSPOT_BUILD_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_BUILD_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_BUILD_CPU_DEFINE@ + CFLAGS_JDKLIB := @OPENJDK_BUILD_CFLAGS_JDKLIB@ CXXFLAGS_JDKLIB := @OPENJDK_BUILD_CXXFLAGS_JDKLIB@ LDFLAGS_JDKLIB := @OPENJDK_BUILD_LDFLAGS_JDKLIB@ @@ -65,6 +71,11 @@ CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@ LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@ OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@ +JVM_CFLAGS := @OPENJDK_BUILD_JVM_CFLAGS@ +JVM_LDFLAGS := @OPENJDK_BUILD_JVM_LDFLAGS@ +JVM_ASFLAGS := @OPENJDK_BUILD_JVM_ASFLAGS@ +JVM_LIBS := @OPENJDK_BUILD_JVM_LIBS@ + # The compiler for the build platform is likely not warning compatible with the official # compiler. WARNINGS_AS_ERRORS := false diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index f8f97ec02d2..e03ff07387c 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -34,6 +34,7 @@ export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@ export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@" export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@" export OPENJDK_TARGET_CPU_LIBDIR="@OPENJDK_TARGET_CPU_LIBDIR@" +export DEBUG_LEVEL="@DEBUG_LEVEL@" export AWK="@AWK@" export BASH="@BASH@" diff --git a/common/autoconf/configure b/common/autoconf/configure index 6815da9a3b1..547cb33fbc8 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -283,7 +283,7 @@ Additional (non-autoconf) OpenJDK Options: EOT - # Print additional help, e.g. a list of toolchains. + # Print additional help, e.g. a list of toolchains and JVM features. # This must be done by the autoconf script. ( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $conf_script_to_run PRINTF=printf ) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index c7bab7c53a8..7d5056cb47d 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -95,10 +95,8 @@ JDKOPT_SETUP_OPEN_OR_CUSTOM # These are needed to be able to create a configuration name (and thus the output directory) JDKOPT_SETUP_JDK_VARIANT -HOTSPOT_SETUP_JVM_INTERPRETER -HOTSPOT_SETUP_JVM_VARIANTS JDKOPT_SETUP_DEBUG_LEVEL -HOTSPOT_SETUP_DEBUG_LEVEL +HOTSPOT_SETUP_JVM_VARIANTS # With basic setup done, call the custom early hook. CUSTOM_EARLY_HOOK @@ -135,7 +133,6 @@ BASIC_SETUP_DEFAULT_MAKE_TARGET # We need build & target for this. JDKOPT_SETUP_JDK_OPTIONS JDKOPT_SETUP_JLINK_OPTIONS -HOTSPOT_SETUP_HOTSPOT_OPTIONS JDKVER_SETUP_JDK_VERSION_NUMBERS ############################################################################### @@ -207,6 +204,10 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC JDKOPT_SETUP_DEBUG_SYMBOLS JDKOPT_SETUP_CODE_COVERAGE +# Need toolchain to setup dtrace +HOTSPOT_SETUP_DTRACE +HOTSPOT_SETUP_JVM_FEATURES + ############################################################################### # # Check dependencies for external and internal libraries. @@ -225,7 +226,7 @@ LIB_SETUP_LIBRARIES # ############################################################################### -HOTSPOT_SETUP_BUILD_TWEAKS +HOTSPOT_SETUP_LEGACY_BUILD JDKOPT_DETECT_INTREE_EC ############################################################################### @@ -267,6 +268,9 @@ BASIC_TEST_USABILITY_ISSUES # At the end, call the custom hook. (Dummy macro if no custom sources available) CUSTOM_LATE_HOOK +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. +HOTSPOT_VALIDATE_JVM_FEATURES + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index b738ef49e22..5e9fc128843 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -61,6 +61,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS], AC_SUBST(LEGACY_EXTRA_CXXFLAGS) AC_SUBST(LEGACY_EXTRA_LDFLAGS) + AC_SUBST(EXTRA_CFLAGS) + AC_SUBST(EXTRA_CXXFLAGS) + AC_SUBST(EXTRA_LDFLAGS) + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -211,8 +215,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -228,8 +234,19 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi AC_SUBST(RC_FLAGS) + AC_SUBST(JVM_RCFLAGS) if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. @@ -237,7 +254,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], fi ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], [ ############################################################################### # @@ -255,6 +272,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -280,6 +298,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,[$]1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -339,11 +361,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], AC_SUBST(SET_SHARED_LIBRARY_MAPFILE) AC_SUBST(SHARED_LIBRARY_FLAGS) - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. ]) @@ -434,6 +451,22 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], AC_SUBST(CFLAGS_DEBUG_SYMBOLS) AC_SUBST(CXXFLAGS_DEBUG_SYMBOLS) + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + AC_SUBST(JVM_CFLAGS_SYMBOLS) + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -444,7 +477,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -455,40 +488,59 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -498,48 +550,75 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -554,260 +633,43 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac + AC_SUBST(C_O_FLAG_HIGHEST_JVM) AC_SUBST(C_O_FLAG_HIGHEST) AC_SUBST(C_O_FLAG_HI) AC_SUBST(C_O_FLAG_NORM) AC_SUBST(C_O_FLAG_DEBUG) AC_SUBST(C_O_FLAG_NONE) + AC_SUBST(C_O_FLAG_SIZE) + AC_SUBST(CXX_O_FLAG_HIGHEST_JVM) AC_SUBST(CXX_O_FLAG_HIGHEST) AC_SUBST(CXX_O_FLAG_HI) AC_SUBST(CXX_O_FLAG_NORM) AC_SUBST(CXX_O_FLAG_DEBUG) AC_SUBST(CXX_O_FLAG_NONE) + AC_SUBST(CXX_O_FLAG_SIZE) ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], + +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], [ - # Special extras... - if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - fi - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" - elif test "x$TOOLCHAIN_TYPE" = xxlc; then - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" - elif test "x$TOOLCHAIN_TYPE" = xgcc; then - CXXSTD_CXXFLAG="-std=gnu++98" - FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$CXXSTD_CXXFLAG -Werror], - IF_FALSE: [CXXSTD_CXXFLAG=""]) - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" - AC_SUBST([CXXSTD_CXXFLAG]) - fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" - - ############################################################################### - # - # Now setup the CFLAGS and LDFLAGS for the JDK build. - # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. - # - - # Setup compiler/platform specific flags into - # CFLAGS_JDK - C Compiler flags - # CXXFLAGS_JDK - C++ Compiler flags - # COMMON_CCXXFLAGS_JDK - common to C and C++ - if test "x$TOOLCHAIN_TYPE" = xgcc; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then - # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" - fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - arm ) - # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - ppc ) - # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS) - elif test "x$TOOLCHAIN_TYPE" = xclang; then - if test "x$OPENJDK_TARGET_OS" = xlinux; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then - # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" - fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - ppc ) - # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - fi - elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" - if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" - fi - - CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" - CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" - elif test "x$TOOLCHAIN_TYPE" = xxlc; then - CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK \ - -MD -Zc:wchar_t- -W3 -wd4800 \ - -DWIN32_LEAN_AND_MEAN \ - -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ - -D_WINSOCK_DEPRECATED_NO_WARNINGS \ - -DWIN32 -DIAL" - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" - fi - # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to - # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual - # studio. - if test "x$TOOLCHAIN_VERSION" = "x2010"; then - STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" - fi - fi - - ############################################################################### - - # Adjust flags according to debug level. - case $DEBUG_LEVEL in - fastdebug | slowdebug ) - CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" - CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - release ) - ;; - * ) - AC_MSG_ERROR([Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL]) - ;; - esac - - # Set some common defines. These works for all compilers, but assume - # -D is universally accepted. - - # Setup endianness - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then - # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the - # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN - # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). - # Note: -Dmacro is the same as #define macro 1 - # -Dmacro= is the same as #define macro - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" - fi - else - # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they - # are defined in the system? - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" - fi - fi - - # Setup target OS define. Use OS target name but in upper case. - OPENJDK_TARGET_OS_UPPERCASE=`$ECHO $OPENJDK_TARGET_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" - - # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ - -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" - - # Setup debug/release defines - if test "x$DEBUG_LEVEL" = xrelease; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DNDEBUG" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DTRIMMED" - fi - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DDEBUG" - fi - - # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" - elif test "x$OPENJDK_TARGET_OS" = xbsd; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" - fi - - # Additional macosx handling - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # Setting these parameters makes it an error to link to macosx APIs that are - # newer than the given OS version and makes the linked binaries compatible - # even if built on a newer version of the OS. - # The expected format is X.Y.Z - MACOSX_VERSION_MIN=10.7.0 - AC_SUBST(MACOSX_VERSION_MIN) - - # The macro takes the version with no dots, ex: 1070 - # Let the flags variables get resolved in make for easier override on make - # command line. - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - fi - - # Setup some hard coded includes - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ - -I${JDK_TOPDIR}/src/java.base/share/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ - -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" - - # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - AC_SUBST(CFLAGS_JDKLIB) - AC_SUBST(CFLAGS_JDKEXE) - AC_SUBST(CXXFLAGS_JDKLIB) - AC_SUBST(CXXFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKEXE) + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([TARGET]) + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([BUILD], [OPENJDK_BUILD_]) + # Tests are only ever compiled for TARGET # Flags for compiling test libraries CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" @@ -821,52 +683,425 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], AC_SUBST(CXXFLAGS_TESTLIB) AC_SUBST(CXXFLAGS_TESTEXE) + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" + LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + + AC_SUBST(LDFLAGS_TESTLIB) + AC_SUBST(LDFLAGS_TESTEXE) + +]) + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], +[ + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + $2CXXSTD_CXXFLAG="-std=gnu++98" + FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [[$]$2CXXSTD_CXXFLAG -Werror], + IF_FALSE: [$2CXXSTD_CXXFLAG=""]) + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2CXXSTD_CXXFLAG}" + AC_SUBST([$2CXXSTD_CXXFLAG]) + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + $2CFLAGS_JDK="${$2CFLAGS_JDK} ${$2EXTRA_CFLAGS}" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2EXTRA_CXXFLAGS}" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} ${$2EXTRA_LDFLAGS}" + + ############################################################################### + # + # Now setup the CFLAGS and LDFLAGS for the JDK build. + # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. + # + + # Setup compiler/platform specific flags into + # $2CFLAGS_JDK - C Compiler flags + # $2CXXFLAGS_JDK - C++ Compiler flags + # $2COMMON_CCXXFLAGS_JDK - common to C and C++ + if test "x$TOOLCHAIN_TYPE" = xgcc; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_$1_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" + fi + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_$1_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS) + elif test "x$TOOLCHAIN_TYPE" = xclang; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" + fi + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-sometimes-uninitialized" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_$1_CPU_ARCH in + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSPARC_WORKS" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_$1_CPU_LEGACY_LIB" + fi + + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK \ + -MD -Zc:wchar_t- -W3 -wd4800 \ + -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -D_WINSOCK_DEPRECATED_NO_WARNINGS \ + -DWIN32 -DIAL" + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to + # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual + # studio. + if test "x$TOOLCHAIN_VERSION" = "x2010"; then + STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS $STATIC_CPPLIB_FLAGS" + fi + fi + + ############################################################################### + + # Adjust flags according to debug level. + case $DEBUG_LEVEL in + fastdebug | slowdebug ) + $2CFLAGS_JDK="[$]$2CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + release ) + ;; + * ) + AC_MSG_ERROR([Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL]) + ;; + esac + + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + + # Setup endianness + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then + # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the + # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN + # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). + # Note: -Dmacro is the same as #define macro 1 + # -Dmacro= is the same as #define macro + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + fi + else + # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they + # are defined in the system? + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + fi + fi + + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_$1_OS_UPPERCASE=`$ECHO $OPENJDK_$1_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D$OPENJDK_$1_OS_UPPERCASE" + + # Setup target CPU + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ + $OPENJDK_$1_ADD_LP64 \ + -DARCH='\"$OPENJDK_$1_CPU_LEGACY\"' -D$OPENJDK_$1_CPU_LEGACY" + + # Setup debug/release defines + if test "x$DEBUG_LEVEL" = xrelease; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DTRIMMED" + fi + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DDEBUG" + fi + + # Set some additional per-OS defines. + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DLINUX" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_$1_OS-$OPENJDK_$1_CPU" = xwindows-x86; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_$1_CPU" = xppc64; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_$1_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_$1_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_OS" != xsolaris && test "x$OPENJDK_$1_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set $2JVM_CFLAGS warning handling + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: [4.8], + IF_AT_LEAST: [ + # These flags either do not work or give spurious warnings prior to gcc 4.8. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + ] + ) + fi + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # Non-zero builds have stricter warnings + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" + fi + + # Additional macosx handling + if test "x$OPENJDK_$1_OS" = xmacosx; then + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + AC_SUBST(MACOSX_VERSION_MIN) + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + + # Setup some hard coded includes + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ + -I${JDK_TOPDIR}/src/java.base/share/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava" + + # The shared libraries are compiled using the picflag. + $2CFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK $PICFLAG [$]$2CFLAGS_JDKLIB_EXTRA" + $2CXXFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK $PICFLAG [$]$2CXXFLAGS_JDKLIB_EXTRA" + + # Executable flags + $2CFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK" + $2CXXFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK" + + AC_SUBST($2CFLAGS_JDKLIB) + AC_SUBST($2CFLAGS_JDKEXE) + AC_SUBST($2CXXFLAGS_JDKLIB) + AC_SUBST($2CXXFLAGS_JDKEXE) + # Setup LDFLAGS et al. # if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_$1_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SAFESH" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:I386" + else + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_$1_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? # We have previously set HAS_GNU_HASH if this is the case if test -n "$HAS_GNU_HASH"; then - LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + $2LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} [$]$2LDFLAGS_HASH_STYLE" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS [$]$2LDFLAGS_HASH_STYLE" fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_$1_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -876,85 +1111,122 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_SOLSTUDIO="-Wl,-z,defs" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_XLC" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables - LDFLAGS_JDKEXE="${LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDK}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then + if test "x$OPENJDK_$1_CPU_BITS" = "x64"; then LDFLAGS_STACK_SIZE=1048576 else LDFLAGS_STACK_SIZE=327680 fi - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" - elif test "x$OPENJDK_TARGET_OS" = xlinux; then - LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_$1_OS" = xlinux; then + $2LDFLAGS_JDKEXE="[$]$2LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} ${$2EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs - LDFLAGS_JDKLIB="${LDFLAGS_JDK}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDK}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" - JDKLIB_LIBS="" + $2JDKLIB_LIBS="" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)" + if test "x$1" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if HOTSPOT_CHECK_JVM_VARIANT(server); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + elif HOTSPOT_CHECK_JVM_VARIANT(client); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/client" + elif HOTSPOT_CHECK_JVM_VARIANT(minimal); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + fi + elif test "x$1" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" fi - JDKLIB_LIBS="-ljava -ljvm" + $2JDKLIB_LIBS="-ljava -ljvm" if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - JDKLIB_LIBS="$JDKLIB_LIBS -lc" + $2JDKLIB_LIBS="[$]$2JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" + # Set $2JVM_LIBS (per os) + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + $2JVM_LIBS="[$]$2JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_LIBS="[$]$2JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_LIBS="[$]$2JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi - AC_SUBST(LDFLAGS_JDKLIB) - AC_SUBST(LDFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE) - AC_SUBST(JDKLIB_LIBS) - AC_SUBST(JDKEXE_LIBS) - AC_SUBST(LDFLAGS_CXX_JDK) - AC_SUBST(LDFLAGS_HASH_STYLE) + # Set $2JVM_ASFLAGS + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi - LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" - LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${$2EXTRA_LDFLAGS_JDK}" + + AC_SUBST($2LDFLAGS_JDKLIB) + AC_SUBST($2LDFLAGS_JDKEXE) + AC_SUBST($2JDKLIB_LIBS) + AC_SUBST($2JDKEXE_LIBS) + AC_SUBST($2LDFLAGS_CXX_JDK) + AC_SUBST($2LDFLAGS_HASH_STYLE) + + AC_SUBST($2JVM_CFLAGS) + AC_SUBST($2JVM_LDFLAGS) + AC_SUBST($2JVM_ASFLAGS) + AC_SUBST($2JVM_LIBS) - AC_SUBST(LDFLAGS_TESTLIB) - AC_SUBST(LDFLAGS_TESTEXE) ]) # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 0c503ce2be9..d97c4b4ebc7 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -651,7 +651,21 @@ JOBS MEMORY_SIZE NUM_CORES ENABLE_INTREE_EC +JVM_VARIANT_CORE +JVM_VARIANT_ZEROSHARK +JVM_VARIANT_ZERO +JVM_VARIANT_HOTSPOT +JVM_VARIANT_MINIMAL1 +JVM_VARIANT_CLIENT +JVM_VARIANT_SERVER +JVM_VARIANTS_COMMA +TEST_IN_BUILD HOTSPOT_MAKE_ARGS +MACOSX_UNIVERSAL +DEBUG_CLASSFILES +FASTDEBUG +VARIANT +USE_NEW_HOTSPOT_BUILD LIBZIP_CAN_USE_MMAP LIBDL LIBM @@ -687,6 +701,15 @@ LIBCXX STATIC_CXX_SETTING FIXPATH_DETACH_FLAG FIXPATH +VALID_JVM_FEATURES +JVM_FEATURES_custom +JVM_FEATURES_zeroshark +JVM_FEATURES_zero +JVM_FEATURES_minimal +JVM_FEATURES_core +JVM_FEATURES_client +JVM_FEATURES_server +INCLUDE_DTRACE GCOV_ENABLED STRIP_POLICY DEBUG_BINARIES @@ -702,22 +725,35 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG ZERO_ARCHFLAG LDFLAGS_TESTEXE LDFLAGS_TESTLIB -LDFLAGS_HASH_STYLE -LDFLAGS_CXX_JDK -JDKEXE_LIBS -JDKLIB_LIBS -OPENJDK_BUILD_LDFLAGS_JDKEXE -OPENJDK_BUILD_LDFLAGS_JDKLIB -LDFLAGS_JDKEXE -LDFLAGS_JDKLIB CXXFLAGS_TESTEXE CXXFLAGS_TESTLIB CFLAGS_TESTEXE CFLAGS_TESTLIB +OPENJDK_BUILD_JVM_LIBS +OPENJDK_BUILD_JVM_ASFLAGS +OPENJDK_BUILD_JVM_LDFLAGS +OPENJDK_BUILD_JVM_CFLAGS +OPENJDK_BUILD_LDFLAGS_HASH_STYLE +OPENJDK_BUILD_LDFLAGS_CXX_JDK +OPENJDK_BUILD_JDKEXE_LIBS +OPENJDK_BUILD_JDKLIB_LIBS +OPENJDK_BUILD_LDFLAGS_JDKEXE +OPENJDK_BUILD_LDFLAGS_JDKLIB OPENJDK_BUILD_CXXFLAGS_JDKEXE OPENJDK_BUILD_CXXFLAGS_JDKLIB OPENJDK_BUILD_CFLAGS_JDKEXE OPENJDK_BUILD_CFLAGS_JDKLIB +OPENJDK_BUILD_CXXSTD_CXXFLAG +JVM_LIBS +JVM_ASFLAGS +JVM_LDFLAGS +JVM_CFLAGS +LDFLAGS_HASH_STYLE +LDFLAGS_CXX_JDK +JDKEXE_LIBS +JDKLIB_LIBS +LDFLAGS_JDKEXE +LDFLAGS_JDKLIB CXXFLAGS_JDKEXE CXXFLAGS_JDKLIB CFLAGS_JDKEXE @@ -726,16 +762,21 @@ MACOSX_VERSION_MIN NO_LIFETIME_DSE_CFLAG NO_NULL_POINTER_CHECK_CFLAG CXXSTD_CXXFLAG +CXX_O_FLAG_SIZE CXX_O_FLAG_NONE CXX_O_FLAG_DEBUG CXX_O_FLAG_NORM CXX_O_FLAG_HI CXX_O_FLAG_HIGHEST +CXX_O_FLAG_HIGHEST_JVM +C_O_FLAG_SIZE C_O_FLAG_NONE C_O_FLAG_DEBUG C_O_FLAG_NORM C_O_FLAG_HI C_O_FLAG_HIGHEST +C_O_FLAG_HIGHEST_JVM +JVM_CFLAGS_SYMBOLS CXXFLAGS_DEBUG_SYMBOLS CFLAGS_DEBUG_SYMBOLS CXX_FLAG_DEPS @@ -747,6 +788,7 @@ SET_SHARED_LIBRARY_ORIGIN SET_EXECUTABLE_ORIGIN CXX_FLAG_REORDER C_FLAG_REORDER +JVM_RCFLAGS RC_FLAGS AR_OUT_OPTION LD_OUT_OPTION @@ -759,6 +801,7 @@ COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG JT_HOME JTREGEXE +HOTSPOT_TOOLCHAIN_TYPE USING_BROKEN_SUSE_LD PACKAGE_PATH USE_CLANG @@ -821,6 +864,9 @@ VS_PATH CYGWIN_LINK SYSROOT_LDFLAGS SYSROOT_CFLAGS +EXTRA_LDFLAGS +EXTRA_CXXFLAGS +EXTRA_CFLAGS LEGACY_EXTRA_LDFLAGS LEGACY_EXTRA_CXXFLAGS LEGACY_EXTRA_CFLAGS @@ -877,12 +923,12 @@ VERSION_MINOR VERSION_MAJOR MACOSX_BUNDLE_ID_BASE MACOSX_BUNDLE_NAME_BASE +HOTSPOT_VM_DISTRO COMPANY_NAME JDK_RC_PLATFORM_NAME PRODUCT_SUFFIX PRODUCT_NAME LAUNCHER_NAME -TEST_IN_BUILD JLINK_KEEP_PACKAGED_MODULES COPYRIGHT_YEAR COMPRESS_JARS @@ -904,6 +950,7 @@ XATTR DSYMUTIL IS_GNU_TIME PATCH +DTRACE TIME STAT HG @@ -927,20 +974,10 @@ CONF_NAME SPEC SDKROOT XCODEBUILD -BUILD_VARIANT_RELEASE -DEBUG_CLASSFILES -FASTDEBUG -VARIANT -DEBUG_LEVEL -MACOSX_UNIVERSAL -JVM_VARIANT_CORE -JVM_VARIANT_ZEROSHARK -JVM_VARIANT_ZERO -JVM_VARIANT_MINIMAL1 -JVM_VARIANT_CLIENT -JVM_VARIANT_SERVER +VALID_JVM_VARIANTS JVM_VARIANTS -JVM_INTERPRETER +DEBUG_LEVEL +HOTSPOT_DEBUG_LEVEL JDK_VARIANT SET_OPENJDK USERNAME @@ -949,16 +986,29 @@ ORIGINAL_TOPDIR TOPDIR PATH_SEP ZERO_ARCHDEF -DEFINE_CROSS_COMPILE_ARCH -LP64 -OPENJDK_TARGET_OS_EXPORT_DIR +HOTSPOT_BUILD_CPU_DEFINE +HOTSPOT_BUILD_CPU_ARCH +HOTSPOT_BUILD_CPU +HOTSPOT_BUILD_OS_TYPE +HOTSPOT_BUILD_OS +OPENJDK_BUILD_OS_EXPORT_DIR OPENJDK_BUILD_CPU_JLI_CFLAGS -OPENJDK_TARGET_CPU_JLI_CFLAGS -OPENJDK_TARGET_CPU_OSARCH -OPENJDK_TARGET_CPU_ISADIR +OPENJDK_BUILD_CPU_OSARCH +OPENJDK_BUILD_CPU_ISADIR OPENJDK_BUILD_CPU_LIBDIR OPENJDK_BUILD_CPU_LEGACY_LIB OPENJDK_BUILD_CPU_LEGACY +HOTSPOT_TARGET_CPU_DEFINE +HOTSPOT_TARGET_CPU_ARCH +HOTSPOT_TARGET_CPU +HOTSPOT_TARGET_OS_TYPE +HOTSPOT_TARGET_OS +DEFINE_CROSS_COMPILE_ARCH +LP64 +OPENJDK_TARGET_OS_EXPORT_DIR +OPENJDK_TARGET_CPU_JLI_CFLAGS +OPENJDK_TARGET_CPU_OSARCH +OPENJDK_TARGET_CPU_ISADIR OPENJDK_TARGET_CPU_LIBDIR OPENJDK_TARGET_CPU_LEGACY_LIB OPENJDK_TARGET_CPU_LEGACY @@ -1088,10 +1138,9 @@ with_target_bits enable_openjdk_only with_custom_make_dir with_jdk_variant -with_jvm_interpreter -with_jvm_variants enable_debug with_debug_level +with_jvm_variants with_devkit with_sys_root with_sysroot @@ -1107,7 +1156,6 @@ with_cacerts_file enable_unlimited_crypto with_copyright_year enable_keep_packaged_modules -enable_hotspot_test_in_build with_milestone with_update_version with_user_release_suffix @@ -1147,6 +1195,9 @@ with_native_debug_symbols enable_debug_symbols enable_zip_debug_info enable_native_coverage +enable_dtrace +with_jvm_features +with_jvm_interpreter with_stdc__lib with_msvcr_dll with_msvcp_dll @@ -1172,6 +1223,8 @@ with_lcms with_dxsdk with_dxsdk_lib with_dxsdk_include +enable_new_hotspot_build +enable_hotspot_test_in_build with_num_cores with_memory_size with_jobs @@ -1244,6 +1297,7 @@ READELF HG STAT TIME +DTRACE PATCH DSYMUTIL XATTR @@ -1923,8 +1977,6 @@ Optional Features: Enable unlimited crypto policy [disabled] --disable-keep-packaged-modules Do not keep packaged modules in jdk image [enable] - --enable-hotspot-test-in-build - run the Queens test after Hotspot build [disabled] --enable-static-build enable static library build [disabled] --disable-warnings-as-errors do not consider native warnings to be an error @@ -1936,10 +1988,18 @@ Optional Features: --enable-native-coverage enable native compilation with code coverage data[disabled] + --enable-dtrace[=yes/no/auto] + enable dtrace. Default is auto, where dtrace is + enabled if all dependencies are present. --disable-freetype-bundling disable bundling of the freetype library with the build result [enabled on Windows or when using --with-freetype, disabled otherwise] + --disable-new-hotspot-build + disable the new hotspot build system (use the old) + [enabled] + --enable-hotspot-test-in-build + run the Queens test after Hotspot build [disabled] --enable-sjavac use sjavac to do fast incremental compiles [disabled] --disable-javac-server disable javac server [enabled] @@ -1959,11 +2019,11 @@ Optional Packages: --with-custom-make-dir Deprecated. Option is kept for backwards compatibility and is ignored --with-jdk-variant JDK variant to build (normal) [normal] - --with-jvm-interpreter JVM interpreter to build (template, cpp) [template] - --with-jvm-variants JVM variants (separated by commas) to build (server, - client, minimal1, zero, zeroshark, core) [server] --with-debug-level set the debug level (release, fastdebug, slowdebug, optimized) [release] + --with-jvm-variants JVM variants (separated by commas) to build + (server,client,minimal,core,zero,zeroshark,custom) + [server] --with-devkit use this devkit for compilers, tools and resources --with-sys-root alias for --with-sysroot for backwards compatability --with-sysroot use this directory as sysroot @@ -2050,6 +2110,10 @@ Optional Packages: --with-native-debug-symbols set the native debug symbol configuration (none, internal, external, zipped) [varying] + --with-jvm-features additional JVM features to enable (separated by + comma), use '--help' to show possible values [none] + --with-jvm-interpreter Deprecated. Option is kept for backwards + compatibility and is ignored --with-stdc++lib=,, force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as @@ -2170,6 +2234,7 @@ Some influential environment variables: HG Override default value for HG STAT Override default value for STAT TIME Override default value for TIME + DTRACE Override default value for DTRACE PATCH Override default value for PATCH DSYMUTIL Override default value for DSYMUTIL XATTR Override default value for XATTR @@ -3969,6 +4034,13 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. + + # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ @@ -4093,6 +4165,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -4162,37 +4236,66 @@ pkgadd_help() { # questions. # -############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) - - - -############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then # -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. + + +############################################################################### +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. + + +############################################################################### +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features # +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. +# +############################################################################### +# Set up all JVM features for each JVM variant. +# + + +############################################################################### +# Validate JVM features once all setup is complete, including custom setup. +# + + +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. +# # @@ -4529,7 +4632,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4613,7 +4716,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4664,6 +4767,9 @@ pkgadd_help() { # +# $1 - Either TARGET or BUILD to setup the variables for. + + #%%% Build and target systems %%% @@ -4950,7 +5056,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1458755892 +DATE_WHEN_GENERATED=1460103573 ############################################################################### # @@ -4975,6 +5081,13 @@ DATE_WHEN_GENERATED=1458755892 TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -15215,6 +15328,7 @@ $as_echo "$COMPILE_TYPE" >&6; } + # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" @@ -15245,37 +15359,6 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - # Now do the same for OPENJDK_BUILD_CPU... - # Also store the legacy naming of the cpu. - # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY="i586" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_BUILD_CPU_LEGACY="amd64" - fi - - - # And the second legacy naming of the cpu. - # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then - OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" - fi - - - # This is the name of the cpu (but using i386 and amd64 instead of - # x86 and x86_64, respectively), preceeded by a /, to be used when - # locating libraries. On macosx, it's empty, though. - OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" - if test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_CPU_LIBDIR="" - fi - - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so @@ -15318,6 +15401,140 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_OS_EXPORT_DIR=macosx + else + OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + fi + + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + A_LP64="LP64:=" + # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in + # unpack200.exe + if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_ADD_LP64="-D_LP64=1" + fi + fi + LP64=$A_LP64 + + + if test "x$COMPILE_TYPE" = "xcross"; then + # FIXME: ... or should this include reduced builds..? + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + else + DEFINE_CROSS_COMPILE_ARCH="" + fi + + + # Convert openjdk platform names to hotspot names + + HOTSPOT_TARGET_OS=${OPENJDK_TARGET_OS} + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + HOTSPOT_TARGET_OS=bsd + fi + + + HOTSPOT_TARGET_OS_TYPE=${OPENJDK_TARGET_OS_TYPE} + if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then + HOTSPOT_TARGET_OS_TYPE=posix + fi + + + HOTSPOT_TARGET_CPU=${OPENJDK_TARGET_CPU} + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU=x86_32 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU=sparc + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_TARGET_CPU_ARCH=${OPENJDK_TARGET_CPU_ARCH} + + + # Setup HOTSPOT_TARGET_CPU_DEFINE + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU_DEFINE=IA32 + elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then + HOTSPOT_TARGET_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xaarch64; then + HOTSPOT_TARGET_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_TARGET_CPU" = xsparc; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xppc; then + HOTSPOT_TARGET_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_TARGET_CPU" = xs390; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + elif test "x$OPENJDK_TARGET_CPU" = ss390x; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + fi + + + + + # Also store the legacy naming of the cpu. + # Ie i586 and amd64 instead of x86 and x86_64 + OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_CPU_LEGACY="i586" + elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + # On all platforms except MacOSX replace x86_64 with amd64. + OPENJDK_BUILD_CPU_LEGACY="amd64" + fi + + + # And the second legacy naming of the cpu. + # Ie i386 and amd64 instead of x86 and x86_64. + OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_CPU_LEGACY_LIB="i386" + elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" + fi + + + # This is the name of the cpu (but using i386 and amd64 instead of + # x86 and x86_64, respectively), preceeded by a /, to be used when + # locating libraries. On macosx, it's empty, though. + OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_CPU_LIBDIR="" + fi + + + # OPENJDK_BUILD_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # /amd64 or /sparcv9. This string is appended to some library paths, like this: + # /usr/lib${OPENJDK_BUILD_CPU_ISADIR}/libexample.so + OPENJDK_BUILD_CPU_ISADIR="" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_CPU_ISADIR="/sparcv9" + fi + fi + + + # Setup OPENJDK_BUILD_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_BUILD_CPU_OSARCH="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_OS" = xlinux && test "x$OPENJDK_BUILD_CPU" = xx86; then + # On linux only, we replace x86 with i386. + OPENJDK_BUILD_CPU_OSARCH="i386" + elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + # On all platforms except macosx, we replace x86_64 with amd64. + OPENJDK_BUILD_CPU_OSARCH="amd64" + fi + + OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU" if test "x$OPENJDK_BUILD_CPU" = xx86; then OPENJDK_BUILD_CPU_JLI="i386" @@ -15336,47 +15553,90 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_BUILD_OS_EXPORT_DIR=${OPENJDK_BUILD_OS_TYPE} fi - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" - fi - fi - LP64=$A_LP64 - - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then OPENJDK_BUILD_ADD_LP64="-D_LP64=1" fi fi + LP64=$A_LP64 + if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_BUILD_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac + # Convert openjdk platform names to hotspot names + + HOTSPOT_BUILD_OS=${OPENJDK_BUILD_OS} + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + HOTSPOT_BUILD_OS=bsd + fi + + + HOTSPOT_BUILD_OS_TYPE=${OPENJDK_BUILD_OS_TYPE} + if test "x$OPENJDK_BUILD_OS_TYPE" = xunix; then + HOTSPOT_BUILD_OS_TYPE=posix + fi + + + HOTSPOT_BUILD_CPU=${OPENJDK_BUILD_CPU} + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU=x86_32 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU=sparc + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_BUILD_CPU_ARCH=${OPENJDK_BUILD_CPU_ARCH} + + + # Setup HOTSPOT_BUILD_CPU_DEFINE + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU_DEFINE=IA32 + elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then + HOTSPOT_BUILD_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xaarch64; then + HOTSPOT_BUILD_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_BUILD_CPU" = xsparc; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xppc; then + HOTSPOT_BUILD_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_BUILD_CPU" = xs390; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + elif test "x$OPENJDK_BUILD_CPU" = ss390x; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + fi + + + + + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + @@ -15915,98 +16175,6 @@ fi $as_echo "$JDK_VARIANT" >&6; } - -# Check whether --with-jvm-interpreter was given. -if test "${with_jvm_interpreter+set}" = set; then : - withval=$with_jvm_interpreter; -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which interpreter of the JVM to build" >&5 -$as_echo_n "checking which interpreter of the JVM to build... " >&6; } - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_INTERPRETER" >&5 -$as_echo "$JVM_INTERPRETER" >&6; } - - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - as_fn_error $? "The available JVM interpreters are: template, cpp" "$LINENO" 5 - fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 -$as_echo_n "checking which variants of the JVM to build... " >&6; } - -# Check whether --with-jvm-variants was given. -if test "${with_jvm_variants+set}" = set; then : - withval=$with_jvm_variants; -fi - - - if test "x$with_jvm_variants" = x; then - with_jvm_variants="server" - fi - - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` - - if test "x$TEST_VARIANTS" != "x,"; then - as_fn_error $? "The available JVM variants are: server, client, minimal1, zero, zeroshark, core" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jvm_variants" >&5 -$as_echo "$with_jvm_variants" >&6; } - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes - else - BUILDING_MULTIPLE_JVM_VARIANTS=no - fi - - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - as_fn_error $? "You cannot build multiple variants with zero." "$LINENO" 5 - fi - - - - - - - - - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" - fi - - - - DEBUG_LEVEL="release" { $as_echo "$as_me:${as_lineno-$LINENO}: checking which debug level to use" >&5 $as_echo_n "checking which debug level to use... " >&6; } @@ -16042,106 +16210,89 @@ $as_echo "$DEBUG_LEVEL" >&6; } as_fn_error $? "Allowed debug levels are: release, fastdebug, slowdebug and optimized" "$LINENO" 5 fi + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi - case $DEBUG_LEVEL in - release ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" - ;; - slowdebug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" - ;; - esac - - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. DEBUG_LEVEL="release" fi - ##### - # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... - HOTSPOT_TARGET="" - if test "x$JVM_VARIANT_SERVER" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " + + + + +# Check whether --with-jvm-variants was given. +if test "${with_jvm_variants+set}" = set; then : + withval=$with_jvm_variants; +fi + + + if test "x$with_jvm_variants" = x; then + with_jvm_variants="server" + fi + JVM_VARIANTS_OPT="$with_jvm_variants" + + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [[ "$JVM_VARIANTS_OPT" =~ "," ]] ; then + BUILDING_MULTIPLE_JVM_VARIANTS=true + else + BUILDING_MULTIPLE_JVM_VARIANTS=false + fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 +$as_echo_n "checking which variants of the JVM to build... " >&6; } + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_VARIANTS" >&5 +$as_echo "$JVM_VARIANTS" >&6; } + + # Check that the selected variants are valid + + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Unknown variant(s) specified: $INVALID_VARIANTS" >&5 +$as_echo "$as_me: Unknown variant(s) specified: $INVALID_VARIANTS" >&6;} + as_fn_error $? "The available JVM variants are: $VALID_JVM_VARIANTS" "$LINENO" 5 fi - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + as_fn_error $? "You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS." "$LINENO" 5 fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " + + + + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero fi - if test "x$JVM_VARIANT_ZERO" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " - fi - - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " - fi - - if test "x$JVM_VARIANT_CORE" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " - fi - - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" - - # On Macosx universal binaries are produced, but they only contain - # 64 bit intel. This invalidates control of which jvms are built - # from configure, but only server is valid anyway. Fix this - # when hotspot makefiles are rewritten. - if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} - fi - - ##### - - - - - - - # With basic setup done, call the custom early hook. @@ -16589,8 +16740,8 @@ $as_echo "$as_me: WARNING: Both SYSROOT and --with-sdk-name are set, only SYSROO if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 @@ -16629,7 +16780,7 @@ $as_echo_n "checking where to store configuration... " >&6; } if test "x${CONF_NAME}" = x; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default location" >&5 $as_echo "in default location" >&6; } - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5 $as_echo "in build directory with custom name" >&6; } @@ -22126,6 +22277,203 @@ $as_echo "$tool_specified" >&6; } + # Publish this variable in the help. + + + if [ -z "${DTRACE+x}" ]; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in dtrace +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DTRACE" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !DTRACE! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!DTRACE!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xDTRACE" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in dtrace +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DTRACE" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if we try to supply an empty value + if test "x$DTRACE" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool DTRACE= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool DTRACE= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + # Check if the provided tool contains a complete path. + tool_specified="$DTRACE" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool DTRACE=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool DTRACE=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$DTRACE" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool DTRACE=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool DTRACE=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool DTRACE=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + fi + + + + # Publish this variable in the help. @@ -23408,10 +23756,7 @@ fi # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then @@ -23473,22 +23818,6 @@ $as_echo "yes (default)" >&6; } - # Control wether Hotspot runs Queens test after build. - # Check whether --enable-hotspot-test-in-build was given. -if test "${enable_hotspot_test_in_build+set}" = set; then : - enableval=$enable_hotspot_test_in_build; -else - enable_hotspot_test_in_build=no -fi - - if test "x$enable_hotspot_test_in_build" = "xyes"; then - TEST_IN_BUILD=true - else - TEST_IN_BUILD=false - fi - - - # Warn user that old version arguments are deprecated. @@ -23539,6 +23868,7 @@ fi + # Override version from arguments # If --with-version-string is set, process it first. It is possible to @@ -30611,6 +30941,10 @@ fi + + + + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -46738,6 +47072,17 @@ $as_echo "yes" >&6; } fi + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + + # Setup the JTReg Regression Test Harness. @@ -47217,8 +47562,10 @@ $as_echo "no" >&6; } # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -47234,9 +47581,20 @@ $as_echo "no" >&6; } -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. COMMON_CCXXFLAGS="$COMMON_CCXXFLAGS -nologo" @@ -47402,6 +47760,10 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + elif test "x$COMPILE_TYPE" = xreduced; then if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then # Specify -m if running reduced on unix platforms @@ -47422,8 +47784,17 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check for ac_header in stdio.h @@ -47548,6 +47919,10 @@ $as_echo "$as_me: Retrying with platforms compiler target bits flag to ${COMPILE CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + # We have to unset 'ac_cv_sizeof_int_p' first, otherwise AC_CHECK_SIZEOF will use the previously cached value! unset ac_cv_sizeof_int_p @@ -47894,6 +48269,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -47919,6 +48295,10 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/$1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,$1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -47978,11 +48358,6 @@ $as_echo "$ac_cv_c_bigendian" >&6; } - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. @@ -48040,6 +48415,22 @@ $as_echo "$ac_cv_c_bigendian" >&6; } + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -48050,7 +48441,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -48325,40 +48716,59 @@ $as_echo "$supports" >&6; } CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -48368,48 +48778,75 @@ $as_echo "$supports" >&6; } if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -48424,12 +48861,16 @@ $as_echo "$supports" >&6; } ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac @@ -48445,6 +48886,12 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... if test "x$TOOLCHAIN_TYPE" = xsolstudio; then if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then @@ -48556,10 +49003,23 @@ $as_echo "$supports" >&6; } CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + CFLAGS_JDK="${CFLAGS_JDK} ${EXTRA_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK} ${EXTRA_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK} ${EXTRA_LDFLAGS}" ############################################################################### # @@ -48572,9 +49032,13 @@ $as_echo "$supports" >&6; } # CXXFLAGS_JDK - C++ Compiler flags # COMMON_CCXXFLAGS_JDK - common to C and C++ if test "x$TOOLCHAIN_TYPE" = xgcc; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT" + JVM_CFLAGS="$JVM_CFLAGS -fcheck-new" if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" @@ -49211,11 +49675,19 @@ $as_echo "$supports" >&6; } elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + JVM_CFLAGS="$JVM_CFLAGS -flimit-debug-info" if test "x$OPENJDK_TARGET_OS" = xlinux; then if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi + JVM_CFLAGS="$JVM_CFLAGS -Wno-sometimes-uninitialized" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" case $OPENJDK_TARGET_CPU_ARCH in @@ -49230,6 +49702,7 @@ $as_echo "$supports" >&6; } esac fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS="$JVM_CFLAGS -DSPARC_WORKS" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" @@ -49238,6 +49711,7 @@ $as_echo "$supports" >&6; } CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -49258,6 +49732,7 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_VERSION" = "x2010"; then STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + JVM_CFLAGS="$JVM_CFLAGS $STATIC_CPPLIB_FLAGS" fi fi @@ -49307,12 +49782,9 @@ $as_echo "$supports" >&6; } COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ + COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ + $OPENJDK_TARGET_ADD_LP64 \ -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" # Setup debug/release defines if test "x$DEBUG_LEVEL" = xrelease; then @@ -49325,10 +49797,171 @@ $as_echo "$supports" >&6; } fi # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -DLINUX" + JVM_CFLAGS="$JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS" + JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + JVM_CFLAGS="$JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" elif test "x$OPENJDK_TARGET_OS" = xbsd; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_CFLAGS="$JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + JVM_CFLAGS="$JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = xwindows-x86; then + JVM_CFLAGS="$JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + JVM_CFLAGS="$JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then + JVM_CFLAGS="$JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_TARGET_OS" != xsolaris && test "x$OPENJDK_TARGET_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + JVM_CFLAGS="$JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set JVM_CFLAGS warning handling + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + JVM_CFLAGS="$JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + JVM_CFLAGS="$JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + JVM_CFLAGS="$JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" fi # Additional macosx handling @@ -49356,43 +49989,14 @@ $as_echo "$supports" >&6; } -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - - - - - - - - - - # Flags for compiling test libraries - CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Flags for compiling test executables - CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" - CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $EXTRA_CFLAGS_JDK" + CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" @@ -49405,9 +50009,21 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + JVM_LDFLAGS="$JVM_LDFLAGS -machine:I386" + else + JVM_LDFLAGS="$JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_LDFLAGS="$JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? @@ -49415,36 +50031,57 @@ $as_echo "$supports" >&6; } if test -n "$HAS_GNU_HASH"; then LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi if test "x$OPENJDK_TARGET_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_LDFLAGS="$JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -49457,9 +50094,14 @@ $as_echo "$supports" >&6; } LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + JVM_LDFLAGS="$JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables @@ -49477,7 +50119,6 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs @@ -49492,18 +50133,24 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + if test "xTARGET" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + fi + elif test "xTARGET" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi JDKLIB_LIBS="-ljava -ljvm" @@ -49511,12 +50158,41 @@ $as_echo "$supports" >&6; } JDKLIB_LIBS="$JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" + # Set JVM_LIBS (per os) + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_LIBS="$JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + JVM_LIBS="$JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_LIBS="$JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xbsd; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_LIBS="$JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set JVM_ASFLAGS + if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_ASFLAGS="$JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_ASFLAGS="$JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" @@ -49528,6 +50204,801 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_CXXSTD_CXXFLAG="-std=gnu++98" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"" >&5 +$as_echo_n "checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"... " >&6; } + supports=yes + + saved_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAG $OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int i; +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + supports=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="$saved_cxxflags" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5 +$as_echo "$supports" >&6; } + if test "x$supports" = "xyes" ; then + : + + else + : + OPENJDK_BUILD_CXXSTD_CXXFLAG="" + fi + + + + + + + + + + + + + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_CXXSTD_CXXFLAG}" + + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CFLAGS}" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CXXFLAGS}" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_LDFLAGS}" + + ############################################################################### + # + # Now setup the CFLAGS and LDFLAGS for the JDK build. + # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. + # + + # Setup compiler/platform specific flags into + # OPENJDK_BUILD_CFLAGS_JDK - C Compiler flags + # OPENJDK_BUILD_CXXFLAGS_JDK - C++ Compiler flags + # OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK - common to C and C++ + if test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=6 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + else + : + + fi + + + + + + + + + + + + + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-sometimes-uninitialized" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSPARC_WORKS" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_BUILD_CPU_LEGACY_LIB" + fi + + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -MD -Zc:wchar_t- -W3 -wd4800 \ + -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -D_WINSOCK_DEPRECATED_NO_WARNINGS \ + -DWIN32 -DIAL" + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to + # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual + # studio. + if test "x$TOOLCHAIN_VERSION" = "x2010"; then + STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS $STATIC_CPPLIB_FLAGS" + fi + fi + + ############################################################################### + + # Adjust flags according to debug level. + case $DEBUG_LEVEL in + fastdebug | slowdebug ) + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + release ) + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + + # Setup endianness + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the + # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN + # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). + # Note: -Dmacro is the same as #define macro 1 + # -Dmacro= is the same as #define macro + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + fi + else + # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they + # are defined in the system? + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + fi + fi + + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_BUILD_OS_UPPERCASE=`$ECHO $OPENJDK_BUILD_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D$OPENJDK_BUILD_OS_UPPERCASE" + + # Setup target CPU + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_ADD_LP64 \ + -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" + + # Setup debug/release defines + if test "x$DEBUG_LEVEL" = xrelease; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRIMMED" + fi + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DDEBUG" + fi + + # Set some additional per-OS defines. + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DLINUX" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" = xwindows-x86; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_OS" != xsolaris && test "x$OPENJDK_BUILD_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set OPENJDK_BUILD_JVM_CFLAGS warning handling + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" + fi + + # Additional macosx handling + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + + # Setup some hard coded includes + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -I${JDK_TOPDIR}/src/java.base/share/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava" + + # The shared libraries are compiled using the picflag. + OPENJDK_BUILD_CFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA" + OPENJDK_BUILD_CXXFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA" + + # Executable flags + OPENJDK_BUILD_CFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK" + OPENJDK_BUILD_CXXFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK" + + + + + + + # Setup LDFLAGS et al. + # + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + LDFLAGS_MICROSOFT="-nologo -opt:ref" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_BUILD_CPU_BITS" = "x32"; then + LDFLAGS_SAFESH="-safeseh" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SAFESH" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:I386" + else + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # If this is a --hash-style=gnu system, use --hash-style=both, why? + # We have previously set HAS_GNU_HASH if this is the case + if test -n "$HAS_GNU_HASH"; then + OPENJDK_BUILD_LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_BUILD_OS" = xlinux; then + # And since we now know that the linker is gnu, then add -z defs, to forbid + # undefined symbols in object files. + LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -march=i586" + fi + case $DEBUG_LEVEL in + release ) + # tell linker to optimize libraries. + # Should this be supplied to the OSS linker as well? + LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + slowdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_NOW" = "xtrue"; then + # do relocations at load + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_NOW_FLAG" + fi + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + fastdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + LDFLAGS_SOLSTUDIO="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + LDFLAGS_CXX_SOLSTUDIO="-norunpath" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -xarch=sparc" + fi + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_XLC" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_XLC" + fi + + # Customize LDFLAGS for executables + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDK}" + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$OPENJDK_BUILD_CPU_BITS" = "x64"; then + LDFLAGS_STACK_SIZE=1048576 + else + LDFLAGS_STACK_SIZE=327680 + fi + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_LDFLAGS_JDKEXE="$OPENJDK_BUILD_LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + fi + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + # Customize LDFLAGS for libs + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDK}" + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" + OPENJDK_BUILD_JDKLIB_LIBS="" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)" + + if test "xBUILD" = "xTARGET"; then + # On some platforms (mac) the linker warns about non existing -L dirs. + # Add server first if available. Linking aginst client does not always produce the same results. + # Only add client/minimal dir if client/minimal is being built. + # Default to server for other variants. + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/minimal" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + elif test "xBUILD" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + + OPENJDK_BUILD_JDKLIB_LIBS="-ljava -ljvm" + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JDKLIB_LIBS="$OPENJDK_BUILD_JDKLIB_LIBS -lc" + fi + + fi + + # Set OPENJDK_BUILD_JVM_LIBS (per os) + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set OPENJDK_BUILD_JVM_ASFLAGS + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + + + + + + + + + + + + + + + # Tests are only ever compiled for TARGET + # Flags for compiling test libraries + CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" + CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" + + # Flags for compiling test executables + CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" + CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + + + + + + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" @@ -49535,6 +51006,7 @@ $as_echo "$supports" >&6; } + # Some Zero and Shark settings. # ZERO_ARCHFLAG tells the compiler which mode to build for case "${OPENJDK_TARGET_CPU}" in @@ -50883,6 +52355,222 @@ $as_echo "no" >&6; } +# Need toolchain to setup dtrace + + # Test for dtrace dependencies + # Check whether --enable-dtrace was given. +if test "${enable_dtrace+set}" = set; then : + enableval=$enable_dtrace; +fi + + + DTRACE_DEP_MISSING=false + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dtrace tool" >&5 +$as_echo_n "checking for dtrace tool... " >&6; } + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found, cannot build dtrace" >&5 +$as_echo "not found, cannot build dtrace" >&6; } + DTRACE_DEP_MISSING=true + fi + + for ac_header in sys/sdt.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sdt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SDT_H 1 +_ACEOF + DTRACE_HEADERS_OK=yes +else + DTRACE_HEADERS_OK=no +fi + +done + + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dtrace should be built" >&5 +$as_echo_n "checking if dtrace should be built... " >&6; } + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + + # Print a helpful message on how to acquire the necessary build dependency. + # dtrace is the help tag: freetype, cups, alsa etc + MISSING_DEPENDENCY=dtrace + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + cygwin_help $MISSING_DEPENDENCY + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + msys_help $MISSING_DEPENDENCY + else + PKGHANDLER_COMMAND= + + case $PKGHANDLER in + apt-get) + apt_help $MISSING_DEPENDENCY ;; + yum) + yum_help $MISSING_DEPENDENCY ;; + port) + port_help $MISSING_DEPENDENCY ;; + pkgutil) + pkgutil_help $MISSING_DEPENDENCY ;; + pkgadd) + pkgadd_help $MISSING_DEPENDENCY ;; + esac + + if test "x$PKGHANDLER_COMMAND" != x; then + HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." + fi + fi + + as_fn_error $? "Cannot enable dtrace with missing dependencies. See above. $HELP_MSG" "$LINENO" 5 + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, non-open linux build" >&5 +$as_echo "no, non-open linux build" >&6; } + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, dependencies present" >&5 +$as_echo "yes, dependencies present" >&6; } + fi + else + as_fn_error $? "Invalid value for --enable-dtrace: $enable_dtrace" "$LINENO" 5 + fi + + + + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + +# Check whether --with-jvm-features was given. +if test "${with_jvm_features+set}" = set; then : + withval=$with_jvm_features; +fi + + if test "x$with_jvm_features" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking additional JVM features" >&5 +$as_echo_n "checking additional JVM features... " >&6; } + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES" >&5 +$as_echo "$JVM_FEATURES" >&6; } + fi + + # Verify that dependencies are met for explicitly set features. + if [[ " $JVM_FEATURES " =~ " jvmti " ]] && ! [[ " $JVM_FEATURES " =~ " services " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmti' requires feature 'services'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " management " ]] && ! [[ " $JVM_FEATURES " =~ " nmt " ]] ; then + as_fn_error $? "Specified JVM feature 'management' requires feature 'nmt'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " jvmci " ]] && ! [[ " $JVM_FEATURES " =~ " compiler2 " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmci' requires feature 'compiler2'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " compiler2 " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'compiler2' requires feature 'all-gcs'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " vm-structs " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'vm-structs' requires feature 'all-gcs'" "$LINENO" 5 + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if [[ " $JVM_FEATURES " =~ " dtrace " ]] ; then + as_fn_error $? "To enable dtrace, you must use --enable-dtrace" "$LINENO" 5 + fi + fi + + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" + else + if [[ " $JVM_FEATURES " =~ " static-build " ]] ; then + as_fn_error $? "To enable static-build, you must use --enable-static-build" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " zero " ]] ; then + as_fn_error $? "To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " shark " ]] ; then + as_fn_error $? "To enable shark, you must use --with-jvm-variants=zeroshark" "$LINENO" 5 + fi + fi + + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" + fi + + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + + + + + + + + + + # Used for verification of Makefiles by check-jvm-feature + + + # We don't support --with-jvm-interpreter anymore, use zero instead. + + +# Check whether --with-jvm-interpreter was given. +if test "${with_jvm_interpreter+set}" = set; then : + withval=$with_jvm_interpreter; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&2;} +fi + + + + ############################################################################### # # Check dependencies for external and internal libraries. @@ -51009,7 +52697,7 @@ $as_echo "yes" >&6; } fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -51132,14 +52820,26 @@ $as_echo "$has_static_libstdcxx" >&6; } # If dynamic wasn't requested, go with static unless it isn't available. { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libstdc++" >&5 $as_echo_n "checking how to link with libstdc++... " >&6; } - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic" >&5 $as_echo "dynamic" >&6; } else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 @@ -61291,7 +62991,7 @@ $as_echo "$LIBFFI_WORKS" >&6; } - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then # Extract the first word of "llvm-config", so it can be a program name with args. set dummy llvm-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -62017,9 +63717,143 @@ fi ############################################################################### + # Check whether --enable-new-hotspot-build was given. +if test "${enable_new_hotspot_build+set}" = set; then : + enableval=$enable_new_hotspot_build; +fi + + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + + + case $HOTSPOT_DEBUG_LEVEL in + product ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + fastdebug ) + VARIANT="DBG" + FASTDEBUG="true" + DEBUG_CLASSFILES="true" + ;; + debug ) + VARIANT="DBG" + FASTDEBUG="false" + DEBUG_CLASSFILES="true" + ;; + optimized ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + esac + + + + + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + MACOSX_UNIVERSAL="true" + fi + + + + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` + + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` + + ##### + # Generate the legacy makefile targets for hotspot. + HOTSPOT_TARGET="" + + if test "x$JVM_VARIANT_SERVER" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " + fi + + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " + fi + + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " + fi + + if test "x$JVM_VARIANT_ZERO" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " + fi + + if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " + fi + + if test "x$JVM_VARIANT_CORE" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " + fi + + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" + + # On Macosx universal binaries are produced, but they only contain + # 64 bit intel. This invalidates control of which jvms are built + # from configure, but only server is valid anyway. Fix this + # when hotspot makefiles are rewritten. + if test "x$MACOSX_UNIVERSAL" = xtrue; then + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} + fi + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + # Control wether Hotspot runs Queens test after build. + # Check whether --enable-hotspot-test-in-build was given. +if test "${enable_hotspot_test_in_build+set}" = set; then : + enableval=$enable_hotspot_test_in_build; +else + enable_hotspot_test_in_build=no +fi + + if test "x$enable_hotspot_test_in_build" = "xyes"; then + TEST_IN_BUILD=true + else + TEST_IN_BUILD=false + fi + + + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + as_fn_error $? "You cannot build a custom JVM using the old hotspot build system." "$LINENO" 5 + fi + fi + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5 $as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; } @@ -63269,6 +65103,10 @@ $as_echo "no, forced" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work effectively with icecc" >&5 $as_echo "no, does not work effectively with icecc" >&6; } USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with Solaris Studio" >&5 +$as_echo "no, does not work with Solaris Studio" >&6; } + USE_PRECOMPILED_HEADER=0 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -63689,6 +65527,32 @@ $as_echo "$OUTPUT_DIR_IS_LOCAL" >&6; } # At the end, call the custom hook. (Dummy macro if no custom sources available) +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. + + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking JVM features for JVM variant '$variant'" >&5 +$as_echo_n "checking JVM features for JVM variant '$variant'... " >&6; } + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES_TO_TEST" >&5 +$as_echo "$JVM_FEATURES_TO_TEST" >&6; } + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + as_fn_error $? "Invalid JVM feature(s): $INVALID_FEATURES" "$LINENO" 5 + fi + done + + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" @@ -64912,7 +66776,7 @@ fi printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -64938,7 +66802,7 @@ fi fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index d0892c56256..e7ccdca3cf3 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -119,6 +119,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -170,6 +172,13 @@ AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -206,7 +215,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -232,7 +241,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in index 54b6ca2f9ed..50d790876a6 100644 --- a/common/autoconf/hotspot-spec.gmk.in +++ b/common/autoconf/hotspot-spec.gmk.in @@ -38,6 +38,16 @@ include $(BASE_SPEC) # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ +JVM_VARIANTS:=@JVM_VARIANTS_COMMA@ + +JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ +JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ +JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ +JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ +JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ +JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ +JVM_VARIANT_CUSTOM:=@JVM_VARIANT_HOTSPOT@ + # Legacy setting: OPT or DBG VARIANT:=@VARIANT@ # Legacy setting: true or false @@ -92,8 +102,7 @@ LLVM_LDFLAGS=@LLVM_LDFLAGS@ ALT_OUTPUTDIR=$(HOTSPOT_OUTPUTDIR) ALT_EXPORT_PATH=$(HOTSPOT_DIST) -JVM_INTERPRETER:=@JVM_INTERPRETER@ -ifeq ($(JVM_INTERPRETER), cpp) +ifeq ($(HOTSPOT_TARGET_CPU), zero) CC_INTERP=true endif diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index fe3eec0ecde..4fffa86983d 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -23,170 +23,344 @@ # questions. # -############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter -AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_INTERPRETER], -[ - AC_ARG_WITH([jvm-interpreter], [AS_HELP_STRING([--with-jvm-interpreter], - [JVM interpreter to build (template, cpp) @<:@template@:>@])]) +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" - AC_MSG_CHECKING([which interpreter of the JVM to build]) - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - AC_MSG_RESULT([$JVM_INTERPRETER]) - - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - AC_MSG_ERROR([The available JVM interpreters are: template, cpp]) - fi - - AC_SUBST(JVM_INTERPRETER) -]) +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_VARIANT], +[ [ [[ " $JVM_VARIANTS " =~ " $1 " ]] ] ]) + +############################################################################### +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_FEATURE], +[ [ [[ " $JVM_FEATURES " =~ " $1 " ]] ] ]) + +############################################################################### +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features +# AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], [ - AC_MSG_CHECKING([which variants of the JVM to build]) AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants], - [JVM variants (separated by commas) to build (server, client, minimal1, zero, zeroshark, core) @<:@server@:>@])]) + [JVM variants (separated by commas) to build (server,client,minimal,core,zero,zeroshark,custom) @<:@server@:>@])]) if test "x$with_jvm_variants" = x; then with_jvm_variants="server" fi + JVM_VARIANTS_OPT="$with_jvm_variants" - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` - - if test "x$TEST_VARIANTS" != "x,"; then - AC_MSG_ERROR([The available JVM variants are: server, client, minimal1, zero, zeroshark, core]) - fi - AC_MSG_RESULT([$with_jvm_variants]) - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) - fi - fi - - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [ [[ "$JVM_VARIANTS_OPT" =~ "," ]] ]; then + BUILDING_MULTIPLE_JVM_VARIANTS=true else - BUILDING_MULTIPLE_JVM_VARIANTS=no + BUILDING_MULTIPLE_JVM_VARIANTS=false + fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` + + AC_MSG_CHECKING([which variants of the JVM to build]) + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + AC_MSG_RESULT([$JVM_VARIANTS]) + + # Check that the selected variants are valid + + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + AC_MSG_NOTICE([Unknown variant(s) specified: $INVALID_VARIANTS]) + AC_MSG_ERROR([The available JVM variants are: $VALID_JVM_VARIANTS]) fi - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - AC_MSG_ERROR([You cannot build multiple variants with zero.]) + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + AC_MSG_ERROR([You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS.]) fi AC_SUBST(JVM_VARIANTS) - AC_SUBST(JVM_VARIANT_SERVER) - AC_SUBST(JVM_VARIANT_CLIENT) - AC_SUBST(JVM_VARIANT_MINIMAL1) - AC_SUBST(JVM_VARIANT_ZERO) - AC_SUBST(JVM_VARIANT_ZEROSHARK) - AC_SUBST(JVM_VARIANT_CORE) + AC_SUBST(VALID_JVM_VARIANTS) + + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero + fi +]) + +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE], +[ + # Test for dtrace dependencies + AC_ARG_ENABLE([dtrace], [AS_HELP_STRING([--enable-dtrace@<:@=yes/no/auto@:>@], + [enable dtrace. Default is auto, where dtrace is enabled if all dependencies + are present.])]) + + DTRACE_DEP_MISSING=false + + AC_MSG_CHECKING([for dtrace tool]) + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + AC_MSG_RESULT([$DTRACE]) + else + AC_MSG_RESULT([not found, cannot build dtrace]) + DTRACE_DEP_MISSING=true + fi + + AC_CHECK_HEADERS([sys/sdt.h], [DTRACE_HEADERS_OK=yes],[DTRACE_HEADERS_OK=no]) + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + AC_MSG_CHECKING([if dtrace should be built]) + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + AC_MSG_RESULT([no, missing dependencies]) + HELP_MSG_MISSING_DEPENDENCY([dtrace]) + AC_MSG_ERROR([Cannot enable dtrace with missing dependencies. See above. $HELP_MSG]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, forced]) + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, forced]) + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, non-open linux build]) + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, missing dependencies]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, dependencies present]) + fi + else + AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace]) + fi + AC_SUBST(INCLUDE_DTRACE) +]) + +############################################################################### +# Set up all JVM features for each JVM variant. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], +[ + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + AC_ARG_WITH([jvm-features], [AS_HELP_STRING([--with-jvm-features], + [additional JVM features to enable (separated by comma), use '--help' to show possible values @<:@none@:>@])]) + if test "x$with_jvm_features" != x; then + AC_MSG_CHECKING([additional JVM features]) + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + AC_MSG_RESULT([$JVM_FEATURES]) + fi + + # Verify that dependencies are met for explicitly set features. + if HOTSPOT_CHECK_JVM_FEATURE(jvmti) && ! HOTSPOT_CHECK_JVM_FEATURE(services); then + AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(management) && ! HOTSPOT_CHECK_JVM_FEATURE(nmt); then + AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(jvmci) && ! HOTSPOT_CHECK_JVM_FEATURE(compiler2); then + AC_MSG_ERROR([Specified JVM feature 'jvmci' requires feature 'compiler2']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(compiler2) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'compiler2' requires feature 'all-gcs']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(vm-structs) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'vm-structs' requires feature 'all-gcs']) + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if HOTSPOT_CHECK_JVM_FEATURE(dtrace); then + AC_MSG_ERROR([To enable dtrace, you must use --enable-dtrace]) + fi + fi + + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" + else + if HOTSPOT_CHECK_JVM_FEATURE(static-build); then + AC_MSG_ERROR([To enable static-build, you must use --enable-static-build]) + fi + fi + + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(zero); then + AC_MSG_ERROR([To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark]) + fi + fi + + if ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(shark); then + AC_MSG_ERROR([To enable shark, you must use --with-jvm-variants=zeroshark]) + fi + fi + + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" + fi + + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + + AC_SUBST(JVM_FEATURES_server) + AC_SUBST(JVM_FEATURES_client) + AC_SUBST(JVM_FEATURES_core) + AC_SUBST(JVM_FEATURES_minimal) + AC_SUBST(JVM_FEATURES_zero) + AC_SUBST(JVM_FEATURES_zeroshark) + AC_SUBST(JVM_FEATURES_custom) + + # Used for verification of Makefiles by check-jvm-feature + AC_SUBST(VALID_JVM_FEATURES) + + # We don't support --with-jvm-interpreter anymore, use zero instead. + BASIC_DEPRECATED_ARG_WITH(jvm-interpreter) +]) + +############################################################################### +# Validate JVM features once all setup is complete, including custom setup. +# +AC_DEFUN_ONCE([HOTSPOT_VALIDATE_JVM_FEATURES], +[ + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + AC_MSG_CHECKING([JVM features for JVM variant '$variant']) + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + AC_MSG_RESULT([$JVM_FEATURES_TO_TEST]) + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + AC_MSG_ERROR([Invalid JVM feature(s): $INVALID_FEATURES]) + fi + done +]) + +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_LEGACY_BUILD], +[ + AC_ARG_ENABLE(new-hotspot-build, [AS_HELP_STRING([--disable-new-hotspot-build], + [disable the new hotspot build system (use the old) @<:@enabled@:>@])]) + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + AC_SUBST(USE_NEW_HOTSPOT_BUILD) + + case $HOTSPOT_DEBUG_LEVEL in + product ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + fastdebug ) + VARIANT="DBG" + FASTDEBUG="true" + DEBUG_CLASSFILES="true" + ;; + debug ) + VARIANT="DBG" + FASTDEBUG="false" + DEBUG_CLASSFILES="true" + ;; + optimized ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + esac + AC_SUBST(VARIANT) + AC_SUBST(FASTDEBUG) + AC_SUBST(DEBUG_CLASSFILES) if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then MACOSX_UNIVERSAL="true" fi AC_SUBST(MACOSX_UNIVERSAL) -]) + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` -############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. -# -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts -# -AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], -[ - case $DEBUG_LEVEL in - release ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" - ;; - slowdebug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" - ;; - esac - - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. - if test "x$DEBUG_LEVEL" = xoptimized; then - DEBUG_LEVEL="release" - fi + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` ##### # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... HOTSPOT_TARGET="" if test "x$JVM_VARIANT_SERVER" = xtrue; then @@ -213,27 +387,19 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " fi - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" # On Macosx universal binaries are produced, but they only contain # 64 bit intel. This invalidates control of which jvms are built # from configure, but only server is valid anyway. Fix this # when hotspot makefiles are rewritten. if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} fi - ##### + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + AC_SUBST(HOTSPOT_MAKE_ARGS) - AC_SUBST(DEBUG_LEVEL) - AC_SUBST(VARIANT) - AC_SUBST(FASTDEBUG) - AC_SUBST(DEBUG_CLASSFILES) - AC_SUBST(BUILD_VARIANT_RELEASE) -]) - -AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], -[ # Control wether Hotspot runs Queens test after build. AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build], [run the Queens test after Hotspot build @<:@disabled@:>@])],, @@ -244,10 +410,29 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], TEST_IN_BUILD=false fi AC_SUBST(TEST_IN_BUILD) -]) -AC_DEFUN_ONCE([HOTSPOT_SETUP_BUILD_TWEAKS], -[ - HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" - AC_SUBST(HOTSPOT_MAKE_ARGS) + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + AC_MSG_ERROR([You cannot build a custom JVM using the old hotspot build system.]) + fi + fi + + AC_SUBST(JVM_VARIANTS_COMMA) + AC_SUBST(JVM_VARIANT_SERVER) + AC_SUBST(JVM_VARIANT_CLIENT) + AC_SUBST(JVM_VARIANT_MINIMAL1) + AC_SUBST(JVM_VARIANT_HOTSPOT) + AC_SUBST(JVM_VARIANT_ZERO) + AC_SUBST(JVM_VARIANT_ZEROSHARK) + AC_SUBST(JVM_VARIANT_CORE) ]) diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 3c677d8adde..0b45cbc877e 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -81,6 +81,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL], test "x$DEBUG_LEVEL" != xslowdebug; then AC_MSG_ERROR([Allowed debug levels are: release, fastdebug, slowdebug and optimized]) fi + + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi + + if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. + DEBUG_LEVEL="release" + fi + + AC_SUBST(HOTSPOT_DEBUG_LEVEL) + AC_SUBST(DEBUG_LEVEL) ]) ############################################################################### @@ -178,10 +203,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then diff --git a/common/autoconf/jdk-version.m4 b/common/autoconf/jdk-version.m4 index 2dc63865c49..3b2fbfb60f1 100644 --- a/common/autoconf/jdk-version.m4 +++ b/common/autoconf/jdk-version.m4 @@ -72,6 +72,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(PRODUCT_SUFFIX) AC_SUBST(JDK_RC_PLATFORM_NAME) AC_SUBST(COMPANY_NAME) + AC_SUBST(HOTSPOT_VM_DISTRO) AC_SUBST(MACOSX_BUNDLE_NAME_BASE) AC_SUBST(MACOSX_BUNDLE_ID_BASE) diff --git a/common/autoconf/lib-std.m4 b/common/autoconf/lib-std.m4 index d3f94609630..6fa0b4844af 100644 --- a/common/autoconf/lib-std.m4 +++ b/common/autoconf/lib-std.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -88,13 +88,25 @@ AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS], # If dynamic was requested, it's available since it would fail above otherwise. # If dynamic wasn't requested, go with static unless it isn't available. AC_MSG_CHECKING([how to link with libstdc++]) - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" AC_MSG_RESULT([dynamic]) else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" AC_MSG_RESULT([static]) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index a6a8bd4f19b..e1e91d678d6 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -74,7 +74,7 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -102,7 +102,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], ################################################################################ AC_DEFUN_ONCE([LIB_SETUP_LLVM], [ - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then AC_CHECK_PROG([LLVM_CONFIG], [llvm-config], [llvm-config]) if test "x$LLVM_CONFIG" != xllvm-config; then diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index fe5a201ecd9..587f80dbcd5 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -273,169 +273,169 @@ AC_DEFUN([PLATFORM_SETUP_TARGET_CPU_BITS], # Setup the legacy variables, for controlling the old makefiles. # AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS], +[ + PLATFORM_SETUP_LEGACY_VARS_HELPER([TARGET]) + PLATFORM_SETUP_LEGACY_VARS_HELPER([BUILD]) + + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + AC_SUBST(ZERO_ARCHDEF) + +]) + +# $1 - Either TARGET or BUILD to setup the variables for. +AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], [ # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY="i586" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY="i586" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_TARGET_CPU_LEGACY="amd64" + OPENJDK_$1_CPU_LEGACY="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY) + AC_SUBST(OPENJDK_$1_CPU_LEGACY) # And the second legacy naming of the cpu. # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_TARGET_CPU_LEGACY_LIB="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_LEGACY_LIB="amd64" + OPENJDK_$1_CPU_LEGACY_LIB="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY_LIB="i386" + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY_LIB="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY_LIB) + AC_SUBST(OPENJDK_$1_CPU_LEGACY_LIB) # This is the name of the cpu (but using i386 and amd64 instead of # x86 and x86_64, respectively), preceeded by a /, to be used when # locating libraries. On macosx, it's empty, though. - OPENJDK_TARGET_CPU_LIBDIR="/$OPENJDK_TARGET_CPU_LEGACY_LIB" - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_CPU_LIBDIR="" + OPENJDK_$1_CPU_LIBDIR="/$OPENJDK_$1_CPU_LEGACY_LIB" + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_CPU_LIBDIR="" fi - AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR) + AC_SUBST(OPENJDK_$1_CPU_LIBDIR) - # Now do the same for OPENJDK_BUILD_CPU... - # Also store the legacy naming of the cpu. - # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY="i586" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_BUILD_CPU_LEGACY="amd64" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY) - - # And the second legacy naming of the cpu. - # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then - OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY_LIB) - - # This is the name of the cpu (but using i386 and amd64 instead of - # x86 and x86_64, respectively), preceeded by a /, to be used when - # locating libraries. On macosx, it's empty, though. - OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" - if test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_CPU_LIBDIR="" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LIBDIR) - - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # OPENJDK_$1_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: - # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so - OPENJDK_TARGET_CPU_ISADIR="" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_ISADIR="/amd64" - elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then - OPENJDK_TARGET_CPU_ISADIR="/sparcv9" + # /usr/lib${OPENJDK_$1_CPU_ISADIR}/libexample.so + OPENJDK_$1_CPU_ISADIR="" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + OPENJDK_$1_CPU_ISADIR="/sparcv9" fi fi - AC_SUBST(OPENJDK_TARGET_CPU_ISADIR) + AC_SUBST(OPENJDK_$1_CPU_ISADIR) - # Setup OPENJDK_TARGET_CPU_OSARCH, which is used to set the os.arch Java system property - OPENJDK_TARGET_CPU_OSARCH="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xx86; then + # Setup OPENJDK_$1_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_$1_CPU_OSARCH="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_OS" = xlinux && test "x$OPENJDK_$1_CPU" = xx86; then # On linux only, we replace x86 with i386. - OPENJDK_TARGET_CPU_OSARCH="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_OSARCH="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_OSARCH="amd64" + OPENJDK_$1_CPU_OSARCH="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_OSARCH) + AC_SUBST(OPENJDK_$1_CPU_OSARCH) - OPENJDK_TARGET_CPU_JLI="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_JLI="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_JLI="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_JLI="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_JLI="amd64" + OPENJDK_$1_CPU_JLI="amd64" fi # Now setup the -D flags for building libjli. - OPENJDK_TARGET_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_TARGET_CPU_JLI\"'" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" + OPENJDK_$1_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_$1_CPU_JLI\"'" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU_ARCH" = xsparc; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" + elif test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" fi fi - AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS) + AC_SUBST(OPENJDK_$1_CPU_JLI_CFLAGS) - OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_JLI="i386" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_BUILD_CPU_JLI="amd64" - fi - # Now setup the -D flags for building libjli. - OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'" - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" - fi - fi - AC_SUBST(OPENJDK_BUILD_CPU_JLI_CFLAGS) - - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_$1_OS_EXPORT_DIR=${OPENJDK_$1_OS_TYPE} fi - AC_SUBST(OPENJDK_TARGET_OS_EXPORT_DIR) + AC_SUBST(OPENJDK_$1_OS_EXPORT_DIR) - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" + if test "x$OPENJDK_$1_OS" = xlinux || test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_ADD_LP64="-D_LP64=1" fi fi AC_SUBST(LP64,$A_LP64) - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then - if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_ADD_LP64="-D_LP64=1" - fi - fi if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_$1_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi AC_SUBST(DEFINE_CROSS_COMPILE_ARCH) - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac - AC_SUBST(ZERO_ARCHDEF) + # Convert openjdk platform names to hotspot names + + HOTSPOT_$1_OS=${OPENJDK_$1_OS} + if test "x$OPENJDK_$1_OS" = xmacosx; then + HOTSPOT_$1_OS=bsd + fi + AC_SUBST(HOTSPOT_$1_OS) + + HOTSPOT_$1_OS_TYPE=${OPENJDK_$1_OS_TYPE} + if test "x$OPENJDK_$1_OS_TYPE" = xunix; then + HOTSPOT_$1_OS_TYPE=posix + fi + AC_SUBST(HOTSPOT_$1_OS_TYPE) + + HOTSPOT_$1_CPU=${OPENJDK_$1_CPU} + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU=x86_32 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU=sparc + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU=ppc_64 + fi + AC_SUBST(HOTSPOT_$1_CPU) + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_$1_CPU_ARCH=${OPENJDK_$1_CPU_ARCH} + AC_SUBST(HOTSPOT_$1_CPU_ARCH) + + # Setup HOTSPOT_$1_CPU_DEFINE + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU_DEFINE=IA32 + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + HOTSPOT_$1_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xaarch64; then + HOTSPOT_$1_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_$1_CPU" = xsparc; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xppc; then + HOTSPOT_$1_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_$1_CPU" = xs390; then + HOTSPOT_$1_CPU_DEFINE=S390 + elif test "x$OPENJDK_$1_CPU" = ss390x; then + HOTSPOT_$1_CPU_DEFINE=S390 + fi + AC_SUBST(HOTSPOT_$1_CPU_DEFINE) + ]) AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], @@ -521,6 +521,10 @@ AC_DEFUN([PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS], CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" ]) AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], @@ -542,6 +546,11 @@ AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check AC_CHECK_HEADERS([stdio.h], , [ diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 0af5e6d0e2d..a30346427a2 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -82,6 +82,13 @@ OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@ OPENJDK_TARGET_CPU_JLI_CFLAGS:=@OPENJDK_TARGET_CPU_JLI_CFLAGS@ OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@ +HOTSPOT_TARGET_OS := @HOTSPOT_TARGET_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_TARGET_OS_TYPE@ + +HOTSPOT_TARGET_CPU := @HOTSPOT_TARGET_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@ + # We are building on this build system. # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ @@ -192,6 +199,7 @@ PRODUCT_NAME:=@PRODUCT_NAME@ PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@ JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@ COMPANY_NAME:=@COMPANY_NAME@ +HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@ MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@ MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@ USERNAME:=@USERNAME@ @@ -201,11 +209,32 @@ RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX) # How to compile the code: release, fastdebug or slowdebug DEBUG_LEVEL:=@DEBUG_LEVEL@ +HOTSPOT_DEBUG_LEVEL:=@HOTSPOT_DEBUG_LEVEL@ # This is the JDK variant to build. # The JDK variant is a name for a specific set of modules to be compiled for the JDK. JDK_VARIANT:=@JDK_VARIANT@ +# Which JVM variants to build (space-separated list) +JVM_VARIANTS := @JVM_VARIANTS@ + +# Lists of features per variant. Only relevant for the variants listed in +# JVM_VARIANTS. +JVM_FEATURES_server := @JVM_FEATURES_server@ +JVM_FEATURES_client := @JVM_FEATURES_client@ +JVM_FEATURES_core := @JVM_FEATURES_core@ +JVM_FEATURES_minimal := @JVM_FEATURES_minimal@ +JVM_FEATURES_zero := @JVM_FEATURES_zero@ +JVM_FEATURES_zeroshark := @JVM_FEATURES_zeroshark@ +JVM_FEATURES_custom := @JVM_FEATURES_custom@ + +# Used for make-time verifications +VALID_JVM_FEATURES := @VALID_JVM_FEATURES@ +VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@ + +# Control use of precompiled header in hotspot libjvm build +USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ + # Should we compile support for running with a graphical UI? (ie headful) # Should we compile support for running without? (ie headless) SUPPORT_HEADFUL:=@SUPPORT_HEADFUL@ @@ -213,25 +242,11 @@ SUPPORT_HEADLESS:=@SUPPORT_HEADLESS@ # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ -# These are the libjvms that we want to build. -# The java launcher uses the default. -# The others can be selected by specifying -client -server -minimal1 -zero or -zeroshark -# on the java launcher command line. -JVM_VARIANTS:=@JVM_VARIANTS@ -JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ -JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ -JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ -JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ -JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ -JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ +# Legacy support +USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@ -# Universal binaries on macosx MACOSX_UNIVERSAL=@MACOSX_UNIVERSAL@ -# Legacy setting: -debug or -fastdebug -# Still used in version string... -BUILD_VARIANT_RELEASE:=@BUILD_VARIANT_RELEASE@ - # JDK_OUTPUTDIR specifies where a working jvm is built. # You can run $(JDK_OUTPUTDIR)/bin/java # Though the layout of the contents of $(JDK_OUTPUTDIR) is not @@ -318,6 +333,11 @@ MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ # Toolchain type: gcc, clang, solstudio, lxc, microsoft... TOOLCHAIN_TYPE:=@TOOLCHAIN_TYPE@ TOOLCHAIN_VERSION := @TOOLCHAIN_VERSION@ +CC_VERSION_NUMBER := @CC_VERSION_NUMBER@ +CXX_VERSION_NUMBER := @CXX_VERSION_NUMBER@ + +# Legacy support +HOTSPOT_TOOLCHAIN_TYPE := @HOTSPOT_TOOLCHAIN_TYPE@ # Option used to tell the compiler whether to create 32- or 64-bit executables COMPILER_TARGET_BITS_FLAG:=@COMPILER_TARGET_BITS_FLAG@ @@ -336,14 +356,18 @@ LD_OUT_OPTION:=@LD_OUT_OPTION@ AR_OUT_OPTION:=@AR_OUT_OPTION@ # Flags used for overriding the default opt setting for a C/C++ source file. +C_O_FLAG_HIGHEST_JVM:=@C_O_FLAG_HIGHEST_JVM@ C_O_FLAG_HIGHEST:=@C_O_FLAG_HIGHEST@ C_O_FLAG_HI:=@C_O_FLAG_HI@ C_O_FLAG_NORM:=@C_O_FLAG_NORM@ C_O_FLAG_NONE:=@C_O_FLAG_NONE@ +C_O_FLAG_SIZE:=@C_O_FLAG_SIZE@ +CXX_O_FLAG_HIGHEST_JVM:=@CXX_O_FLAG_HIGHEST_JVM@ CXX_O_FLAG_HIGHEST:=@CXX_O_FLAG_HIGHEST@ CXX_O_FLAG_HI:=@CXX_O_FLAG_HI@ CXX_O_FLAG_NORM:=@CXX_O_FLAG_NORM@ CXX_O_FLAG_NONE:=@CXX_O_FLAG_NONE@ +CXX_O_FLAG_SIZE:=@CXX_O_FLAG_SIZE@ C_FLAG_DEPS:=@C_FLAG_DEPS@ CXX_FLAG_DEPS:=@CXX_FLAG_DEPS@ @@ -372,6 +396,23 @@ CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@ LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@ +JVM_CFLAGS := @JVM_CFLAGS@ +JVM_CFLAGS_SYMBOLS := @JVM_CFLAGS_SYMBOLS@ +JVM_LDFLAGS := @JVM_LDFLAGS@ +JVM_ASFLAGS := @JVM_ASFLAGS@ +JVM_LIBS := @JVM_LIBS@ +JVM_RCFLAGS := @JVM_RCFLAGS@ + +# Flags for zeroshark +LLVM_CFLAGS := @LLVM_CFLAGS@ +LLVM_LIBS := @LLVM_LIBS@ +LLVM_LDFLAGS := @LLVM_LDFLAGS@ + +# These flags might contain variables set by a custom extension that is included later. +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ +EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ + CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ CPP:=@FIXPATH@ @CPP@ @@ -628,6 +669,7 @@ XATTR:=@XATTR@ JT_HOME:=@JT_HOME@ JTREGEXE:=@JTREGEXE@ XCODEBUILD=@XCODEBUILD@ +DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ # Build setup diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 263c0a8ff2c..7e7a07c5d8b 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -930,6 +930,17 @@ AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS], rm -rf version-script.map main.c a.out fi AC_SUBST(USING_BROKEN_SUSE_LD) + + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + AC_SUBST(HOTSPOT_TOOLCHAIN_TYPE) ]) # Setup the JTReg Regression Test Harness. diff --git a/common/autoconf/version-numbers b/common/autoconf/version-numbers index dcde2286a29..98f106680b5 100644 --- a/common/autoconf/version-numbers +++ b/common/autoconf/version-numbers @@ -32,6 +32,7 @@ PRODUCT_NAME=OpenJDK PRODUCT_SUFFIX="Runtime Environment" JDK_RC_PLATFORM_NAME=Platform COMPANY_NAME=N/A +HOTSPOT_VM_DISTRO="OpenJDK" # Might need better names for these MACOSX_BUNDLE_NAME_BASE="OpenJDK" diff --git a/common/bin/compare.sh b/common/bin/compare.sh index d073fbbda32..0447334042e 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -732,6 +732,13 @@ compare_bin_file() { SYM_SORT_CMD="cat" fi + if [ -n "$SYMBOLS_DIFF_FILTER" ] && [ -z "$NEED_SYMBOLS_DIFF_FILTER" ] \ + || [[ "$NEED_SYMBOLS_DIFF_FILTER" = *"$BIN_FILE"* ]]; then + this_SYMBOLS_DIFF_FILTER="$SYMBOLS_DIFF_FILTER" + else + this_SYMBOLS_DIFF_FILTER="$CAT" + fi + # Check symbols if [ "$OPENJDK_TARGET_OS" = "windows" ]; then # The output from dumpbin on windows differs depending on if the debug symbol @@ -750,8 +757,16 @@ compare_bin_file() { $NM -j $ORIG_OTHER_FILE 2> /dev/null | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other $NM -j $ORIG_THIS_FILE 2> /dev/null | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this else - $NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other - $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this + $NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME \ + | $AWK '{print $2, $3, $4, $5}' \ + | eval "$this_SYMBOLS_DIFF_FILTER" \ + | $SYM_SORT_CMD \ + > $WORK_FILE_BASE.symbols.other + $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME \ + | $AWK '{print $2, $3, $4, $5}' \ + | eval "$this_SYMBOLS_DIFF_FILTER" \ + | $SYM_SORT_CMD \ + > $WORK_FILE_BASE.symbols.this fi LC_ALL=C $DIFF $WORK_FILE_BASE.symbols.other $WORK_FILE_BASE.symbols.this > $WORK_FILE_BASE.symbols.diff @@ -828,9 +843,10 @@ compare_bin_file() { FULLDUMP_DIFF_FILTER="$CAT" fi $FULLDUMP_CMD $OTHER_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \ - > $WORK_FILE_BASE.fulldump.other 2>&1 + > $WORK_FILE_BASE.fulldump.other 2>&1 & $FULLDUMP_CMD $THIS_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \ - > $WORK_FILE_BASE.fulldump.this 2>&1 + > $WORK_FILE_BASE.fulldump.this 2>&1 & + wait LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this \ > $WORK_FILE_BASE.fulldump.diff @@ -854,18 +870,19 @@ compare_bin_file() { FULLDUMP_MSG=" " DIFF_FULLDUMP= if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then - FULLDUMP_MSG=" ! " + FULLDUMP_MSG=" ! " fi fi fi # Compare disassemble output if [ -n "$DIS_CMD" ] && [ -z "$SKIP_DIS_DIFF" ]; then - # By default we filter out differences that include references to symbols. - # To get a raw diff with the complete disassembly, set - # DIS_DIFF_FILTER="$CAT" - if [ -z "$DIS_DIFF_FILTER" ]; then - DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$' | $SED -r -e 's/(\b|x)([0-9a-fA-F]+)(\b|:|>)/X/g'" + this_DIS_DIFF_FILTER="$CAT" + if [ -n "$DIS_DIFF_FILTER" ]; then + if [ -z "$NEED_DIS_DIFF_FILTER" ] \ + || [[ "$NEED_DIS_DIFF_FILTER" = *"$BIN_FILE"* ]]; then + this_DIS_DIFF_FILTER="$DIS_DIFF_FILTER" + fi fi if [ "$OPENJDK_TARGET_OS" = "windows" ]; then DIS_GREP_ARG=-a @@ -873,9 +890,10 @@ compare_bin_file() { DIS_GREP_ARG= fi $DIS_CMD $OTHER_FILE | $GREP $DIS_GREP_ARG -v $NAME \ - | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1 + | eval "$this_DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1 & $DIS_CMD $THIS_FILE | $GREP $DIS_GREP_ARG -v $NAME \ - | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1 + | eval "$this_DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1 & + wait LC_ALL=C $DIFF $WORK_FILE_BASE.dis.other $WORK_FILE_BASE.dis.this > $WORK_FILE_BASE.dis.diff @@ -884,11 +902,15 @@ compare_bin_file() { DIS_MSG=$($PRINTF "%8d" $DIS_DIFF_SIZE) if [[ "$ACCEPTED_DIS_DIFF" != *"$BIN_FILE"* ]]; then DIFF_DIS=true - if [[ "$KNOWN_DIS_DIFF" != *"$BIN_FILE"* ]]; then + if [ "$MAX_KNOWN_DIS_DIFF_SIZE" = "" ]; then + MAX_KNOWN_DIS_DIFF_SIZE="0" + fi + if [[ "$KNOWN_DIS_DIFF" = *"$BIN_FILE"* ]] \ + && [ "$DIS_DIFF_SIZE" -lt "$MAX_KNOWN_DIS_DIFF_SIZE" ]; then + DIS_MSG=" $DIS_MSG " + else DIS_MSG="*$DIS_MSG*" REGRESSIONS=true - else - DIS_MSG=" $DIS_MSG " fi else DIS_MSG="($DIS_MSG)" diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index 30ae49c6fc1..9a6f85fb734 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -113,21 +113,36 @@ if [ "$OPENJDK_TARGET_OS" = "linux" ]; then ./bin/xjc " - # Issue with __FILE__ usage in generated header files prevent clean fulldump diff of - # server jvm with old hotspot build. - KNOWN_FULLDUMP_DIFF=" - ./lib$OPENJDK_TARGET_CPU_LIBDIR/client/libjvm.so - ./lib$OPENJDK_TARGET_CPU_LIBDIR/server/libjvm.so - ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so - " - - if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then - KNOWN_DIS_DIFF=" - ./lib$OPENJDK_TARGET_CPU_LIBDIR/server/libjvm.so + if [ "$OPENJDK_TARGET_CPU" = "arm" ]; then + # NOTE: When comparing the old and new hotspot builds, the link time + # optimization makes good comparisons impossible. Fulldump compare always + # fails and disassembly can end up with some functions in different order. + # So for now, accept the difference but put a limit on the size. The + # different order of functions shouldn't result in a very big diff. + KNOWN_FULLDUMP_DIFF=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + + # Link time optimization adds random numbers to symbol names + NEED_DIS_DIFF_FILTER=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + DIS_DIFF_FILTER="$SED -r \ + -e 's/\.[0-9]+/.X/g' \ + -e 's/\t[0-9a-f]{4} [0-9a-f]{4} /\tXXXX XXXX /' \ + -e 's/\t[0-9a-f]{5,} /\t /' \ + " + KNOWN_DIS_DIFF=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + MAX_KNOWN_DIS_DIFF_SIZE="3000" + + NEED_SYMBOLS_DIFF_FILTER=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + SYMBOLS_DIFF_FILTER="$SED -r \ + -e 's/\.[0-9]+/.X/g' " - DIS_DIFF_FILTER="$SED \ - -e 's/\(:\t\)\([0-9a-z]\{2,2\} \)\{1,7\}/\1/g' \ - -e 's/0x[0-9a-z]\{2,9\}//g'" fi fi @@ -250,15 +265,10 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; SKIP_FULLDUMP_DIFF="true" - # Filter random C++ symbol strings. - # Some numbers differ randomly. + # Random strings looking like this differ: <.XAKoKoPIac2W0OA. DIS_DIFF_FILTER="$SED \ - -e 's/\.[a-zA-Z0-9_\$]\{15\}//g' \ - -e 's/\(\# \)[0-9a-f]*\( <\)/\1\2/g' \ - -e 's/0x[0-9a-f]*$//g' \ - -e 's/0x[0-9a-f]*\([,(>]\)/\1/g' \ - -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /g' \ - -e 's/ [\.A-Za-z0-9%@]\{16\}$/ /g'" + -e 's/<\.[A-Za-z0-9]\{\15}\./<.SYM./' \ + " fi @@ -380,23 +390,18 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "sparcv9" ] ./bin/xjc " - # Some numbers differ randomly. DIS_DIFF_FILTER="$SED \ - -e 's/\$[a-zA-Z0-9_\$]\{15\}//g' \ - -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /g' \ - -e 's/, [0-9a-fx\-]\{1,8\}/, /g' \ - -e 's/call [0-9a-f]\{7\}/call /g' \ + -e 's/^[0-9a-f]\{16\}/:/' \ + -e 's/^ *[0-9a-f]\{3,8\}:/ :/' \ + -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /' \ + -e 's/\$[a-zA-Z0-9_\$]\{15\}\././' \ -e 's/0x[0-9a-f]\{1,8\}//g' \ - -e 's/\! [0-9a-f]\{1,8\} /! /g'" + -e 's/\! [0-9a-f]\{1,8\} /! /' \ + -e 's/, [0-9a-fx\-]\{1,8\}/, /g' \ + -e 's/call [0-9a-f]\{4,7\}/call /' \ + " - # libjvm.so - # __FILE__ macro usage in debug.hpp causes differences between old and new - # hotspot builds in ad_sparc.o and ad_sparc_clone.o. The .o files compare - # equal when stripped, but at link time differences appear. Removing - # __FILE__ from ShouldNotCallThis() and ShouldNotReachHere() removes - # the differences. KNOWN_DIS_DIFF=" - ./lib/sparcv9/server/libjvm.so ./lib/sparcv9/libsaproc.so " @@ -419,6 +424,7 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then ./demo/jvmti/minst/lib/minst.dll ./bin/attach.dll ./bin/jsoundds.dll + ./bin/client/jvm.dll ./bin/server/jvm.dll ./bin/appletviewer.exe ./bin/idlj.exe @@ -469,22 +475,39 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then ./bin/jabswitch.exe " - # On windows, there are unavoidable allignment issues making - # a perfect disasm diff impossible. Filter out the following: - # * Random parts of C++ symbols (this is a bit greedy, but does the trick) - # @XXXXX - # * Hexadecimal addresses that are sometimes alligned differently. - # * Dates in version strings XXXX_XX_XX. - DIS_DIFF_FILTER="$SED \ - -e 's/^ [0-9A-F]\{16\}: //g' \ - -e 's/[@?][A-Za-z0-9_]\{1,25\}//g' \ - -e 's/\([\[+]\)[0-9A-F]\{4,16\}h\]/\1]/g' \ - -e 's/_[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}/_/g'" - #DIS_DIFF_FILTER="$CAT" + if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then + DIS_DIFF_FILTER="$SED -r \ + -e 's/^ [0-9A-F]{16}: //' \ + -e 's/^ [0-9A-F]{8}: / : /' \ + -e 's/(offset \?\?)_C@_.*/\1/' \ + -e 's/[@?][A-Za-z0-9_]{1,25}//' \ + -e 's/([-,+])[0-9A-F]{2,16}/\1/g' \ + -e 's/\[[0-9A-F]{4,16}h\]/[]/' \ + -e 's/: ([a-z]{2}[a-z ]{2}) [0-9A-F]{2,16}h?$/: \1 /' \ + -e 's/_20[0-9]{2}_[0-1][0-9]_[0-9]{2}/_/' \ + " + elif [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then + DIS_DIFF_FILTER="$SED -r \ + -e 's/^ [0-9A-F]{16}: //' \ + -e 's/\[[0-9A-F]{4,16}h\]/[]/' \ + -e 's/([,+])[0-9A-F]{2,16}h/\1/' \ + -e 's/([a-z]{2}[a-z ]{2}) [0-9A-F]{4,16}$/\1 /' \ + -e 's/\[\?\?_C@_.*/[]/' \ + " + fi SKIP_BIN_DIFF="true" SKIP_FULLDUMP_DIFF="true" + # NOTE: When comparing the old and new hotspot builds, the server jvm.dll + # cannot be made equal in disassembly. Some functions just always end up + # in different order. So for now, accept the difference but put a limit + # on the size. The different order of functions shouldn't result in a very + # big diff. + KNOWN_DIS_DIFF=" + ./bin/server/jvm.dll + " + MAX_KNOWN_DIS_DIFF_SIZE="2000000" fi @@ -565,6 +588,7 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then ./Contents/Home/lib/libverify.dylib ./Contents/Home/lib/libsaproc.dylib ./Contents/Home/lib/libsplashscreen.dylib + ./Contents/Home/lib/server/libjsig.dylib ./Contents/Home/lib/server/libjvm.dylib ./Contents/Home/lib/deploy/JavaControlPanel.prefPane/Contents/MacOS/JavaControlPanel ./Contents/Resources/JavaControlPanelHelper @@ -590,6 +614,7 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then ./lib/libverify.dylib ./lib/libsaproc.dylib ./lib/libsplashscreen.dylib + ./lib/server/libjsig.dylib ./lib/server/libjvm.dylib ./lib/deploy/JavaControlPanel.prefPane/Contents/MacOS/JavaControlPanel ./Versions/A/Resources/finish_installation.app/Contents/MacOS/finish_installation @@ -606,7 +631,8 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then DIS_DIFF_FILTER="LANG=C $SED \ -e 's/0x[0-9a-f]\{3,16\}//g' -e 's/^[0-9a-f]\{12,20\}//' \ - -e 's/## literal pool for: .Java HotSpot(TM) 64-Bit Server VM.*//g' + -e 's/-20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]-[0-2][0-9]\{5\}//g' \ + -e 's/), built on .*/), /' \ " fi diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index a3372cf3fe2..123c6be1f29 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -241,7 +241,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "linux", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -259,7 +259,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "macosx", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -267,7 +267,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -275,7 +275,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "sparcv9", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, diff --git a/make/Jprt.gmk b/make/Jprt.gmk index 6b778293d2a..e7eba24bd31 100644 --- a/make/Jprt.gmk +++ b/make/Jprt.gmk @@ -108,7 +108,9 @@ SRC_JDK_MACOSX_BUNDLE_DIR := $(JDK_MACOSX_BUNDLE_DIR) SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR) # Bundle up the images -bundles: all +JPRT_TARGET ?= all +ifeq ($(JPRT_TARGET), all) + bundles: $(JPRT_TARGET) @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r \ @@ -128,9 +130,24 @@ bundles: all $(BUILD_OUTPUT)/bundles/$(SYMBOLS_IMAGE_SUBDIR).zip . ; \ fi @$(call TargetExit) +else + # Just fake the bundles + bundles: $(JPRT_TARGET) + @$(call TargetEnter) + $(MKDIR) -p $(BUILD_OUTPUT)/bundles + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/modules.zip README + @$(call TargetExit) +endif # Copy images to one unified location regardless of platform etc. -final-images: all +final-images: $(JPRT_TARGET) @$(call TargetEnter) $(RM) -r $(BUILD_OUTPUT)/final-images $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) diff --git a/make/Main.gmk b/make/Main.gmk index 5d8137f2b47..6f77baa92eb 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -229,10 +229,17 @@ ALL_TARGETS += $(LAUNCHER_TARGETS) ifeq ($(BUILD_HOTSPOT),true) hotspot: - +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + ifeq ($(USE_NEW_HOTSPOT_BUILD), true) + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f BuildHotspot.gmk) + else + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + endif endif -ALL_TARGETS += hotspot +hotspot-ide-project: + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f ide/CreateVSProject.gmk) + +ALL_TARGETS += hotspot hotspot-ide-project ################################################################################ # Build demos and samples targets @@ -462,6 +469,8 @@ else $(JAVA_TARGETS): interim-langtools + hotspot-ide-project: hotspot exploded-image + import-hotspot: hotspot generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 7ed52135f28..dd9de199f37 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -730,6 +730,16 @@ endif PathList = \ "$(subst $(SPACE),$(PATH_SEP),$(strip $1))" +################################################################################ +# Check if a specified hotspot variant is being built, or at least one of a +# list of variants. Will return 'true' or 'false'. +# $1 - the variant to test for +check-jvm-variant = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_VARIANTS), $1), \ + $(error Internal error: Invalid variant tested: $1)) \ + $(if $(filter $1, $(JVM_VARIANTS)), true, false)) + ################################################################################ # Hook to include the corresponding custom file, if present. diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index d6a003a8c8e..d595e044013 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -197,14 +197,51 @@ define add_native_source $1_$2_THIS_FILE = -DTHIS_FILE='"$$( Disable the given warnings for the specified toolchain # DISABLED_WARNINGS_C_ Disable the given warnings for the specified toolchain # when compiling C code @@ -331,7 +372,11 @@ endef # toolchain when compiling C++ code # STRIP_SYMBOLS Set to true to strip the final binary if the toolchain allows for it # DEBUG_SYMBOLS Set to false to disable generation of debug symbols +# CFLAGS_DEBUG_SYMBOLS Overrides the default cflags for enabling debug symbols +# CXXFLAGS_DEBUG_SYMBOLS Overrides the default cxxflags for enabling debug symbols # STRIPFLAGS Optionally change the flags given to the strip command +# PRECOMPILED_HEADER Header file to use as precompiled header +# PRECOMPILED_HEADER_EXCLUDE List of source files that should not use PCH SetupNativeCompilation = $(NamedParamsMacroTemplate) define SetupNativeCompilationBody @@ -556,8 +601,10 @@ define SetupNativeCompilationBody endif ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true) - $1_EXTRA_CFLAGS += $(CFLAGS_DEBUG_SYMBOLS) - $1_EXTRA_CXXFLAGS += $(CXXFLAGS_DEBUG_SYMBOLS) + $$(call SetIfEmpty, $1_CFLAGS_DEBUG_SYMBOLS, $(CFLAGS_DEBUG_SYMBOLS)) + $$(call SetIfEmpty, $1_CXXFLAGS_DEBUG_SYMBOLS, $(CXXFLAGS_DEBUG_SYMBOLS)) + $1_EXTRA_CFLAGS += $$($1_CFLAGS_DEBUG_SYMBOLS) + $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_DEBUG_SYMBOLS) endif ifneq (,$$($1_REORDER)) @@ -597,17 +644,23 @@ define SetupNativeCompilationBody endif ifeq (NONE, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NONE) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NONE) + $1_OPT_CFLAGS := $(C_O_FLAG_NONE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE) else ifeq (LOW, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NORM) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NORM) + $1_OPT_CFLAGS := $(C_O_FLAG_NORM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM) else ifeq (HIGH, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HI) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HI) + $1_OPT_CFLAGS := $(C_O_FLAG_HI) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI) else ifeq (HIGHEST, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HIGHEST) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HIGHEST) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST) + else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM) + else ifeq (SIZE, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_SIZE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE) else ifneq (, $$($1_OPTIMIZATION)) $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION)) endif @@ -618,11 +671,65 @@ define SetupNativeCompilationBody # lines for all object files in this setup. This includes at least all the # variables used in the call to add_native_source below. $1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ - $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_OPT_CFLAGS) $$($1_OPT_CXXFLAGS) \ $$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS) $1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps) + ifneq ($$($1_PRECOMPILED_HEADER), ) + ifeq ($(USE_PRECOMPILED_HEADER), 1) + ifeq ($(TOOLCHAIN_TYPE), microsoft) + $1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch + $1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp + $1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch.obj + + $$(eval $$(call add_native_source,$1,$$($1_GENERATED_PCH_SRC), \ + $$($1_OBJECT_DIR),,, \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_SYSROOT_CFLAGS) \ + -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \ + $$($1_CXX),,no_this_file)) + + $1_USE_PCH_FLAGS := \ + -Fp$$($1_PCH_FILE) -Yu$$(notdir $$($1_PRECOMPILED_HEADER)) + + $$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ) + + # Explicitly add the pch obj file first to ease comparing to old + # hotspot build. + $1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS) + + $$($1_GENERATED_PCH_SRC): + $(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@ + + else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), ) + ifeq ($(TOOLCHAIN_TYPE), gcc) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch + $1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled + else ifeq ($(TOOLCHAIN_TYPE), clang) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch + $1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE) + endif + $1_PCH_DEP := $$($1_PCH_FILE).d + $1_PCH_DEP_TARGETS := $$($1_PCH_FILE).d.targets + + -include $$($1_PCH_DEP) + -include $$($1_PCH_DEP_TARGETS) + + $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) + $$(call LogInfo, Generating precompiled header) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, \ + $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ + $$($1_OPT_CFLAGS) \ + -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP) $$< -o $$@) + $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEP) > $$($1_PCH_DEP_TARGETS) + + $$($1_ALL_OBJS): $$($1_PCH_FILE) + + endif + endif + endif + # Now call add_native_source for each source file we are going to compile. $$(foreach p,$$($1_SRCS), \ $$(eval $$(call add_native_source,$1,$$p,$$($1_OBJECT_DIR), \ diff --git a/make/jprt.properties b/make/jprt.properties index 943f15b5be5..40a75b1140f 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -129,9 +129,15 @@ jprt.build.flavor.optimized.target=jprt_bundle jprt.build.flavor.optimizedOpen.target=jprt_bundle jprt.build.flavor.slowdebug.target=jprt_bundle -# Use these configure args to define debug level +# Use these configure args to define debug level or provide specific +# configuration details not covered by Jib profiles. jprt.slowdebug.build.configure.args= jprt.fastdebug.build.configure.args=--disable-precompiled-headers +# Don't disable precompiled headers on windows. It's simply too slow. +jprt.windows_i586.fastdebug.build.configure.args= +jprt.windows_x64.fastdebug.build.configure.args= +jprt.windows_i586.fastdebugOpen.build.configure.args= +jprt.windows_x64.fastdebugOpen.build.configure.args= jprt.product.build.configure.args= jprt.optimized.build.configure.args=--with-debug-level=optimized jprt.slowdebugOpen.build.configure.args=${jprt.slowdebug.build.configure.args} From 87d68625afddda5556bf5c9bcb274002fb34bb38 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 8 Apr 2016 13:14:23 +0200 Subject: [PATCH 055/113] 8152666: The new Hotspot Build System Co-authored-by: Magnus Ihse Bursie Co-authored-by: Ingemar Aberg Reviewed-by: ihse, dcubed, erikj --- hotspot/make/Makefile | 18 +- hotspot/make/aix/makefiles/trace.make | 10 +- hotspot/make/bsd/makefiles/trace.make | 10 +- hotspot/make/linux/makefiles/gcc.make | 4 +- hotspot/make/linux/makefiles/trace.make | 10 +- hotspot/make/linux/makefiles/zero.make | 5 + hotspot/make/solaris/makefiles/dtrace.make | 2 +- hotspot/make/solaris/makefiles/trace.make | 10 +- hotspot/make/windows/makefiles/debug.make | 6 +- hotspot/make/windows/makefiles/fastdebug.make | 6 +- hotspot/make/windows/makefiles/product.make | 7 +- hotspot/make/windows/makefiles/trace.make | 6 + hotspot/make/windows/makefiles/vm.make | 4 +- hotspot/makefiles/BuildHotspot.gmk | 54 ++++ hotspot/makefiles/Dist.gmk | 239 +++++++++++++++++ hotspot/makefiles/HotspotCommon.gmk | 45 ++++ hotspot/makefiles/gensrc/GenerateSources.gmk | 75 ++++++ hotspot/makefiles/gensrc/GensrcAdlc.gmk | 192 ++++++++++++++ hotspot/makefiles/gensrc/GensrcDtrace.gmk | 56 ++++ hotspot/makefiles/gensrc/GensrcJvmti.gmk | 174 +++++++++++++ hotspot/makefiles/ide/CreateVSProject.gmk | 153 +++++++++++ .../makefiles/lib/CompileDtracePostJvm.gmk | 217 ++++++++++++++++ hotspot/makefiles/lib/CompileDtracePreJvm.gmk | 36 +++ hotspot/makefiles/lib/CompileJvm.gmk | 242 ++++++++++++++++++ hotspot/makefiles/lib/CompileLibjsig.gmk | 106 ++++++++ hotspot/makefiles/lib/CompileLibraries.gmk | 42 +++ hotspot/makefiles/lib/JvmFeatures.gmk | 144 +++++++++++ hotspot/makefiles/lib/JvmMapfile.gmk | 172 +++++++++++++ hotspot/makefiles/lib/JvmOverrideFiles.gmk | 168 ++++++++++++ .../mapfiles/libjsig/mapfile-vers-solaris | 38 +++ .../makefiles/mapfiles/libjvm_db/mapfile-vers | 38 +++ .../mapfiles/libjvm_dtrace/mapfile-vers | 37 +++ hotspot/makefiles/symbols/symbols-aix | 27 ++ hotspot/makefiles/symbols/symbols-aix-debug | 26 ++ hotspot/makefiles/symbols/symbols-linux | 27 ++ hotspot/makefiles/symbols/symbols-macosx | 24 ++ hotspot/makefiles/symbols/symbols-shared | 35 +++ hotspot/makefiles/symbols/symbols-solaris | 25 ++ .../symbols/symbols-solaris-dtrace-compiler1 | 34 +++ .../symbols/symbols-solaris-dtrace-compiler2 | 36 +++ hotspot/makefiles/symbols/symbols-unix | 195 ++++++++++++++ 41 files changed, 2714 insertions(+), 41 deletions(-) create mode 100644 hotspot/makefiles/BuildHotspot.gmk create mode 100644 hotspot/makefiles/Dist.gmk create mode 100644 hotspot/makefiles/HotspotCommon.gmk create mode 100644 hotspot/makefiles/gensrc/GenerateSources.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcAdlc.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcDtrace.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcJvmti.gmk create mode 100644 hotspot/makefiles/ide/CreateVSProject.gmk create mode 100644 hotspot/makefiles/lib/CompileDtracePostJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileDtracePreJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileLibjsig.gmk create mode 100644 hotspot/makefiles/lib/CompileLibraries.gmk create mode 100644 hotspot/makefiles/lib/JvmFeatures.gmk create mode 100644 hotspot/makefiles/lib/JvmMapfile.gmk create mode 100644 hotspot/makefiles/lib/JvmOverrideFiles.gmk create mode 100644 hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris create mode 100644 hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers create mode 100644 hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers create mode 100644 hotspot/makefiles/symbols/symbols-aix create mode 100644 hotspot/makefiles/symbols/symbols-aix-debug create mode 100644 hotspot/makefiles/symbols/symbols-linux create mode 100644 hotspot/makefiles/symbols/symbols-macosx create mode 100644 hotspot/makefiles/symbols/symbols-shared create mode 100644 hotspot/makefiles/symbols/symbols-solaris create mode 100644 hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 create mode 100644 hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 create mode 100644 hotspot/makefiles/symbols/symbols-unix diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 4312c797579..db2b96e25e0 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -237,19 +237,21 @@ else $(MAKE_ARGS) $(VM_TARGET) endif +# NOTE: Changes in this file was just to facilitate comparison when +# developing the new build, and should not be integrated. generic_buildcore: $(HOTSPOT_SCRIPT) -ifeq ($(HS_ARCH),ppc) - ifeq ($(ARCH_DATA_MODEL),64) +#ifeq ($(HS_ARCH),ppc) +# ifeq ($(ARCH_DATA_MODEL),64) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) - else - @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" -endif +# else +# @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" +# endif +#else +# @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" +#endif generic_buildzero: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index f4f9e7f8e6c..f17e75e1f4f 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index af46df58ce0..37df4425f50 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index a2e5c6c03b6..75dcaeb2c34 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -221,7 +221,7 @@ ifeq ($(USE_CLANG),) ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" # GCC < 4.3 WARNING_FLAGS += -Wconversion - endif + endif ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1" # GCC >= 4.8 # This flag is only known since GCC 4.3. Gcc 4.8 contains a fix so that with templates no @@ -260,7 +260,7 @@ endif OPT_CFLAGS = $(OPT_CFLAGS/$(OPT_CFLAGS_DEFAULT)) $(OPT_EXTRAS) -# Variable tracking size limit exceeded for VMStructs::init() +# Variable tracking size limit exceeded for VMStructs::init() ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "1" # GCC >= 4.3 # Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file. diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 09cb921094e..2209716d35b 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/zero.make b/hotspot/make/linux/makefiles/zero.make index 0270711f5cb..622710f4dfa 100644 --- a/hotspot/make/linux/makefiles/zero.make +++ b/hotspot/make/linux/makefiles/zero.make @@ -30,3 +30,8 @@ TYPE = ZERO # Install libjvm.so, etc in in server directory. VM_SUBDIR = server + +# Disable trace for zero builds +# NOTE: This is used for simple comparison with the new build system, and +# should not be merged into mainline with build-infra. +INCLUDE_TRACE := false diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 376732d0e6b..2c65059a213 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -270,7 +270,7 @@ $(DTRACE.o): $(DTRACE).d $(DTraced_Files) @echo $(LOG_INFO) Compiling $(DTRACE).d $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ - $(DTraced_Files) ||\ + $(sort $(DTraced_Files)) ||\ STATUS=$$?;\ if [ x"$$STATUS" = x"1" ]; then \ if [ x`uname -r` = x"5.10" -a \ diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ed7046295b3..effe34061ce 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make index f2ecd269887..3ad45627467 100644 --- a/hotspot/make/windows/makefiles/debug.make +++ b/hotspot/make/windows/makefiles/debug.make @@ -48,10 +48,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-debug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make index cbcfd5abb04..ea6fc41a42a 100644 --- a/hotspot/make/windows/makefiles/fastdebug.make +++ b/hotspot/make/windows/makefiles/fastdebug.make @@ -47,10 +47,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-fastdebug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make index cd3a4e70bc5..09e750acc07 100644 --- a/hotspot/make/windows/makefiles/product.make +++ b/hotspot/make/windows/makefiles/product.make @@ -51,10 +51,11 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING) # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) + !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/trace.make b/hotspot/make/windows/makefiles/trace.make index eecc890663f..d52391386d0 100644 --- a/hotspot/make/windows/makefiles/trace.make +++ b/hotspot/make/windows/makefiles/trace.make @@ -41,6 +41,12 @@ HAS_ALT_SRC = true !endif !endif +!ifndef OPENJDK +!if EXISTS($(TraceAltSrcDir)) +HAS_ALT_SRC = true +!endif +!endif + TraceGeneratedNames = \ traceEventClasses.hpp \ traceEventIds.hpp \ diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index fd42111866b..a1391a04413 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -305,8 +305,10 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi # This guy should remain a single colon rule because # otherwise we can't specify the output filename. +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. {$(COMMONSRC)\os\windows\vm}.rc.res: - @$(RC) $(RC_FLAGS) /fo"$@" $< + $(RC) $(RC_FLAGS) /fo"$@" $< {$(COMMONSRC)\cpu\$(Platform_arch)\vm}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< diff --git a/hotspot/makefiles/BuildHotspot.gmk b/hotspot/makefiles/BuildHotspot.gmk new file mode 100644 index 00000000000..4ae7b84c387 --- /dev/null +++ b/hotspot/makefiles/BuildHotspot.gmk @@ -0,0 +1,54 @@ +# +# Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +VARIANT_TARGETS := $(foreach v, $(JVM_VARIANTS), variant-$v) +VARIANT_GENSRC_TARGETS := $(addsuffix -gensrc, $(VARIANT_TARGETS)) +VARIANT_LIBS_TARGETS := $(addsuffix -libs, $(VARIANT_TARGETS)) + +$(VARIANT_GENSRC_TARGETS): variant-%-gensrc: + $(call LogWarn, Building JVM variant '$*' with features '$(JVM_FEATURES_$*)') + +$(MAKE) -f gensrc/GenerateSources.gmk JVM_VARIANT=$* + +$(VARIANT_LIBS_TARGETS): variant-%-libs: variant-%-gensrc + +$(MAKE) -f lib/CompileLibraries.gmk JVM_VARIANT=$* + +$(VARIANT_TARGETS): variant-%: variant-%-gensrc variant-%-libs + +jsig: + +$(MAKE) -f lib/CompileLibjsig.gmk + +dist: $(VARIANT_TARGETS) jsig + +$(MAKE) -f Dist.gmk + +all: dist + +.PHONY: $(VARIANT_TARGETS) $(VARIANT_GENSRC_TARGETS) $(VARIANT_LIBS_TARGETS) \ + jsig dist all diff --git a/hotspot/makefiles/Dist.gmk b/hotspot/makefiles/Dist.gmk new file mode 100644 index 00000000000..bfe3daf2062 --- /dev/null +++ b/hotspot/makefiles/Dist.gmk @@ -0,0 +1,239 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +################################################################################ +# Copy the generated output into well-defined places in the dist directory. + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +$(eval $(call IncludeCustomExtension, hotspot, Dist.gmk)) + +DIST_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/dist + +# Unfortunately, all platforms have different target subdirs. +ifeq ($(OPENJDK_TARGET_OS), windows) + LIB_SUBDIR := bin +else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIB_SUBDIR := lib +else + LIB_SUBDIR := lib$(OPENJDK_TARGET_CPU_LIBDIR) +endif + +################################################################################ +# Functions to setup copying of files for variants + +# Support macro for SetupDistLibFile +define macosx_universalize + $(MKDIR) -p $(@D) + $(LIPO) -create -output $@ $< +endef + +################################################################################ +# Setup make rules to copy a native library and associated data. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# NAME -- The base name of the native library (e.g. 'jvm') +# VARIANT -- The variant to copy from +# VARIANT_TARGET_DIR -- The variant target sub dir, with trailing slash, optional +SetupDistLibFile = $(NamedParamsMacroTemplate) +define SetupDistLibFileBody + ifneq ($$($1_VARIANT), ) + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_VARIANT)/lib$$($1_NAME) + else + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/lib$$($1_NAME) + endif + $1_LIB_NAME := $(LIBRARY_PREFIX)$$($1_NAME) + $1_TARGET_DIR := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$$($1_VARIANT_TARGET_DIR) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # We must use the 'universalize' macro to run lipo on shared libraries, at + # least until JDK-8069540 is fixed. + $1_MACRO := macosx_universalize + endif + + # Copy the the native library. + $$(eval $$(call SetupCopyFiles, $1_COPY_LIB, \ + DEST := $$($1_TARGET_DIR), \ + MACRO := $$($1_MACRO), \ + FILES := $$(wildcard \ + $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX)), \ + )) + + TARGETS += $$($1_COPY_LIB) + + # Copy related data (debug symbols, static-build symbols file etc) + $$(eval $$(call SetupCopyFiles, $1_COPY_FILES, \ + DEST := $$($1_TARGET_DIR), \ + FILES := $$(wildcard \ + $$(addprefix $$($1_SRC_DIR)/$$($1_LIB_NAME), \ + .diz .debuginfo .pdb .map .symbols)), \ + )) + + TARGETS += $$($1_COPY_FILES) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # Debug symbols on macosx is a directory, not a single file, per library. + $1_DSYM_SRC := $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX).dSYM) + ifneq ($$(wildcard $$($1_DSYM_SRC)), ) + $$(eval $$(call SetupCopyFiles, $1_COPY_DSYM_DIR, \ + DEST := $$($1_TARGET_DIR), \ + SRC := $$($1_SRC_DIR), \ + FILES := $$(shell $(FIND) $$($1_DSYM_SRC) -type f), \ + )) + TARGETS += $$($1_COPY_DSYM_DIR) + endif + endif +endef + +################################################################################ +# Copy common files, which are independent on the jvm variant(s) being built. +# For files that were generated during the build, we assume all versions of +# these files are identical, and just pick one arbitrarily to use as source. + +ANY_JVM_VARIANT := $(firstword $(JVM_VARIANTS)) +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(ANY_JVM_VARIANT) + +### Copy platform-independent .h files +INCLUDE_FILES_SRC_DIR := $(HOTSPOT_TOPDIR)/src/share/vm +$(eval $(call SetupCopyFiles, COPY_INCLUDE, \ + SRC := $(INCLUDE_FILES_SRC_DIR), \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(INCLUDE_FILES_SRC_DIR)/prims/jni.h \ + $(INCLUDE_FILES_SRC_DIR)/code/jvmticmlr.h \ + $(INCLUDE_FILES_SRC_DIR)/services/jmm.h)) + +TARGETS += $(COPY_INCLUDE) + +### Copy jni_md.h + +# This might have been defined in a custom extension +ifeq ($(JNI_MD_H_SRC), ) + JNI_MD_H_SRC := $(HOTSPOT_TOPDIR)/src/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/jni_$(HOTSPOT_TARGET_CPU_ARCH).h +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: This should most likely be darwin, but the old hotspot build uses bsd + JNI_MD_SUBDIR := bsd +else ifeq ($(OPENJDK_TARGET_OS), windows) + JNI_MD_SUBDIR := win32 +else + JNI_MD_SUBDIR := $(OPENJDK_TARGET_OS) +endif + +# SetupCopyFiles is not used here since it's non-trivial to copy a single +# file with a different target name. +$(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h: $(JNI_MD_H_SRC) + $(call LogInfo, Copying hotspot/dist/include/$(JNI_MD_SUBDIR)/jni_md.h) + $(install-file) + +TARGETS += $(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h + +$(eval $(call SetupCopyFiles, COPY_JVMTI_H, \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h)) + +TARGETS += $(COPY_JVMTI_H) + +# NOTE: In the old build, this file was not copied on Windows. +ifneq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \ + DEST := $(DIST_OUTPUTDIR)/docs/platform/jvmti, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.html)) +endif + +TARGETS += $(COPY_JVMTI_HTML) + +ifeq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ + DEST := $(DIST_OUTPUTDIR)/lib, \ + FILES :=$(JVM_VARIANT_OUTPUTDIR)/libjvm/objs/jvm.lib)) + + TARGETS += $(COPY_JVM_LIB) +endif + +# Copy libjsig, if it exists +$(eval $(call SetupDistLibFile, DIST_jsig, \ + NAME := jsig, \ +)) + +################################################################################ +# Copy variant-specific files + +# Setup make rules to copy a single variant to dist. +# $1: The name of the variant +define SetupDistForVariant + ifneq ($$(filter client minimal, $1), ) + VARIANT_TARGET_DIR := $1 + else + # Use 'server' as default target directory name for all other variants. + VARIANT_TARGET_DIR := server + endif + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm, \ + NAME := jvm, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the dtrace libraries, if they exist + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_db, \ + NAME := jvm_db, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_dtrace, \ + NAME := jvm_dtrace, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the Xusage.txt file + $$(eval $$(call SetupCopyFiles, DIST_$(strip $1)_Xusage, \ + DEST := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$(strip $1), \ + FILES := $$(HOTSPOT_OUTPUTDIR)/variant-$(strip $1)/support/misc/Xusage.txt, \ + )) + + TARGETS += $$(DIST_$(strip $1)_Xusage) +endef + +$(foreach variant, $(JVM_VARIANTS), \ + $(eval $(call SetupDistForVariant, $(variant))) \ +) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/HotspotCommon.gmk b/hotspot/makefiles/HotspotCommon.gmk new file mode 100644 index 00000000000..1df3f4fa9b3 --- /dev/null +++ b/hotspot/makefiles/HotspotCommon.gmk @@ -0,0 +1,45 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +ifeq ($(JVM_VARIANT), ) + $(error This makefile must be called with JVM_VARIANT set) +endif + +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(JVM_VARIANT) +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_SUPPORT_DIR := $(JVM_VARIANT_OUTPUTDIR)/support + +DTRACE_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/dtrace + +################################################################################ + +# Test if a feature is available in the present build of JVM_VARIANT. Will return +# 'true' or 'false'. +# $1 - the feature to test for +check-jvm-feature = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_FEATURES), $1), \ + $(error Internal error: Invalid feature tested: $1)) \ + $(if $(filter $1, $(JVM_FEATURES_$(JVM_VARIANT))), true, false)) diff --git a/hotspot/makefiles/gensrc/GenerateSources.gmk b/hotspot/makefiles/gensrc/GenerateSources.gmk new file mode 100644 index 00000000000..b91f2d0c864 --- /dev/null +++ b/hotspot/makefiles/gensrc/GenerateSources.gmk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include NativeCompilation.gmk +include TextFileProcessing.gmk + +include HotspotCommon.gmk + +# The real work is done in these files + +include gensrc/GensrcAdlc.gmk +include gensrc/GensrcDtrace.gmk +include gensrc/GensrcJvmti.gmk + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GenerateSources.gmk)) + +# While technically the rules below are "gendata" which can be done in parallel +# with native compilation, let's keep it here for simplicity. + +# The Xusage.txt file needs to have platform specific path separator +$(eval $(call SetupTextFileProcessing, CREATE_XUSAGE, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/Xusage.txt, \ + OUTPUT_FILE := $(JVM_SUPPORT_DIR)/misc/Xusage.txt, \ + REPLACEMENTS := separated by ;> => separated by $(PATH_SEP)> ; , \ +)) + +TARGETS += $(CREATE_XUSAGE) + +# Setup the hotspot launcher script for developer use +$(eval $(call SetupTextFileProcessing, CREATE_HOTSPOT_LAUNCHER, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/make/hotspot.script, \ + OUTPUT_FILE := $(JVM_OUTPUTDIR)/hotspot, \ + REPLACEMENTS := \ + @@LIBARCH@@ => $(OPENJDK_TARGET_CPU_LEGACY_LIB) ; \ + @@JDK_IMPORT_PATH@@ => $(JDK_OUTPUTDIR) ; , \ +)) + +CHMOD_HOTSPOT_LAUNCHER := $(JVM_VARIANT_OUTPUTDIR)/libjvm/_hotspot-script-chmod.marker + +$(CHMOD_HOTSPOT_LAUNCHER): $(CREATE_HOTSPOT_LAUNCHER) + $(CHMOD) +x $< + $(TOUCH) $@ + +TARGETS += $(CREATE_HOTSPOT_LAUNCHER) $(CHMOD_HOTSPOT_LAUNCHER) + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/gensrc/GensrcAdlc.gmk b/hotspot/makefiles/gensrc/GensrcAdlc.gmk new file mode 100644 index 00000000000..eb58ac7737c --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcAdlc.gmk @@ -0,0 +1,192 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcAdlc.gmk)) + +ifeq ($(call check-jvm-feature, compiler2), true) + + ADLC_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/adlc + + ############################################################################## + # Build the ad compiler (the adlc build tool) + + # Flags depending on the build platform/tool chain + # NOTE: No optimization or debug flags set here + ifeq ($(OPENJDK_BUILD_OS), linux) + ADLC_CFLAGS := -fno-exceptions -DLINUX + else ifeq ($(OPENJDK_BUILD_OS), solaris) + ADLC_LDFLAGS := -m64 + ADLC_CFLAGS := -m64 + ADLC_CFLAGS_WARNINGS := +w + else ifeq ($(OPENJDK_BUILD_OS), aix) + # FIXME: Not implemented. These flags are likely, however + # ADLC_LDFLAGS := -q64 + # ADLC_CFLAGS := -qnortti -qnoeh -q64 + else ifeq ($(OPENJDK_BUILD_OS), windows) + ADLC_LDFLAGS := -nologo + ADLC_CFLAGS := -nologo -EHsc + # NOTE: The old build also have -D_CRT_SECURE_NO_DEPRECATE but it doesn't + # seem needed any more. + ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS + endif + + # NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to + # hurt. + ADLC_CFLAGS += -DASSERT + + ADLC_CFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE) + + ADLC_CFLAGS += -I$(HOTSPOT_TOPDIR)/src/share/vm + + $(eval $(call SetupNativeCompilation, BUILD_ADLC, \ + TOOLCHAIN := TOOLCHAIN_BUILD_LINK_CXX, \ + SRC := $(HOTSPOT_TOPDIR)/src/share/vm/adlc, \ + EXTRA_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/opto/opcodes.cpp, \ + CFLAGS := $(ADLC_CFLAGS) $(ADLC_CFLAGS_WARNINGS), \ + LDFLAGS := $(ADLC_LDFLAGS), \ + LIBS := $(ADLC_LIBS), \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc, \ + PROGRAM := adlc, \ + DEBUG_SYMBOLS := false, \ + DISABLED_WARNINGS_clang := parentheses tautological-compare, \ + DISABLED_WARNINGS_solstudio := notemsource, \ + )) + + ADLC_TOOL := $(BUILD_ADLC_TARGET) + + ############################################################################## + # Transform the ad source files into C++ source files using adlc + + # Setup flags for the adlc build tool (ADLCFLAGS). + ADLCFLAGS += -q -T + + # ADLC flags depending on target OS + ifeq ($(OPENJDK_TARGET_OS), linux) + ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1 + else ifeq ($(OPENJDK_TARGET_OS), solaris) + ADLCFLAGS += -DSOLARIS=1 -DSPARC_WORKS=1 + else ifeq ($(OPENJDK_TARGET_OS), aix) + # FIXME: Not implemented + else ifeq ($(OPENJDK_TARGET_OS), macosx) + ADLCFLAGS += -D_ALLBSD_SOURCE=1 -D_GNU_SOURCE=1 + endif + + ifneq ($(OPENJDK_TARGET_OS), windows) + # NOTE: Windows adlc flags was different in the old build. Is this really + # correct? + + # -g makes #line directives in the generated C++ files. + ADLCFLAGS += -g + + ADLCFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE)=1 + endif + + # This generates checks in the generated C++ files that _LP64 is correctly + # (un)defined when compiling them. + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + ADLCFLAGS += -D_LP64=1 + else + ADLCFLAGS += -U_LP64 + endif + + ############################################################################## + # Concatenate all ad source files into a single file, which will be fed to + # adlc. Also include a #line directive at the start of every included file + # (after the initial header block), stating the original source file name. + # + # Normally, debugging is done directly on the ad_*.cpp files, but the + # #line directives in those files will be pointing back to .ad. + + # AD_SRC_ROOTS might have been added to by a custom extension + AD_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + + AD_SRC_FILES := $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU).ad \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU_ARCH).ad \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \ + ))) + + SINGLE_AD_SRCFILE := $(ADLC_SUPPORT_DIR)/all-ad-src.ad + + INSERT_FILENAME_AWK_SCRIPT := \ + '{ \ + if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \ + if (need_lineno && $$0 !~ /\/\//) \ + { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \ + print \ + }' + + $(SINGLE_AD_SRCFILE): $(AD_SRC_FILES) + $(call LogInfo, Preprocessing adlc files $(^F)) + $(call MakeDir, $(@D)) + $(NAWK) $(INSERT_FILENAME_AWK_SCRIPT) $^ > $@ + + ############################################################################## + # Run the adlc tool on the single concatenated ad source file, and store the + # output in support/adlc for further processing. + ADLC_RUN_MARKER := $(ADLC_SUPPORT_DIR)/_adlc_run.marker + + $(ADLC_RUN_MARKER): $(BUILD_ADLC) $(SINGLE_AD_SRCFILE) + $(call LogInfo, Generating adlc files) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $(ADLC_SUPPORT_DIR)/adlc_run, \ + $(FIXPATH) $(ADLC_TOOL) $(ADLCFLAGS) $(SINGLE_AD_SRCFILE) \ + -c$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).cpp \ + -h$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).hpp \ + -a$(ADLC_SUPPORT_DIR)/dfa_$(HOTSPOT_TARGET_CPU).cpp \ + -v$(ADLC_SUPPORT_DIR)/adGlobals_$(HOTSPOT_TARGET_CPU).hpp) + $(TOUCH) $@ + + ############################################################################## + # Finally copy the generated files from support/adlc into gensrc/adfiles, + # and postprocess them by fixing dummy #line directives. + + ADLC_GENERATED_FILES := $(addprefix $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/, \ + ad_$(HOTSPOT_TARGET_CPU).cpp \ + ad_$(HOTSPOT_TARGET_CPU).hpp \ + ad_$(HOTSPOT_TARGET_CPU)_clone.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_expand.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_format.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_gen.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_misc.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_peephole.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_pipeline.cpp \ + adGlobals_$(HOTSPOT_TARGET_CPU).hpp \ + dfa_$(HOTSPOT_TARGET_CPU).cpp \ + ) + + $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/%: $(ADLC_RUN_MARKER) + $(call LogInfo, Postprocessing adlc file $*) + $(call MakeDir, $(@D)) + $(NAWK) \ + 'BEGIN { print "#line 1 \"$*\""; } \ + /^#line 999999$$/ {print "#line " (NR+1) " \"$*\""; next} \ + {print}' \ + < $(ADLC_SUPPORT_DIR)/$* > $@ + + TARGETS := $(ADLC_GENERATED_FILES) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcDtrace.gmk b/hotspot/makefiles/gensrc/GensrcDtrace.gmk new file mode 100644 index 00000000000..563f22112fb --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcDtrace.gmk @@ -0,0 +1,56 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +################################################################################ +# Gensrc support for dtrace. The files generated here are included by dtrace.hpp + +ifeq ($(call check-jvm-feature, dtrace), true) + + ifeq ($(OPENJDK_TARGET_OS), solaris) + DTRACE_FLAGS := -64 + DTRACE_CPP_FLAGS := -D_LP64 + else ifeq ($(OPENJDK_TARGET_OS), macosx) + DTRACE_CPP_FLAGS := -D_LP64 -x c + else ifeq ($(OPENJDK_TARGET_OS), linux) + DTRACE_CPP_FLAGS := -x c + endif + + DTRACE_SOURCE_DIR := $(HOTSPOT_TOPDIR)/src/os/posix/dtrace + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_GENSRC_DIR)/%.h: $(DTRACE_SOURCE_DIR)/%.d + $(call LogInfo, Generating dtrace header file $(@F)) + $(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR)) + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + # Process all .d files in DTRACE_SOURCE_DIR. They are: + # hotspot_jni.d hotspot.d hs_private.d + TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \ + $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d)) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcJvmti.gmk b/hotspot/makefiles/gensrc/GensrcJvmti.gmk new file mode 100644 index 00000000000..25f569dc119 --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcJvmti.gmk @@ -0,0 +1,174 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcJvmti.gmk)) + +################################################################################ +# Build tools needed for the JVMTI source code generation + +JVMTI_TOOLS_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_TOOLS_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/tools/jvmti + +$(eval $(call SetupJavaCompiler, GENERATE_OLDBYTECODE, \ + JAVAC := $(JAVAC), \ + FLAGS := $(DISABLE_WARNINGS), \ + SERVER_DIR := $(SJAVAC_SERVER_DIR), \ + SERVER_JVM := $(SJAVAC_SERVER_JAVA), \ + DISABLE_SJAVAC := true, \ +)) + +$(eval $(call SetupJavaCompilation, BUILD_JVMTI_TOOLS, \ + SETUP := GENERATE_OLDBYTECODE, \ + SRC := $(JVMTI_TOOLS_SRCDIR), \ + INCLUDE_FILES := jvmtiGen.java jvmtiEnvFill.java, \ + BIN := $(JVMTI_TOOLS_OUTPUTDIR), \ +)) + +TOOL_JVMTI_GEN := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiGen +TOOL_JVMTI_ENV_FILL := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiEnvFill + +################################################################################ +# Setup make rules for an xml transform for jvmti/trace file generation. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. This name is +# also used as the name of the output file. +# +# Remaining parameters are named arguments. These include: +# XML_FILE -- The input source file to use +# XSL_FILE -- The xsl file to use +# OUTPUT_DIR -- The directory to put the generated file in +# ARGS -- Additional arguments to the jvmtiGen tool +# DEPS -- Additional dependencies +SetupXslTransform = $(NamedParamsMacroTemplate) +define SetupXslTransformBody + $$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSL_FILE) $$($1_DEPS) $$(BUILD_JVMTI_TOOLS) + $$(call LogInfo, Generating $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS)) + # jvmtiGen does not return error code properly on fail. + # NOTE: We should really fix jvmtiGen.java instead. + test -f $$@ + + TARGETS += $$($1_OUTPUT_DIR)/$1 +endef + +################################################################################ +# Create JVMTI files in gensrc/jvmtifiles + +JVMTI_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles + +# Setup rule for generating a jvmti file +# +# $1 is generated source file name in $(JVMTI_OUTPUTDIR) +# $2 is XSL file to use in $(JVMTI_SRCDIR) +# $3 is optional extra arguments to jvmtiGen +define SetupJvmtiGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(JVMTI_SRCDIR)/jvmti.xml, \ + XSL_FILE := $$(JVMTI_SRCDIR)/$(strip $2), \ + OUTPUT_DIR := $$(JVMTI_OUTPUTDIR), \ + ARGS := $3, \ + DEPS := $$(JVMTI_SRCDIR)/jvmtiLib.xsl, \ + )) +endef + +$(eval $(call SetupJvmtiGeneration, jvmtiEnter.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnterTrace.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti -PARAM trace Trace)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnv.hpp, jvmtiHpp.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.h, jvmtiH.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.html, jvmti.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnvStub.cpp, jvmtiEnv.xsl)) + +JVMTI_BC_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/interpreter + +$(eval $(call SetupXslTransform, bytecodeInterpreterWithChecks.cpp, \ + XML_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xml, \ + XSL_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xsl, \ + OUTPUT_DIR := $(JVMTI_OUTPUTDIR), \ + DEPS := $(JVMTI_BC_SRCDIR)/bytecodeInterpreter.cpp, \ +)) + +# We need $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp (generated above) as input +$(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp: $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp $(BUILD_JVMTI_TOOLS) + $(call LogInfo, Generating $(@F)) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, $(TOOL_JVMTI_ENV_FILL) $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp) + # jvmtiEnvFill does not necessarily return an error code on failure. + # NOTE: We should really fix jvmtiEnvFill.java instead. + test -f $@ + +TARGETS += $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp + +################################################################################ +# Create trace files in gensrc/tracefiles + +TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles +TRACE_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/trace + +# Append directories to search (might have been set by custom extensions) +TRACE_SEARCH_DIRS += $(TRACE_SRCDIR) + +TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml + +# Changing these will trigger a rebuild of generated trace files. +TRACE_DEPS += \ + $(TRACE_XML) \ + $(TRACE_SRCDIR)/tracetypes.xml \ + $(TRACE_SRCDIR)/tracerelationdecls.xml \ + $(TRACE_SRCDIR)/traceevents.xml \ + $(TRACE_SRCDIR)/trace.dtd \ + $(TRACE_SRCDIR)/xinclude.mod \ + # + +# Setup rule for generating a trace file +# +# $1 is generated source file name in $(TRACE_OUTPUTDIR) +define SetupTraceGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(TRACE_XML), \ + XSL_FILE := $$(firstword $$(wildcard $$(addsuffix /$$(basename $1).xsl, $$(TRACE_SEARCH_DIRS)))), \ + OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \ + DEPS := $$(TRACE_DEPS), \ + )) +endef + +# Append files to generated (might have been set by custom extensions) +TRACE_GENSRC_FILES += \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp \ + # + +# Call SetupTraceGeneration for all trace gensrc files +$(foreach tracefile, $(TRACE_GENSRC_FILES), \ + $(eval $(call SetupTraceGeneration, $(tracefile))) \ +) diff --git a/hotspot/makefiles/ide/CreateVSProject.gmk b/hotspot/makefiles/ide/CreateVSProject.gmk new file mode 100644 index 00000000000..d804dcce9a8 --- /dev/null +++ b/hotspot/makefiles/ide/CreateVSProject.gmk @@ -0,0 +1,153 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include SetupJavaCompilers.gmk + +ifeq ($(OPENJDK_TARGET_OS), windows) + # The next part is a bit hacky. We include the CompileJvm.gmk to be + # able to extact flags, but we do not wish to execute the rules. + + # Use client as base for defines and includes + JVM_VARIANT=client + + include HotspotCommon.gmk + include lib/CompileJvm.gmk + + # Reset targets so we don't build libjvm. + TARGETS := + + # Helper macro to convert a unix path to a Windows path, suitable for + # inclusion in a command line. + FixPath = \ + $(strip $(subst \,\\,$(shell $(CYGPATH) -w $1))) + + JVM_DEFINES_client := $(patsubst -D%,%, $(filter -D%, $(JVM_CFLAGS))) + EXTRACTED_DEFINES_client := $(addprefix -define , $(JVM_DEFINES_client)) + + JVM_INCLUDES_client := $(patsubst -I%,%, $(filter -I%, $(JVM_CFLAGS))) + EXTRACTED_INCLUDES_client := $(foreach path, $(JVM_INCLUDES_client), -absoluteInclude $(call FixPath, $(path))) + + # Hand-code variant-specific arguments, based on the fact that we use + # client for general arguments. Not optimal but other solutions require + # major changes in ProjectCreator. + ADDITIONAL_VARIANT_ARGS := \ + -define_server COMPILER2 \ + -ignorePath_client adfiles \ + -ignorePath_client c2_ \ + -ignorePath_client runtime_ \ + -ignorePath_client libadt \ + -ignorePath_client opto \ + # + + IGNORED_PLATFORMS_ARGS := \ + -ignorePath aarch64 \ + -ignorePath aix \ + -ignorePath arm \ + -ignorePath bsd \ + -ignorePath linux \ + -ignorePath posix \ + -ignorePath ppc \ + -ignorePath shark \ + -ignorePath solaris \ + -ignorePath sparc \ + -ignorePath x86_32 \ + -ignorePath zero \ + # + + ################################################################################ + # Build the ProjectCreator java tool. + + TOOLS_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/support/tools_classes + + $(eval $(call SetupJavaCompilation, BUILD_PROJECT_CREATOR, \ + SETUP := GENERATE_OLDBYTECODE, \ + ADD_JAVAC_FLAGS := -Xlint:-auxiliaryclass, \ + SRC := $(HOTSPOT_TOPDIR)/makefiles/src/classes, \ + BIN := $(TOOLS_OUTPUTDIR), \ + )) + + TARGETS += $(BUILD_PROJECT_CREATOR) + + # Run the ProjectCreator tool + PROJECT_CREATOR_TOOL := $(JAVA_SMALL) -cp $(TOOLS_OUTPUTDIR) build.tools.projectcreator.ProjectCreator + + IDE_OUTPUTDIR := $(BUILD_OUTPUT)/ide/hotspot-visualstudio + + VCPROJ_FILE := $(IDE_OUTPUTDIR)/jvm.vcxproj + + PROJECT_CREATOR_CLASS := build.tools.projectcreator.WinGammaPlatformVC10 + + # We hard-code gensrc dir to server (since this includes adfiles) + PROJECT_CREATOR_ARGS := \ + -sourceBase $(call FixPath, $(HOTSPOT_TOPDIR)) \ + -startAt src \ + -relativeSrcInclude src \ + -hidePath .hg \ + -hidePath .jcheck \ + -hidePath jdk.hotspot.agent \ + -hidePath jdk.vm.ci \ + -hidePath jdk.jfr \ + -compiler VC10 \ + -jdkTargetRoot $(call FixPath, $(JDK_OUTPUTDIR)) \ + -platformName x64 \ + -buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \ + -buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \ + -makeBinary $(call FixPath, $(MAKE)) \ + -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \ + -absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + -absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + $(EXTRACTED_DEFINES_client) \ + $(EXTRACTED_INCLUDES_client) \ + $(ADDITIONAL_VARIANT_ARGS) \ + $(IGNORED_PLATFORMS_ARGS) \ + # + + VCPROJ_VARDEPS := $(PROJECT_CREATOR_CLASS) $(PROJECT_CREATOR_ARGS) + VCPROJ_VARDEPS_FILE := $(call DependOnVariable, VCPROJ_VARDEPS, \ + $(VCPROJ_FILE).vardeps) + + $(VCPROJ_FILE): $(BUILD_PROJECT_CREATOR) $(VCPROJ_VARDEPS_FILE) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, \ + $(PROJECT_CREATOR_TOOL) $(PROJECT_CREATOR_CLASS) \ + $(PROJECT_CREATOR_ARGS) -projectFileName $(call FixPath, $@)) \ + $(LOG_INFO) + + TARGETS += $(VCPROJ_FILE) + + all: $(TARGETS) + +else + all: + $(info Hotspot Visual Studio generation only supported on Windows) +endif + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileDtracePostJvm.gmk b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk new file mode 100644 index 00000000000..127460a562e --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk @@ -0,0 +1,217 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +################################################################################ +# Support for dtrace integration with libjvm, and stand-alone dtrace library +# compilation. + +ifeq ($(call check-jvm-feature, dtrace), true) + ############################################################################## + + ifeq ($(OPENJDK_TARGET_OS), solaris) + ############################################################################ + # Integrate with libjvm. Here we generate three object files which are + # linked with libjvm.so. This step is complicated from a dependency + # perspective, since it needs the rest of the compiled object files from the + # libjvm compilation, but the output is object files that are to be included + # when linking libjvm.so. So this generation must happen as a part of the + # libjvm compilation. + + # First we need to generate the dtraceGenOffsets tool. When run, this will + # produce more header files and a C++ file. + + # Note that generateJvmOffsets.cpp must be compiled as if it were a file + # in the libjvm.so, using JVM_CFLAGS as setup in CompileJvm.gmk. Otherwise + # this would preferrably have been done as a part of GensrcDtrace.gmk. + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ + SRC := $(HOTSPOT_TOPDIR)/src/os/$(OPENJDK_TARGET_OS)/dtrace, \ + INCLUDE_FILES := generateJvmOffsets.cpp generateJvmOffsetsMain.c, \ + CC := $(BUILD_CXX), \ + CXX := $(BUILD_CXX), \ + LDEXE := $(BUILD_CXX), \ + generateJvmOffsets.cpp_CXXFLAGS := $(JVM_CFLAGS) -mt -xnolib -norunpath, \ + generateJvmOffsetsMain.c_CFLAGS := -library=%none -mt -m64 -norunpath -z nodefs, \ + LDFLAGS := -m64, \ + LIBS := -lc, \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ + PROGRAM := dtraceGenOffsets, \ + )) + + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET) + + # Argument 1: Output filename + # Argument 2: dtrace-gen-offset tool command line option + define SetupDtraceOffsetsGeneration + $1: $$(BUILD_DTRACE_GEN_OFFSETS) + $$(call LogInfo, Generating dtrace $2 file $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@) + + TARGETS += $1 + endef + + JVM_OFFSETS_H := $(DTRACE_SUPPORT_DIR)/JvmOffsets.h + JVM_OFFSETS_CPP := $(DTRACE_SUPPORT_DIR)/JvmOffsets.cpp + JVM_OFFSETS_INDEX_H := $(DTRACE_SUPPORT_DIR)/JvmOffsetsIndex.h + + # Run the dtrace-gen-offset tool to generate these three files. + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table)) + + ############################################################################ + # Compile JVM_OFFSETS_OBJ which is linked with libjvm.so. + + # JvmOffsets.cpp is compiled without the common JVM_CFLAGS. Otherwise, the + # natural way would have been to included this source code in BUILD_LIBJVM. + JVM_OFFSETS_CFLAGS := -m64 + ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_OFFSETS_CFLAGS += -xarch=sparc + endif + + $(JVM_OFFSETS_OBJ): $(JVM_OFFSETS_CPP) $(JVM_OFFSETS_H) + $(call LogInfo, Compiling dtrace file JvmOffsets.cpp (for libjvm.so)) + $(call ExecuteWithLog, $@, $(CXX) -c -I$( $@ + + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + ciEnv.o \ + classLoadingService.o \ + compileBroker.o \ + hashtable.o \ + instanceKlass.o \ + java.o \ + jni.o \ + jvm.o \ + memoryManager.o \ + nmethod.o \ + objectMonitor.o \ + runtimeService.o \ + sharedRuntime.o \ + synchronizer.o \ + thread.o \ + unsafe.o \ + vmThread.o \ + vmGCOperations.o \ + ) + + ifeq ($(call check-jvm-feature, all-gcs), true) + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + vmCMSOperations.o \ + vmPSOperations.o \ + ) + endif + + DTRACE_FLAGS := -64 -G + DTRACE_CPP_FLAGS := -D_LP64 + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.d $(DTRACE_INSTRUMENTED_OBJS) + $(call LogInfo, Generating $(@F) from $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \ + -s $(DTRACE_SUPPORT_DIR)/$(@F).d $(sort $(DTRACE_INSTRUMENTED_OBJS))) + + ############################################################################ + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so. + + # Unfortunately dtrace generates incorrect types for some symbols in + # dtrace_jhelper.o, resulting in "warning: symbol X has differing types" + # This is tracked in JDK-6890703. + $(DTRACE_JHELPER_OBJ): $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace/jhelper.d \ + $(JVM_OFFSETS_INDEX_H) + $(call LogInfo, Running dtrace for $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + # $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \ + # -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + ############################################################################ + # Build the stand-alone dtrace libraries + + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace + + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ + LIBRARY := jvm_dtrace, \ + OUTPUT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := jvm_dtrace.c, \ + CFLAGS := -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := $(LIBDL) -lc -lthread -ldoor, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_dtrace/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db + + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by + # the old build. + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ + LIBRARY := jvm_db, \ + OUTPUT_DIR := $(LIBJVM_DB_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := libjvm_db.c, \ + CFLAGS := -I$(JVM_VARIANT_OUTPUTDIR)/gensrc -I$(DTRACE_SUPPORT_DIR) \ + -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := -lc, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_db/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + # We need the generated JvmOffsets.h before we can compile the libjvm_db source code. + $(BUILD_LIBJVM_DB_ALL_OBJS): $(JVM_OFFSETS_H) + + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB) + endif +endif diff --git a/hotspot/makefiles/lib/CompileDtracePreJvm.gmk b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk new file mode 100644 index 00000000000..20e3aa9be7d --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +ifeq ($(call check-jvm-feature, dtrace), true) + ifeq ($(OPENJDK_TARGET_OS), solaris) + # These files are are generated by CompileDtrace.gmk but consumed by + # CompileJvm.gmk + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o + JVM_OFFSETS_OBJ := $(JVM_OUTPUTDIR)/objs/JvmOffsets.o + + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ) $(JVM_OFFSETS_OBJ) + endif +endif diff --git a/hotspot/makefiles/lib/CompileJvm.gmk b/hotspot/makefiles/lib/CompileJvm.gmk new file mode 100644 index 00000000000..b6404cf74b1 --- /dev/null +++ b/hotspot/makefiles/lib/CompileJvm.gmk @@ -0,0 +1,242 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +# Include support files that will setup compiler flags due to the selected +# jvm feature set, and specific file overrides. +include lib/JvmFeatures.gmk +include lib/JvmOverrideFiles.gmk + +$(eval $(call IncludeCustomExtension, hotspot, lib/CompileJvm.gmk)) + +################################################################################ +# Setup compilation of the main Hotspot native library (libjvm). + +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_MAPFILE := $(JVM_OUTPUTDIR)/mapfile + +################################################################################ +# Platform independent setup + +# This variable may be added to by a custom extension +JVM_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + +JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \ + $d/share/vm \ + $d/os/$(HOTSPOT_TARGET_OS)/vm \ + $d/os/$(HOTSPOT_TARGET_OS_TYPE)/vm \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + ))) \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles \ + # + +JVM_CFLAGS_INCLUDES += \ + $(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \ + -I$(JVM_VARIANT_OUTPUTDIR)/gensrc \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/precompiled \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/prims \ + # + +JVM_CFLAGS_TARGET_DEFINES += \ + -DTARGET_OS_FAMILY_$(HOTSPOT_TARGET_OS) \ + -DTARGET_ARCH_MODEL_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_OS_ARCH_MODEL_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_OS_ARCH_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ + -D$(HOTSPOT_TARGET_CPU_DEFINE) \ + -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ + # + +ifeq ($(DEBUG_LEVEL), release) + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) + JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT + endif +else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT + ifeq ($(filter $(OPENJDK_TARGET_OS), windows aix), ) + # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. + JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS + endif +else ifeq ($(DEBUG_LEVEL), slowdebug) + # _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler + JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_ +endif + +JVM_CFLAGS += \ + $(JVM_CFLAGS_DEBUGLEVEL) \ + $(JVM_CFLAGS_TARGET_DEFINES) \ + $(JVM_CFLAGS_FEATURES) \ + $(JVM_CFLAGS_INCLUDES) \ + $(EXTRA_CFLAGS) \ + # + +JVM_LDFLAGS += \ + $(SHARED_LIBRARY_FLAGS) \ + $(JVM_LDFLAGS_FEATURES) \ + $(EXTRA_LDFLAGS) \ + # + +JVM_LIBS += \ + $(JVM_LIBS_FEATURES) \ + # + +# These files and directories are always excluded +JVM_EXCLUDE_FILES += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp args.cc +JVM_EXCLUDES += adlc + +# Needed by vm_version.cpp +ifeq ($(OPENJDK_TARGET_CPU), x86_64) + OPENJDK_TARGET_CPU_VM_VERSION := amd64 +else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + OPENJDK_TARGET_CPU_VM_VERSION := sparc +else + OPENJDK_TARGET_CPU_VM_VERSION := $(OPENJDK_TARGET_CPU) +endif + +CFLAGS_VM_VERSION := \ + $(VERSION_CFLAGS) \ + -DHOTSPOT_VERSION_STRING='"$(VERSION_STRING)"' \ + -DDEBUG_LEVEL='"$(DEBUG_LEVEL)"' \ + -DHOTSPOT_BUILD_USER='"$(USERNAME)"' \ + -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"' \ + -DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \ + # + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifeq ($(USE_PRECOMPILED_HEADER), 0) + JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + +################################################################################ +# Platform specific setup + +ifneq ($(filter $(OPENJDK_TARGET_OS), linux macosx windows), ) + JVM_PRECOMPILED_HEADER := $(HOTSPOT_TOPDIR)/src/share/vm/precompiled/precompiled.hpp +endif + +ifneq ($(filter $(OPENJDK_TARGET_OS), macosx aix solaris), ) + # On macosx, aix and solaris we have to link with the C++ compiler + JVM_TOOLCHAIN := TOOLCHAIN_LINK_CXX +else + JVM_TOOLCHAIN := TOOLCHAIN_DEFAULT +endif + +ifeq ($(OPENJDK_TARGET_CPU), x86) + JVM_EXCLUDE_PATTERNS += x86_64 +else ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_EXCLUDE_PATTERNS += x86_32 +endif + +# Inline assembly for solaris +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_x86/vm/solaris_x86_64.il + else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_sparc/vm/solaris_sparc.il + endif +endif + +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), false) + # NOTE: In the old build, we weirdly enough set -g/-g0 always, regardless + # of if debug symbols were needed. Without it, compilation fails on + # sparc! :-( + JVM_CFLAGS += -g0 + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + RC_DESC := 64-Bit$(SPACE) + endif + JVM_RCFLAGS += -D"HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(RC_DESC)$(JVM_VARIANT) VM" +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: The old build did not strip binaries on macosx. + JVM_STRIP_SYMBOLS := false +else + JVM_STRIP_SYMBOLS := true +endif + +JVM_OPTIMIZATION ?= HIGHEST_JVM + +################################################################################ +# Now set up the actual compilation of the main hotspot native library + +$(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ + TOOLCHAIN := $(JVM_TOOLCHAIN), \ + LIBRARY := jvm, \ + OUTPUT_DIR := $(JVM_OUTPUTDIR), \ + SRC := $(JVM_SRC_DIRS), \ + EXCLUDES := $(JVM_EXCLUDES), \ + EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \ + EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \ + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \ + CFLAGS := $(JVM_CFLAGS), \ + CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ + DISABLED_WARNINGS_clang := delete-non-virtual-dtor dynamic-class-memaccess \ + empty-body format logical-op-parentheses parentheses \ + parentheses-equality switch tautological-compare, \ + DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \ + 1540-1088 1500-010, \ + ASFLAGS := $(JVM_ASFLAGS), \ + LDFLAGS := $(JVM_LDFLAGS), \ + LIBS := $(JVM_LIBS), \ + OPTIMIZATION := $(JVM_OPTIMIZATION), \ + OBJECT_DIR := $(JVM_OUTPUTDIR)/objs, \ + MAPFILE := $(JVM_MAPFILE), \ + USE_MAPFILE_FOR_SYMBOLS := true, \ + STRIP_SYMBOLS := $(JVM_STRIP_SYMBOLS), \ + EMBED_MANIFEST := true, \ + RC_FLAGS := $(JVM_RCFLAGS), \ + VERSIONINFO_RESOURCE := $(HOTSPOT_TOPDIR)/src/os/windows/vm/version.rc, \ + PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \ + PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \ +)) + +# AIX warning explanation: +# 1500-010 : (W) WARNING in ...: Infinite loop. Program may not stop. +# There are several infinite loops in the vm, so better suppress. +# 1540-0198 : (W) The omitted keyword "private" is assumed for base class "...". +# 1540-0216 : (W) An expression of type .. cannot be converted to type .. +# In hotspot this fires for functionpointer to pointer conversions +# 1540-1088 : (W) The exception specification is being ignored. +# In hotspot this is caused by throw() in declaration of new() in nmethod.hpp. +# 1540-1090 : (I) The destructor of "..." might not be called. +# 1540-1639 : (I) The behavior of long type bit fields has changed ... + +# Include mapfile generation. It relies on BUILD_LIBJVM_ALL_OBJS which is only +# defined after the above call to BUILD_LIBJVM. Mapfile will be generated +# after all object files are built, but before the jvm library is linked. +include lib/JvmMapfile.gmk + +TARGETS += $(BUILD_LIBJVM) diff --git a/hotspot/makefiles/lib/CompileLibjsig.gmk b/hotspot/makefiles/lib/CompileLibjsig.gmk new file mode 100644 index 00000000000..ba9791cdef8 --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibjsig.gmk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +################################################################################ +# Create the libjsig.so shared library + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +ifneq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(STATIC_BUILD), false) + LIBJSIG_STRIP_SYMBOLS := true + ifeq ($(OPENJDK_TARGET_OS), linux) + LIBJSIG_CFLAGS := -fPIC -D_GNU_SOURCE -D_REENTRANT $(EXTRA_CFLAGS) + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) $(EXTRA_CFLAGS) + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + # Flags for other CPUs can be provided in EXTRA_CFLAGS + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + LIBJSIG_CPU_FLAGS := -m64 + else ifeq ($(OPENJDK_TARGET_CPU), x86) + LIBJSIG_CPU_FLAGS := -m32 -march=i586 + endif + + else ifeq ($(OPENJDK_TARGET_OS), solaris) + LIBJSIG_CFLAGS := -m64 -KPIC -mt + LIBJSIG_LDFLAGS := -m64 -mt -xnolib + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), aix) + LIBJSIG_CFLAGS := -q64 -D_GNU_SOURCE -D_REENTRANT -qpic=large + LIBJSIG_LDFLAGS := -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath -bernotok + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIBJSIG_CFLAGS := -m64 -D_GNU_SOURCE -pthread -mno-omit-leaf-frame-pointer -mstack-alignment=16 -fPIC + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) + # NOTE: This lib is not stripped on macosx in old build. Looks like a mistake. + LIBJSIG_STRIP_SYMBOLS := false + else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in CompileLibjsig.gmk) + endif + + LIBJSIG_SRC_FILE := $(HOTSPOT_TOPDIR)/src/os/$(HOTSPOT_TARGET_OS)/vm/jsig.c + LIBJSIG_MAPFILE := $(wildcard $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) + LIBJSIG_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/libjsig + + LIBJSIG_LDFLAGS += $(SHARED_LIBRARY_FLAGS) + + $(eval $(call SetupNativeCompilation, BUILD_LIBJSIG, \ + LIBRARY := jsig, \ + EXTRA_FILES := $(LIBJSIG_SRC_FILE), \ + OUTPUT_DIR := $(LIBJSIG_OUTPUTDIR), \ + LANG := C, \ + CFLAGS := $(LIBJSIG_CFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LDFLAGS := $(LIBJSIG_LDFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LIBS := $(LIBJSIG_LIBS), \ + MAPFILE := $(LIBJSIG_MAPFILE), \ + OBJECT_DIR := $(LIBJSIG_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := $(LIBJSIG_STRIP_SYMBOLS), \ + )) + + TARGETS += $(BUILD_LIBJSIG) + endif +endif + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileLibraries.gmk b/hotspot/makefiles/lib/CompileLibraries.gmk new file mode 100644 index 00000000000..7a7a1651194 --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibraries.gmk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +include HotspotCommon.gmk + +# The dtrace setup must be done both before and after CompileJvm.gmk, due to +# intricate dependencies. +include lib/CompileDtracePreJvm.gmk +include lib/CompileJvm.gmk +include lib/CompileDtracePostJvm.gmk + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/JvmFeatures.gmk b/hotspot/makefiles/lib/JvmFeatures.gmk new file mode 100644 index 00000000000..40a3247c9a7 --- /dev/null +++ b/hotspot/makefiles/lib/JvmFeatures.gmk @@ -0,0 +1,144 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmFeatures.gmk)) + +################################################################################ +# Setup CFLAGS and EXCLUDES for the libjvm compilation, depending on which +# jvm features are selected for this jvm variant. + +ifeq ($(call check-jvm-feature, compiler1), true) + JVM_CFLAGS_FEATURES += -DCOMPILER1 +else + JVM_EXCLUDE_PATTERNS += c1_ +endif + +ifeq ($(call check-jvm-feature, compiler2), true) + JVM_CFLAGS_FEATURES += -DCOMPILER2 + JVM_SRC_DIRS += $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles +else + JVM_EXCLUDES += opto libadt + JVM_EXCLUDE_FILES += bcEscapeAnalyzer.cpp ciTypeFlow.cpp + JVM_EXCLUDE_PATTERNS += c2_ runtime_ +endif + +ifeq ($(call check-jvm-feature, zero), true) + JVM_CFLAGS_FEATURES += -DZERO -DCC_INTERP -DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS) + JVM_LIBS_FEATURES += $(LIBFFI_LIBS) +endif + +ifeq ($(call check-jvm-feature, shark), true) + JVM_CFLAGS_FEATURES += -DSHARK $(LLVM_CFLAGS) + JVM_LDFLAGS_FEATURES += $(LLVM_LDFLAGS) + JVM_LIBS_FEATURES += $(LLVM_LIBS) +else + JVM_EXCLUDES += shark +endif + +ifeq ($(call check-jvm-feature, minimal), true) + JVM_CFLAGS_FEATURES += -DMINIMAL_JVM -DVMTYPE=\"Minimal\" +endif + +ifeq ($(call check-jvm-feature, dtrace), true) + JVM_CFLAGS_FEATURES += -DDTRACE_ENABLED +endif + +ifeq ($(call check-jvm-feature, static-build), true) + JVM_CFLAGS_FEATURES += -DSTATIC_BUILD=1 +endif + +ifneq ($(call check-jvm-feature, jvmti), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMTI=0 + JVM_EXCLUDE_FILES += jvmtiGetLoadedClasses.cpp jvmtiThreadState.cpp jvmtiExtensions.cpp \ + jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \ + jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \ + jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \ + jvmtiClassFileReconstituter.cpp +endif + +ifneq ($(call check-jvm-feature, jvmci), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMCI=0 + JVM_EXCLUDES += jvmci + JVM_EXCLUDE_FILES += jvmciCodeInstaller_$(HOTSPOT_TARGET_CPU_ARCH).cpp +endif + +ifneq ($(call check-jvm-feature, fprof), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_FPROF=0 + JVM_EXCLUDE_FILES += fprofiler.cpp +endif + +ifneq ($(call check-jvm-feature, vm-structs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_VM_STRUCTS=0 + JVM_EXCLUDE_FILES += vmStructs.cpp +endif + +ifneq ($(call check-jvm-feature, jni-check), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JNI_CHECK=0 + JVM_EXCLUDE_FILES += jniCheck.cpp +endif + +ifneq ($(call check-jvm-feature, services), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_SERVICES=0 + JVM_EXCLUDE_FILES += heapDumper.cpp heapInspection.cpp \ + attachListener_$(HOTSPOT_TARGET_OS).cpp attachListener.cpp +endif + +ifneq ($(call check-jvm-feature, management), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_MANAGEMENT=0 +endif + +ifneq ($(call check-jvm-feature, cds), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0 + JVM_EXCLUDE_FILES += \ + classListParser.cpp \ + classLoaderExt.cpp \ + filemap.cpp \ + metaspaceShared.cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU).cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU_ARCH).cpp \ + sharedClassUtil.cpp \ + sharedPathsMiscInfo.cpp \ + systemDictionaryShared.cpp \ + # +endif + +ifneq ($(call check-jvm-feature, all-gcs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_ALL_GCS=0 + JVM_EXCLUDE_PATTERNS += \ + cms/ g1/ parallel/ + JVM_EXCLUDE_FILES += \ + concurrentGCThread.cpp \ + plab.cpp + JVM_EXCLUDE_FILES += \ + g1MemoryPool.cpp \ + psMemoryPool.cpp +endif + +ifneq ($(call check-jvm-feature, nmt), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_NMT=0 + JVM_EXCLUDE_FILES += \ + memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \ + memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp +endif diff --git a/hotspot/makefiles/lib/JvmMapfile.gmk b/hotspot/makefiles/lib/JvmMapfile.gmk new file mode 100644 index 00000000000..9d7655b26ee --- /dev/null +++ b/hotspot/makefiles/lib/JvmMapfile.gmk @@ -0,0 +1,172 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmMapfile.gmk)) + +################################################################################ +# Combine a list of static symbols + +ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), windows-x86_64) + # On Windows x86_64, we should not have any symbols at all, since that + # results in duplicate warnings from the linker (JDK-8043491). + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-shared +endif + +ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-unix +endif + +ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS) +endif + +ifneq ($(findstring debug, $(DEBUG_LEVEL)), ) + ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(call check-jvm-feature, dtrace), true) + # Additional mapfiles that are only used when dtrace is enabled + ifeq ($(call check-jvm-feature, compiler2), true) + # This also covers the case of compiler1+compiler2. + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler2 + else ifeq ($(call check-jvm-feature, compiler1), true) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler1 + endif + endif +endif + +################################################################################ +# Create a dynamic list of symbols from the built object files. This is highly +# platform dependent. + +ifeq ($(OPENJDK_TARGET_OS), linux) + DUMP_SYMBOLS_CMD := $(NM) --defined-only *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^_ZN9Arguments17SharedArchivePathE$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + DUMP_SYMBOLS_CMD := $(NM) -p *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^__1c.*__vtbl_$$|^gHotSpotVM + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^__1cJArgumentsRSharedArchivePath_$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$2 == "U") next; \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # nm on macosx prints out "warning: nm: no name list" to stderr for + # files without symbols. Hide this, even at the expense of hiding real errors. + DUMP_SYMBOLS_CMD := $(NM) -Uj *.o 2> /dev/null + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +# NOTE: The script is from the old build. It is broken and finds no symbols. +# The script below might be what was intended, but it failes to link with tons +# of 'cannot export hidden symbol vtable for X'. +# '{ if ($$1 ~ /^__ZTV/ || $$1 ~ /^_gHotSpotVM/) print substr($$1, 2) }' +else ifeq ($(OPENJDK_TARGET_OS), aix) + # NOTE: The old build had the solution below. This should to be fixed in + # configure instead. + + # On AIX we have to prevent that we pick up the 'nm' version from the GNU binutils + # which may be installed under /opt/freeware/bin. So better use an absolute path here! + # NM=/usr/bin/nm + + DUMP_SYMBOLS_CMD := $(NM) -X64 -B -C *.o + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if (($$2="d" || $$2="D") && ($$3 ~ /^__vft/ || $$3 ~ /^gHotSpotVM/)) print $$3; \ + if ($$3 ~ /^UseSharedSpaces$$/) print $$3; \ + if ($$3 ~ /^SharedArchivePath__9Arguments$$/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), windows) + DUMP_SYMBOLS_CMD := $(DUMPBIN) -symbols *.obj + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$7 ~ /??_7.*@@6B@/ && $$7 !~ /type_info/) print $$7; \ + }' + +else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in JvmMapfile.gmk) +endif + +# A more correct solution would be to send BUILD_LIBJVM_ALL_OBJS instead of +# cd && *.o, but this will result in very long command lines, which is +# problematic on some platforms. +$(JVM_OUTPUTDIR)/symbols-objects: $(BUILD_LIBJVM_ALL_OBJS) + $(call LogInfo, Generating symbol list from object files) + $(CD) $(JVM_OUTPUTDIR)/objs && \ + $(DUMP_SYMBOLS_CMD) | $(NAWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@ + +SYMBOLS_SRC += $(JVM_OUTPUTDIR)/symbols-objects + +################################################################################ +# Now concatenate all symbol lists into a single file and remove comments. + +$(JVM_OUTPUTDIR)/symbols: $(SYMBOLS_SRC) + $(SED) -e '/^#/d' $^ > $@ + +################################################################################ +# Finally convert the symbol list into a platform-specific mapfile + +$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols + $(call LogInfo, Creating mapfile) + $(RM) $@ + ifeq ($(OPENJDK_TARGET_OS), macosx) + # On macosx, we need to add a leading underscore + $(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp + else ifeq ($(OPENJDK_TARGET_OS), windows) + # On windows, add an 'EXPORTS' header + $(ECHO) "EXPORTS" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp + else + # Assume standard linker script + $(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp + $(PRINTF) " local: \n *; \n }; \n" >> $@.tmp + endif + $(MV) $@.tmp $@ diff --git a/hotspot/makefiles/lib/JvmOverrideFiles.gmk b/hotspot/makefiles/lib/JvmOverrideFiles.gmk new file mode 100644 index 00000000000..1ffcb7455ce --- /dev/null +++ b/hotspot/makefiles/lib/JvmOverrideFiles.gmk @@ -0,0 +1,168 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmOverrideFiles.gmk)) + +################################################################################ +# This file contains explicit overrides of CFLAGS and/or precompiled header +# status for individual files on specific platforms. + +ifeq ($(TOOLCHAIN_TYPE), gcc) + BUILD_LIBJVM_vmStructs.cpp_CXXFLAGS := -fno-var-tracking-assignments -O0 +endif + +ifeq ($(OPENJDK_TARGET_OS), linux) + BUILD_LIBJVM_ostream.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64 + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + + ifeq ($(TOOLCHAIN_TYPE), clang) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + # + endif + endif + + ifeq ($(OPENJDK_TARGET_CPU), x86) + # Performance measurements show that by compiling GC related code, we could + # significantly reduce the GC pause time on 32 bit Linux/Unix platforms by + # compiling without the PIC flag (-fPIC on linux). + # See 6454213 for more details. + ALL_SRC := $(filter %.cpp, $(call CacheFind, $(HOTSPOT_TOPDIR)/src/share/vm)) + NONPIC_FILTER := $(addsuffix %, $(addprefix $(HOTSPOT_TOPDIR)/src/share/vm/, \ + memory oops gc)) + # Due to what looks like a bug in the old build implementation of this, add a + # couple of more files that were accidentally matched as substrings of GC related + # files. + NONPIC_SRC := $(filter $(NONPIC_FILTER), $(ALL_SRC)) globals.cpp location.cpp + # Declare variables for each source file that needs the pic flag like this: + # BUILD_JVM__CXXFLAGS := -fno-PIC + # This will get implicitly picked up by SetupNativeCompilation below. + $(foreach s, $(NONPIC_SRC), $(eval BUILD_LIBJVM_$(notdir $s)_CXXFLAGS := -fno-PIC)) + endif + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + ifneq ($(DEBUG_LEVEL), slowdebug) + # Workaround for a bug in dtrace. If ciEnv::post_compiled_method_load_event() + # is inlined, the resulting dtrace object file needs a reference to this + # function, whose symbol name is too long for dtrace. So disable inlining + # for this method for now. (fix this when dtrace bug 6258412 is fixed) + BUILD_LIBJVM_ciEnv.cpp_CXXFLAGS := \ + -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ + # dtrace cannot handle tail call optimization (6672627, 6693876) + BUILD_LIBJVM_jni.cpp_CXXFLAGS := -Qoption ube -O~yz + BUILD_LIBJVM_stubGenerator_$(HOTSPOT_TARGET_CPU).cpp_CXXFLAGS := -xspace + + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + # Temporary until SS10 C++ compiler is fixed + BUILD_LIBJVM_generateOptoStub.cpp_CXXFLAGS := -xO2 + # Temporary util SS12u1 C++ compiler is fixed + BUILD_LIBJVM_c1_LinearScan.cpp_CXXFLAGS := -xO2 + endif + endif + + # Need extra inlining to get oop_ps_push_contents functions to perform well enough. + ifeq ($(DEBUG_LEVEL),release) + BUILD_LIBJVM_psPromotionManager.cpp_CXXFLAGS := -W2,-Ainline:inc=1000 + endif + + ifeq ($(DEBUG_LEVEL), fastdebug) + # this hangs in iropt now (7113504) + BUILD_LIBJVM_compileBroker.cpp_CXXFLAGS := -xO2 + + # Frame size > 100k if we allow inlining via -g0! + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS := +d + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS := +d + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + # ube explodes on x86 + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS += -xO1 + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS += -xO1 + endif + + endif + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # The copied fdlibm routines in these files must not be optimized + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifeq ($(TOOLCHAIN_TYPE), clang) + # NOTE: The old build tested clang version to make sure this workaround + # for the clang bug was still needed. + BUILD_LIBJVM_loopTransform.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifneq ($(DEBUG_LEVEL), slowdebug) + BUILD_LIBJVM_unsafe.cpp_CXXFLAGS := -O1 + endif + + # The following files are compiled at various optimization + # levels due to optimization issues encountered at the + # default level. The Clang compiler issues a compile + # time error if there is an optimization level specification + # skew between the PCH file and the C++ file. Especially if the + # PCH file is compiled at a higher optimization level than + # the C++ file. One solution might be to prepare extra optimization + # level specific PCH files for the opt build and use them here, but + # it's probably not worth the effort as long as only a few files + # need this special handling. + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + loopTransform.cpp \ + unsafe.cpp \ + jvmciCompilerToVM.cpp \ + # + endif + +else ifeq ($(OPENJDK_TARGET_OS), aix) + BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -qnoinline + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + # Disable aggressive optimizations for functions in sharedRuntimeTrig.cpp + # and sharedRuntimeTrans.cpp on ppc64. + # -qstrict turns off the following optimizations: + # * Performing code motion and scheduling on computations such as loads + # and floating-point computations that may trigger an exception. + # * Relaxing conformance to IEEE rules. + # * Reassociating floating-point expressions. + # When using '-qstrict' there still remains one problem + # in javasoft.sqe.tests.api.java.lang.Math.sin5Tests when run in compile-all + # mode, so don't optimize sharedRuntimeTrig.cpp at all. + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + + # Disable ELF decoder on AIX (AIX uses XCOFF). + JVM_EXCLUDE_PATTERNS += elf + +else ifeq ($(OPENJDK_TARGET_OS), windows) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + bytecodeInterpreter.cpp \ + bytecodeInterpreterWithChecks.cpp \ + opcodes.cpp \ + os_windows.cpp \ + os_windows_x86.cpp \ + osThread_windows.cpp \ + # +endif diff --git a/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris new file mode 100644 index 00000000000..ddb46c050ec --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris @@ -0,0 +1,38 @@ +# +# Copyright (c) 2005, 2013, 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + JVM_begin_signal_setting; + JVM_end_signal_setting; + JVM_get_libjsig_version; + JVM_get_signal_action; + sigaction; + signal; + sigset; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers new file mode 100644 index 00000000000..9ee418d01a2 --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers @@ -0,0 +1,38 @@ +# + +# +# Copyright (c) 2005, 2008, 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Jagent_create; + Jagent_destroy; + Jframe_iter; + #Jget_vframe; + #Jlookup_by_regs; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers new file mode 100644 index 00000000000..f9aaa19ba9d --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers @@ -0,0 +1,37 @@ +# + +# +# Copyright (c) 2006, 2008, 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. +# +# + +# Define library interface for JVM-DTrace interface + +SUNWprivate_1.1 { + global: + jvm_attach; + jvm_get_last_error; + jvm_enable_dtprobes; + jvm_detach; + local: + *; +}; diff --git a/hotspot/makefiles/symbols/symbols-aix b/hotspot/makefiles/symbols/symbols-aix new file mode 100644 index 00000000000..0efd2dba97f --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-aix-debug b/hotspot/makefiles/symbols/symbols-aix-debug new file mode 100644 index 00000000000..10887ab2b61 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix-debug @@ -0,0 +1,26 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_AccessVMBooleanFlag +JVM_AccessVMIntFlag +JVM_VMBreakPoint diff --git a/hotspot/makefiles/symbols/symbols-linux b/hotspot/makefiles/symbols/symbols-linux new file mode 100644 index 00000000000..0efd2dba97f --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-linux @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-macosx b/hotspot/makefiles/symbols/symbols-macosx new file mode 100644 index 00000000000..d0243562b67 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-macosx @@ -0,0 +1,24 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_bsd_signal diff --git a/hotspot/makefiles/symbols/symbols-shared b/hotspot/makefiles/symbols/symbols-shared new file mode 100644 index 00000000000..5d26d1028c7 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-shared @@ -0,0 +1,35 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +AsyncGetCallTrace +jio_fprintf +jio_printf +jio_snprintf +jio_vfprintf +jio_vsnprintf +JNI_CreateJavaVM +JNI_GetCreatedJavaVMs +JNI_GetDefaultJavaVMInitArgs +JVM_FindClassFromBootLoader +JVM_GetVersionInfo +JVM_InitAgentProperties diff --git a/hotspot/makefiles/symbols/symbols-solaris b/hotspot/makefiles/symbols/symbols-solaris new file mode 100644 index 00000000000..bc6124f83a3 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris @@ -0,0 +1,25 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_solaris_signal +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 new file mode 100644 index 00000000000..4ce7d8e30b2 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 new file mode 100644 index 00000000000..306345e5c29 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ +__1cNExceptionBlobG__vtbl_ +__1cQUncommonTrapBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-unix b/hotspot/makefiles/symbols/symbols-unix new file mode 100644 index 00000000000..5d876710e65 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-unix @@ -0,0 +1,195 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_ActiveProcessorCount +JVM_ArrayCopy +JVM_AssertionStatusDirectives +JVM_CallStackWalk +JVM_ClassDepth +JVM_ClassLoaderDepth +JVM_Clone +JVM_ConstantPoolGetClassAt +JVM_ConstantPoolGetClassAtIfLoaded +JVM_ConstantPoolGetClassRefIndexAt +JVM_ConstantPoolGetDoubleAt +JVM_ConstantPoolGetFieldAt +JVM_ConstantPoolGetFieldAtIfLoaded +JVM_ConstantPoolGetFloatAt +JVM_ConstantPoolGetIntAt +JVM_ConstantPoolGetLongAt +JVM_ConstantPoolGetMemberRefInfoAt +JVM_ConstantPoolGetMethodAt +JVM_ConstantPoolGetMethodAtIfLoaded +JVM_ConstantPoolGetNameAndTypeRefIndexAt +JVM_ConstantPoolGetNameAndTypeRefInfoAt +JVM_ConstantPoolGetSize +JVM_ConstantPoolGetStringAt +JVM_ConstantPoolGetTagAt +JVM_ConstantPoolGetUTF8At +JVM_CountStackFrames +JVM_CurrentClassLoader +JVM_CurrentLoadedClass +JVM_CurrentThread +JVM_CurrentTimeMillis +JVM_DefineClass +JVM_DefineClassWithSource +JVM_DesiredAssertionStatus +JVM_DoPrivileged +JVM_DumpAllStacks +JVM_DumpThreads +JVM_FillInStackTrace +JVM_FillStackFrames +JVM_FindClassFromCaller +JVM_FindClassFromClass +JVM_FindLibraryEntry +JVM_FindLoadedClass +JVM_FindPrimitiveClass +JVM_FindSignal +JVM_FreeMemory +JVM_GC +JVM_GetAllThreads +JVM_GetArrayElement +JVM_GetArrayLength +JVM_GetCallerClass +JVM_GetClassAccessFlags +JVM_GetClassAnnotations +JVM_GetClassConstantPool +JVM_GetClassContext +JVM_GetClassCPEntriesCount +JVM_GetClassCPTypes +JVM_GetClassDeclaredConstructors +JVM_GetClassDeclaredFields +JVM_GetClassDeclaredMethods +JVM_GetClassFieldsCount +JVM_GetClassInterfaces +JVM_GetClassMethodsCount +JVM_GetClassModifiers +JVM_GetClassName +JVM_GetClassNameUTF +JVM_GetClassSignature +JVM_GetClassSigners +JVM_GetClassTypeAnnotations +JVM_GetCPClassNameUTF +JVM_GetCPFieldClassNameUTF +JVM_GetCPFieldModifiers +JVM_GetCPFieldNameUTF +JVM_GetCPFieldSignatureUTF +JVM_GetCPMethodClassNameUTF +JVM_GetCPMethodModifiers +JVM_GetCPMethodNameUTF +JVM_GetCPMethodSignatureUTF +JVM_GetDeclaredClasses +JVM_GetDeclaringClass +JVM_GetEnclosingMethodInfo +JVM_GetFieldIxModifiers +JVM_GetFieldTypeAnnotations +JVM_GetInheritedAccessControlContext +JVM_GetInterfaceVersion +JVM_GetManagement +JVM_GetMethodIxArgsSize +JVM_GetMethodIxByteCode +JVM_GetMethodIxByteCodeLength +JVM_GetMethodIxExceptionIndexes +JVM_GetMethodIxExceptionsCount +JVM_GetMethodIxExceptionTableEntry +JVM_GetMethodIxExceptionTableLength +JVM_GetMethodIxLocalsCount +JVM_GetMethodIxMaxStack +JVM_GetMethodIxModifiers +JVM_GetMethodIxNameUTF +JVM_GetMethodIxSignatureUTF +JVM_GetMethodParameters +JVM_GetMethodTypeAnnotations +JVM_GetNanoTimeAdjustment +JVM_GetPrimitiveArrayElement +JVM_GetProtectionDomain +JVM_GetSimpleBinaryName +JVM_GetStackAccessControlContext +JVM_GetStackTraceElements +JVM_GetSystemPackage +JVM_GetSystemPackages +JVM_GetTemporaryDirectory +JVM_GetVmArguments +JVM_Halt +JVM_HoldsLock +JVM_IHashCode +JVM_InitProperties +JVM_InternString +JVM_Interrupt +JVM_InvokeMethod +JVM_IsArrayClass +JVM_IsConstructorIx +JVM_IsInterface +JVM_IsInterrupted +JVM_IsPrimitiveClass +JVM_IsSameClassPackage +JVM_IsSupportedJNIVersion +JVM_IsThreadAlive +JVM_IsVMGeneratedMethodIx +JVM_LatestUserDefinedLoader +JVM_LoadLibrary +JVM_MaxMemory +JVM_MaxObjectInspectionAge +JVM_MonitorNotify +JVM_MonitorNotifyAll +JVM_MonitorWait +JVM_MoreStackWalk +JVM_NanoTime +JVM_NativePath +JVM_NewArray +JVM_NewInstanceFromConstructor +JVM_NewMultiArray +JVM_RaiseSignal +JVM_RawMonitorCreate +JVM_RawMonitorDestroy +JVM_RawMonitorEnter +JVM_RawMonitorExit +JVM_RegisterSignal +JVM_ReleaseUTF +JVM_ResumeThread +JVM_SetArrayElement +JVM_SetClassSigners +JVM_SetMethodInfo +JVM_SetNativeThreadName +JVM_SetPrimitiveArrayElement +JVM_SetThreadPriority +JVM_Sleep +JVM_StartThread +JVM_StopThread +JVM_SupportsCX8 +JVM_SuspendThread +JVM_TotalMemory +JVM_UnloadLibrary +JVM_Yield + +# Module related API's +JVM_AddModuleExports +JVM_AddModuleExportsToAll +JVM_AddModuleExportsToAllUnnamed +JVM_AddModulePackage +JVM_AddReadsModule +JVM_CanReadModule +JVM_DefineModule +JVM_IsExportedToModule +JVM_SetBootLoaderUnnamedModule +JVM_GetModuleByPackageName From e1a8c2d19748b50038ca5eacc4b631f3254c546c Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 8 Apr 2016 15:36:34 +0200 Subject: [PATCH 056/113] 8153731: Increase max tag combinations for UL expression (config) Reviewed-by: stefank, mlarsson --- hotspot/src/share/vm/logging/log.cpp | 9 +++++++++ hotspot/src/share/vm/logging/logTagLevelExpression.hpp | 7 +++++-- hotspot/src/share/vm/logging/logTagSet.hpp | 4 ++++ hotspot/src/share/vm/utilities/internalVMTests.cpp | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index e37d83a7cc9..6621b0325a3 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -32,6 +32,8 @@ #include "logging/log.hpp" #include "logging/logConfiguration.hpp" #include "logging/logOutput.hpp" +#include "logging/logTagLevelExpression.hpp" +#include "logging/logTagSet.hpp" #include "logging/logStream.inline.hpp" #include "memory/resourceArea.hpp" @@ -44,6 +46,13 @@ #define assert_char_not_in(c, s) \ assert(strchr(s, c) == NULL, "Expected '%s' to *not* contain character '%c'", s, c) +void Test_log_tag_combinations_limit() { + assert(LogTagLevelExpression::MaxCombinations > LogTagSet::ntagsets(), + "Combination limit (" SIZE_FORMAT ") not sufficient " + "for configuring all available tag sets (" SIZE_FORMAT ")", + LogTagLevelExpression::MaxCombinations, LogTagSet::ntagsets()); +} + class TestLogFile { private: char file_name[256]; diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index 1eb27f07517..9a0d7c9cd79 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -36,9 +36,12 @@ class LogTagSet; // Class used to temporary encode a 'what'-expression during log configuration. // Consists of a combination of tags and levels, e.g. "tag1+tag2=level1,tag3*=level2". class LogTagLevelExpression : public StackObj { - friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + public: + static const size_t MaxCombinations = 256; + private: - static const size_t MaxCombinations = 32; + friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + static const char* DefaultExpressionString; size_t _ntags, _ncombinations; diff --git a/hotspot/src/share/vm/logging/logTagSet.hpp b/hotspot/src/share/vm/logging/logTagSet.hpp index 7b193fc9751..60080700d79 100644 --- a/hotspot/src/share/vm/logging/logTagSet.hpp +++ b/hotspot/src/share/vm/logging/logTagSet.hpp @@ -64,6 +64,10 @@ class LogTagSet VALUE_OBJ_CLASS_SPEC { return _list; } + static size_t ntagsets() { + return _ntagsets; + } + LogTagSet* next() { return _next; } diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 9b3df11e27b..63bd284920d 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -67,6 +67,7 @@ void InternalVMTests::run() { run_unit_test(Test_linked_list); run_unit_test(TestChunkedList_test); run_unit_test(JSON_test); + run_unit_test(Test_log_tag_combinations_limit); run_unit_test(Test_logtarget); run_unit_test(Test_logstream); run_unit_test(Test_loghandle); From e9a1251fb36b9d08bf7ae7a2c4ceea730d0eddf2 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 8 Apr 2016 19:39:32 -0400 Subject: [PATCH 057/113] 8033735: make Throwable.backtrace visible to Class.getDeclaredField again Removed old hack to workaround an old crash. Reviewed-by: hseigel, twisti, mchung --- hotspot/src/share/vm/prims/jvm.cpp | 14 ---- .../ThrowableIntrospectionSegfault.java | 80 +++++++++++++++++++ 2 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7665065c9df..7fc617e819f 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1818,9 +1818,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, // Ensure class is linked k->link_class(CHECK_NULL); - // 4496456 We need to filter out java.lang.Throwable.backtrace - bool skip_backtrace = false; - // Allocate result int num_fields; @@ -1831,11 +1828,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } } else { num_fields = k->java_fields_count(); - - if (k() == SystemDictionary::Throwable_klass()) { - num_fields--; - skip_backtrace = true; - } } objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); @@ -1844,12 +1836,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, int out_idx = 0; fieldDescriptor fd; for (JavaFieldStream fs(k); !fs.done(); fs.next()) { - if (skip_backtrace) { - // 4496456 skip java.lang.Throwable.backtrace - int offset = fs.offset(); - if (offset == java_lang_Throwable::get_backtrace_offset()) continue; - } - if (!publicOnly || fs.access_flags().is_public()) { fd.reinitialize(k(), fs.index()); oop field = Reflection::new_field(&fd, CHECK_NULL); diff --git a/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java new file mode 100644 index 00000000000..fd4be6c88e1 --- /dev/null +++ b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033735 + * @summary check backtrace field introspection + * @library /testlibrary + * @run main ThrowableIntrospectionSegfault + */ + +import java.lang.reflect.*; + +public class ThrowableIntrospectionSegfault { + public static void main(java.lang.String[] unused) { + // Construct a throwable object. + Throwable throwable = new Throwable(); + throwable.fillInStackTrace(); + + // Retrieve a reflection handle to the private backtrace field. + Class class1 = throwable.getClass(); + Field field; + try { + field = class1.getDeclaredField("backtrace"); + } + catch (NoSuchFieldException e) { + System.err.println("Can't retrieve field handle Throwable.backtrace: " + e.toString()); + return; + } + field.setAccessible(true); + + // Retrieve the value of the backtrace field. + Object backtrace; + try { + backtrace = field.get(throwable); + } + catch (IllegalAccessException e) { + System.err.println( "Can't retrieve field value for Throwable.backtrace: " + e.toString()); + return; + } + + try { + + // Retrieve the class of throwable.backtrace[0][0]. + Class class2 = ((Object[]) ((Object[]) backtrace)[2])[0].getClass(); + + // Segfault occurs while executing this line, to retrieve the name of + // this class. + String class2Name = class2.getName(); + + System.err.println("class2Name=" + class2Name); + return; // pass! Passes if it doesn't crash. + } catch (ClassCastException e) { + // Passes if it doesn't crash. Also if the backtrace changes this test might get + // ClassCastException and that's ok too. + System.out.println("Catch exception " + e); + return; // pass! Passes if it doesn't crash. + } + } +} From 78a7d2c16985a2f8273b0902ad83aa134795770b Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sat, 9 Apr 2016 12:15:13 +0300 Subject: [PATCH 058/113] 8152679: DeadlockDetectionTest.java fails due to expected output missing Detect OS X and bailout Reviewed-by: sspitsyn, tbell --- hotspot/test/serviceability/sa/DeadlockDetectionTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java index aff1aaf156a..23ce96f6399 100644 --- a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java +++ b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java @@ -80,6 +80,12 @@ public class DeadlockDetectionTest { return; } + if (Platform.isOSX()) { + // Coredump stackwalking is not implemented for Darwin + System.out.println("This test is not expected to work on OS X. Skipping"); + return; + } + if (!LingeredApp.isLastModifiedWorking()) { // Exact behaviour of the test depends on operating system and the test nature, From 7b27547030710dbd8b6cf1e5002201e61be7f937 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sun, 10 Apr 2016 21:34:47 -0400 Subject: [PATCH 059/113] 8151322: Implement os::set_native_thread_name() on Solaris Reviewed-by: sla, kbarrett, gziemski --- hotspot/src/os/solaris/vm/os_solaris.cpp | 19 +++++++++++++++++-- hotspot/src/os/solaris/vm/os_solaris.hpp | 5 ++++- .../share/vm/utilities/globalDefinitions.hpp | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 68f4a58c30a..6a10ba59434 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -161,6 +161,7 @@ address os::Solaris::handler_end; // end pc of thr_sighndlrinfo address os::Solaris::_main_stack_base = NULL; // 4352906 workaround +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL; // "default" initializers for missing libc APIs extern "C" { @@ -441,8 +442,15 @@ static bool assign_distribution(processorid_t* id_array, } void os::set_native_thread_name(const char *name) { - // Not yet implemented. - return; + if (Solaris::_pthread_setname_np != NULL) { + // Only the first 31 bytes of 'name' are processed by pthread_setname_np + // but we explicitly copy into a size-limited buffer to avoid any + // possible overflow. + char buf[32]; + snprintf(buf, sizeof(buf), "%s", name); + buf[sizeof(buf) - 1] = '\0'; + Solaris::_pthread_setname_np(pthread_self(), buf); + } } bool os::distribute_processes(uint length, uint* distribution) { @@ -4410,6 +4418,13 @@ void os::init(void) { // the minimum of what the OS supports (thr_min_stack()), and // enough to allow the thread to get to user bytecode execution. Solaris::min_stack_allowed = MAX2(thr_min_stack(), Solaris::min_stack_allowed); + + // retrieve entry point for pthread_setname_np + void * handle = dlopen("libc.so.1", RTLD_LAZY); + if (handle != NULL) { + Solaris::_pthread_setname_np = + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np"); + } } // To install functions for atexit system call diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 777e63c8f75..12f72247168 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,9 @@ class Solaris { static int _SIGasync; // user-overridable ASYNC_SIGNAL static void set_SIGasync(int newsig) { _SIGasync = newsig; } + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*); + static pthread_setname_np_func_t _pthread_setname_np; + public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3fa2c942f13..5a080626ada 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -328,7 +328,7 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) { // so far from the middle of the road that it is likely to be problematic in // many C++ compilers. // -#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value))) +#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast(value)) #define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((address_word)(func_ptr))) // Unsigned byte types for os and stream.hpp From 3a4f4362a6411e01320281dd8e8b2727d52c29d4 Mon Sep 17 00:00:00 2001 From: Cheleswer Sahu Date: Mon, 11 Apr 2016 12:50:08 +0000 Subject: [PATCH 060/113] 8153319: new test serviceability/tmtools/jstack/JstackThreadTest.java fails Reviewed-by: dsamersoff, lmesnik --- .../tmtools/jstack/JstackThreadTest.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java index b1e3ed3f2a8..6ca81885814 100644 --- a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java +++ b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java @@ -25,6 +25,8 @@ import java.util.Arrays; import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.ProcessTools; +import utils.Utils; +import java.util.concurrent.CountDownLatch; /* * @test JstackThreadTest @@ -32,23 +34,22 @@ import jdk.test.lib.ProcessTools; * @summary jstack doesn't close quotation marks properly with threads' name greater than 1996 characters * @library /testlibrary * @build jdk.test.lib.* - * @ignore 8153319 * @run main JstackThreadTest */ public class JstackThreadTest { static class NamedThread extends Thread { - NamedThread(String name) { + CountDownLatch latch; + NamedThread(String name, CountDownLatch latch) { + this.latch = latch; setName(name); + } @Override public void run() { - try { - Thread.sleep(2000); - } catch(Exception e){ - e.printStackTrace(); - } - } + latch.countDown(); + Utils.sleep(); } + } public static void main(String[] args) throws Exception { StringBuilder sb = new StringBuilder(); @@ -60,8 +61,11 @@ public class JstackThreadTest { } private static void testWithName(String name) throws Exception { + //parent thread countDown latch + CountDownLatch latch = new CountDownLatch(1); // Start a thread with a long thread name - NamedThread thread = new NamedThread(name); + NamedThread thread = new NamedThread(name, latch); + thread.setDaemon(true); thread.start(); ProcessBuilder processBuilder = new ProcessBuilder(); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstack"); @@ -69,6 +73,8 @@ public class JstackThreadTest { launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); + // Ensuring that Jstack will always run after NamedThread + latch.await(); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); System.out.println(output.getOutput()); output.shouldContain("\""+ name + "\""); From ac0824cbad6dd19d14f1b1c54c856c6ad5033154 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 11 Apr 2016 11:33:52 -0400 Subject: [PATCH 061/113] 8152468: PrintMiscellaneous in constantPool should use classresolve logging Some instances of PrintMiscellaneous have ben replaced by classresolve logging. Reviewed-by: coleenp, rprotacio --- hotspot/src/share/vm/oops/constantPool.cpp | 27 ++++++++++--------- .../runtime/logging/ClassResolutionTest.java | 4 ++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 75a2bf970da..996f5a50eef 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -283,8 +283,9 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM // logging for classresolve tag. - trace_class_resolution(this_cp, k); - + if (log_is_enabled(Debug, classresolve)){ + trace_class_resolution(this_cp, k); + } this_cp->klass_at_put(which, k()); entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); @@ -340,9 +341,7 @@ Method* ConstantPool::method_at_if_loaded(const constantPoolHandle& cpool, int cache_index = decode_cpcache_index(which, true); if (!(cache_index >= 0 && cache_index < cpool->cache()->length())) { // FIXME: should be an assert - if (PrintMiscellaneous && (Verbose||WizardMode)) { - tty->print_cr("bad operand %d in:", which); cpool->print(); - } + log_debug(classresolve)("bad operand %d in:", which); cpool->print(); return NULL; } ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); @@ -672,10 +671,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in int callee_index = this_cp->method_handle_klass_index_at(index); Symbol* name = this_cp->method_handle_name_ref_at(index); Symbol* signature = this_cp->method_handle_signature_ref_at(index); - if (PrintMiscellaneous) - tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", - ref_kind, index, this_cp->method_handle_index_at(index), - callee_index, name->as_C_string(), signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", + ref_kind, index, this_cp->method_handle_index_at(index), + callee_index, name->as_C_string(), signature->as_C_string()); + } KlassHandle callee; { Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL); callee = KlassHandle(THREAD, k); @@ -694,10 +694,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in case JVM_CONSTANT_MethodType: { Symbol* signature = this_cp->method_type_signature_at(index); - if (PrintMiscellaneous) - tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s", - index, this_cp->method_type_index_at(index), - signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodType [%d/%d] %s", + index, this_cp->method_type_index_at(index), + signature->as_C_string()); + } KlassHandle klass(THREAD, this_cp->pool_holder()); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); diff --git a/hotspot/test/runtime/logging/ClassResolutionTest.java b/hotspot/test/runtime/logging/ClassResolutionTest.java index 3c8d6dd7f09..700fc77cb29 100644 --- a/hotspot/test/runtime/logging/ClassResolutionTest.java +++ b/hotspot/test/runtime/logging/ClassResolutionTest.java @@ -51,7 +51,8 @@ public class ClassResolutionTest { }; public static void main(String... args) throws Exception { - Thing1Handler.getThingNumber(); + int x = Thing1Handler.getThingNumber(); + System.out.println("ThingNumber: "+Integer.toString(x)); } } @@ -62,6 +63,7 @@ public class ClassResolutionTest { ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); + o.shouldContain("[classresolve] resolve JVM_CONSTANT_MethodHandle"); // (2) classresolve should turn off. pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug", From cf540ad2aff07c4df7bcd3cce2d9be2f1673e3d7 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 11 Apr 2016 16:10:41 -0400 Subject: [PATCH 062/113] 8145704: Make test for classinit logging more robust 8145704: Make test for classinit logging more robust. Reviewed-by: hseigel, gtriantafill --- .../test/runtime/logging/ClassInitializationTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hotspot/test/runtime/logging/ClassInitializationTest.java b/hotspot/test/runtime/logging/ClassInitializationTest.java index f465ab5775d..a95cc489a3e 100644 --- a/hotspot/test/runtime/logging/ClassInitializationTest.java +++ b/hotspot/test/runtime/logging/ClassInitializationTest.java @@ -62,6 +62,16 @@ public class ClassInitializationTest { out.shouldContain("[Initialized").shouldContain("without side effects]"); out.shouldHaveExitValue(0); } + + // (3) classinit should turn off. + pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=off", + "-Xverify:all", + "-Xmx64m", + "BadMap50"); + out = new OutputAnalyzer(pb.start()); + out.shouldNotContain("[classinit]"); + out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); + } public static class InnerClass { public static void main(String[] args) throws Exception { From 71bcff35cfb9c6cc5d0c36742b14ffdf2a4adb7e Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 063/113] 8153742: Move Thread::current() to thread.hpp Reviewed-by: coleenp, jmasa --- hotspot/src/share/vm/interpreter/abstractInterpreter.hpp | 2 +- hotspot/src/share/vm/interpreter/interpreterRuntime.hpp | 2 +- hotspot/src/share/vm/memory/resourceArea.hpp | 2 +- hotspot/src/share/vm/runtime/javaCalls.hpp | 2 +- hotspot/src/share/vm/runtime/vmThread.hpp | 2 +- hotspot/src/share/vm/utilities/preserveException.hpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index db31ac83400..2c527a8f893 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -28,7 +28,7 @@ #include "asm/macroAssembler.hpp" #include "code/stubs.hpp" #include "interpreter/bytecodes.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" #include "utilities/top.hpp" diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 2039adba2a0..dd4f797b0c7 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -31,7 +31,7 @@ #include "oops/method.hpp" #include "runtime/frame.inline.hpp" #include "runtime/signature.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "utilities/top.hpp" // The InterpreterRuntime is called by the interpreter for everything diff --git a/hotspot/src/share/vm/memory/resourceArea.hpp b/hotspot/src/share/vm/memory/resourceArea.hpp index 65ae36a1646..89ad7457314 100644 --- a/hotspot/src/share/vm/memory/resourceArea.hpp +++ b/hotspot/src/share/vm/memory/resourceArea.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_MEMORY_RESOURCEAREA_HPP #include "memory/allocation.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // The resource area holds temporary data structures in the VM. // The actual allocation areas are thread local. Typical usage: diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index 543e58f0dde..0d885686de8 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -29,7 +29,7 @@ #include "oops/method.hpp" #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" #ifdef TARGET_ARCH_x86 # include "jniTypes_x86.hpp" diff --git a/hotspot/src/share/vm/runtime/vmThread.hpp b/hotspot/src/share/vm/runtime/vmThread.hpp index 43147e53c36..692fbdd164d 100644 --- a/hotspot/src/share/vm/runtime/vmThread.hpp +++ b/hotspot/src/share/vm/runtime/vmThread.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_RUNTIME_VMTHREAD_HPP #include "runtime/perfData.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" // diff --git a/hotspot/src/share/vm/utilities/preserveException.hpp b/hotspot/src/share/vm/utilities/preserveException.hpp index 58f92a876ab..09b3664ef9a 100644 --- a/hotspot/src/share/vm/utilities/preserveException.hpp +++ b/hotspot/src/share/vm/utilities/preserveException.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_UTILITIES_PRESERVEEXCEPTION_HPP #include "runtime/handles.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // This file provides more support for exception handling; see also exceptions.hpp class PreserveExceptionMark { From 2ca745d47ad2450d1cce2b0d3fbd6444dd844cb3 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 064/113] 8152639: ResourceMark missing in reportFreeListStatistics Reviewed-by: pliden, sjohanss --- .../src/share/vm/gc/cms/compactibleFreeListSpace.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index c048f08b4a1..ad651723aef 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -32,6 +32,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/spaceDecorator.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -505,10 +506,13 @@ void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const return; } log.debug("%s", title); - _dictionary->report_statistics(log.debug_stream()); + + LogStream out(log.debug()); + _dictionary->report_statistics(&out); + if (log.is_trace()) { - ResourceMark rm; - reportIndexedFreeListStatistics(log.trace_stream()); + LogStream trace_out(log.trace()); + reportIndexedFreeListStatistics(&trace_out); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); From 388236cc3d9cd233a087e1b57706100026fba93c Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 065/113] 8152962: CMSCollector::shouldConcurrentCollect incorrectly logs against the debug stream Reviewed-by: brutisso, sjohanss --- .../gc/cms/concurrentMarkSweepGeneration.cpp | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 1e7a4991dd3..9e67c9b39e3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -425,7 +425,7 @@ void CMSStats::print_on(outputStream *st) const { st->print(",cms_consumption_rate=%g,time_until_full=%g", cms_consumption_rate(), time_until_cms_gen_full()); } - st->print(" "); + st->cr(); } #endif // #ifndef PRODUCT @@ -1108,8 +1108,10 @@ bool ConcurrentMarkSweepGeneration::should_collect(bool full, } bool CMSCollector::shouldConcurrentCollect() { + LogTarget(Trace, gc) log; + if (_full_gc_requested) { - log_trace(gc)("CMSCollector: collect because of explicit gc request (or GCLocker)"); + log.print("CMSCollector: collect because of explicit gc request (or GCLocker)"); return true; } @@ -1117,21 +1119,22 @@ bool CMSCollector::shouldConcurrentCollect() { // ------------------------------------------------------------------ // Print out lots of information which affects the initiation of // a collection. - Log(gc) log; - if (log.is_trace() && stats().valid()) { - log.trace("CMSCollector shouldConcurrentCollect: "); - ResourceMark rm; - stats().print_on(log.debug_stream()); - log.trace("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); - log.trace("free=" SIZE_FORMAT, _cmsGen->free()); - log.trace("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); - log.trace("promotion_rate=%g", stats().promotion_rate()); - log.trace("cms_allocation_rate=%g", stats().cms_allocation_rate()); - log.trace("occupancy=%3.7f", _cmsGen->occupancy()); - log.trace("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); - log.trace("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); - log.trace("cms_time_since_end=%3.7f", stats().cms_time_since_end()); - log.trace("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); + if (log.is_enabled() && stats().valid()) { + log.print("CMSCollector shouldConcurrentCollect: "); + + LogStream out(log); + stats().print_on(&out); + + log.print("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); + log.print("free=" SIZE_FORMAT, _cmsGen->free()); + log.print("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); + log.print("promotion_rate=%g", stats().promotion_rate()); + log.print("cms_allocation_rate=%g", stats().cms_allocation_rate()); + log.print("occupancy=%3.7f", _cmsGen->occupancy()); + log.print("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); + log.print("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); + log.print("cms_time_since_end=%3.7f", stats().cms_time_since_end()); + log.print("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); } // ------------------------------------------------------------------ @@ -1149,8 +1152,8 @@ bool CMSCollector::shouldConcurrentCollect() { // this branch will not fire after the first successful CMS // collection because the stats should then be valid. if (_cmsGen->occupancy() >= _bootstrap_occupancy) { - log_trace(gc)(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", - _cmsGen->occupancy(), _bootstrap_occupancy); + log.print(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", + _cmsGen->occupancy(), _bootstrap_occupancy); return true; } } @@ -1162,7 +1165,7 @@ bool CMSCollector::shouldConcurrentCollect() { // XXX We need to make sure that the gen expansion // criterion dovetails well with this. XXX NEED TO FIX THIS if (_cmsGen->should_concurrent_collect()) { - log_trace(gc)("CMS old gen initiated"); + log.print("CMS old gen initiated"); return true; } @@ -1173,12 +1176,12 @@ bool CMSCollector::shouldConcurrentCollect() { assert(gch->collector_policy()->is_generation_policy(), "You may want to check the correctness of the following"); if (gch->incremental_collection_will_fail(true /* consult_young */)) { - log_trace(gc)("CMSCollector: collect because incremental collection will fail "); + log.print("CMSCollector: collect because incremental collection will fail "); return true; } if (MetaspaceGC::should_concurrent_collect()) { - log_trace(gc)("CMSCollector: collect for metadata allocation "); + log.print("CMSCollector: collect for metadata allocation "); return true; } @@ -1193,10 +1196,10 @@ bool CMSCollector::shouldConcurrentCollect() { // as we want to be able to trigger the first CMS cycle as well) if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) { if (stats().valid()) { - log_trace(gc)("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", - stats().cms_time_since_begin()); + log.print("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", + stats().cms_time_since_begin()); } else { - log_trace(gc)("CMSCollector: collect because of trigger interval (first collection)"); + log.print("CMSCollector: collect because of trigger interval (first collection)"); } return true; } From 0f89b2e137de3ed8b52bfa5e5b5c0b10656b268c Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 066/113] 8153583: Make OutputAnalyzer.reportDiagnosticSummary public Reviewed-by: brutisso, sjohanss --- .../testlibrary/jdk/test/lib/OutputAnalyzer.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java index 37f0209b288..15f6f53157b 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java +++ b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java @@ -378,14 +378,14 @@ public final class OutputAnalyzer { * - exit code * Note: the command line is printed by the ProcessTools */ - private void reportDiagnosticSummary() { - String msg = - " stdout: [" + stdout + "];\n" + - " stderr: [" + stderr + "]\n" + - " exitValue = " + getExitValue() + "\n"; + public void reportDiagnosticSummary() { + String msg = + " stdout: [" + stdout + "];\n" + + " stderr: [" + stderr + "]\n" + + " exitValue = " + getExitValue() + "\n"; - System.err.println(msg); - } + System.err.println(msg); + } /** From dab21ebd4d19c571f5436431da57590c53446756 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 067/113] 8153658: Redundant memory copy in LogStreamNoResourceMark Reviewed-by: kbarrett, jmasa --- hotspot/src/share/vm/logging/logStream.inline.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/logging/logStream.inline.hpp b/hotspot/src/share/vm/logging/logStream.inline.hpp index b1bff8b53bd..5be4754438d 100644 --- a/hotspot/src/share/vm/logging/logStream.inline.hpp +++ b/hotspot/src/share/vm/logging/logStream.inline.hpp @@ -33,7 +33,8 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); - _tagset->write(_level, "%s", _current_line.as_string()); + _current_line.write("\0", 1); + _tagset->write(_level, "%s", _current_line.base()); _current_line.reset(); } else { _current_line.write(s, len); From 320005909801f9484191c1e1daafef511e548efa Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 068/113] 8153659: Create a CHeap backed LogStream class Reviewed-by: brutisso, mlarsson --- hotspot/src/share/vm/logging/log.cpp | 21 ++++ hotspot/src/share/vm/logging/logHandle.hpp | 4 +- hotspot/src/share/vm/logging/logStream.cpp | 2 +- hotspot/src/share/vm/logging/logStream.hpp | 95 +++++++++++++++++-- .../src/share/vm/logging/logStream.inline.hpp | 55 +---------- 5 files changed, 113 insertions(+), 64 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 6c6566b386e..e37d83a7cc9 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -361,11 +361,32 @@ static void Test_logstream_no_rm() { Test_logstream_helper(stream); } +static void Test_logstreamcheap_log() { + Log(gc) log; + LogStreamCHeap stream(log.debug()); + + Test_logstream_helper(&stream); +} + +static void Test_logstreamcheap_logtarget() { + LogTarget(Debug, gc) log; + LogStreamCHeap stream(log); + + Test_logstream_helper(&stream); +} + void Test_logstream() { + // Test LogStreams with embedded ResourceMark. Test_logstream_log(); Test_logstream_logtarget(); Test_logstream_logstreamhandle(); + + // Test LogStreams without embedded ResourceMark. Test_logstream_no_rm(); + + // Test LogStreams backed by CHeap memory. + Test_logstreamcheap_log(); + Test_logstreamcheap_logtarget(); } void Test_loghandle_on() { diff --git a/hotspot/src/share/vm/logging/logHandle.hpp b/hotspot/src/share/vm/logging/logHandle.hpp index 1f62d96e6f9..41d20609a73 100644 --- a/hotspot/src/share/vm/logging/logHandle.hpp +++ b/hotspot/src/share/vm/logging/logHandle.hpp @@ -67,13 +67,13 @@ public: // This can be used to pass a Log instance as a parameter without // polluting the surrounding API with template functions. class LogTargetHandle { - friend class LogStream; - private: const LogLevelType _level; LogTagSet* _tagset; public: + LogTargetHandle(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} + template LogTargetHandle(const LogTargetImpl& type_carrier) : _level(level), diff --git a/hotspot/src/share/vm/logging/logStream.cpp b/hotspot/src/share/vm/logging/logStream.cpp index b68dca7f056..5c980a7b2ce 100644 --- a/hotspot/src/share/vm/logging/logStream.cpp +++ b/hotspot/src/share/vm/logging/logStream.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "logging/log.hpp" -#include "logging/logStream.hpp" +#include "logging/logStream.inline.hpp" // Create a log stream without an embedded ResourceMark. // The function is placed here to be called out-of-line in log.hpp. diff --git a/hotspot/src/share/vm/logging/logStream.hpp b/hotspot/src/share/vm/logging/logStream.hpp index 38ba83ab3ee..6e7a28ac5d2 100644 --- a/hotspot/src/share/vm/logging/logStream.hpp +++ b/hotspot/src/share/vm/logging/logStream.hpp @@ -26,23 +26,100 @@ #define SHARE_VM_LOGGING_LOGSTREAM_HPP #include "logging/log.hpp" +#include "logging/logHandle.hpp" +#include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -// An output stream that logs to the logging framework. -// Requires a ResourceMark on the stack. -class LogStreamNoResourceMark : public outputStream { -private: - stringStream _current_line; - LogLevelType _level; - LogTagSet* _tagset; +// The base class of an output stream that logs to the logging framework. +template +class LogStreamBase : public outputStream { + streamClass _current_line; + LogTargetHandle _log_handle; public: - LogStreamNoResourceMark(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} - ~LogStreamNoResourceMark() { + // Constructor to support creation from a LogTarget instance. + // + // LogTarget(Debug, gc) log; + // LogStreamBase(log) stream; + template + LogStreamBase(const LogTargetImpl& type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. + // + // LogStreamBase stream(log.debug()); + // or + // LogStreamBase stream((LogTargetImpl*)NULL); + template + LogStreamBase(const LogTargetImpl* type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from a LogTargetHandle. + // + // LogTarget(Debug, gc) log; + // LogTargetHandle(log) handle; + // LogStreamBase stream(handle); + LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {} + + // Constructor to support creation from a log level and tagset. + // + // LogStreamBase(level, tageset); + LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {} + + ~LogStreamBase() { guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?"); } +public: void write(const char* s, size_t len); }; +// A stringStream with an embedded ResourceMark. +class stringStreamWithResourceMark : outputStream { + private: + // The stringStream Resource allocate in the constructor, + // so the order of the fields is important. + ResourceMark _embedded_resource_mark; + stringStream _stream; + + public: + stringStreamWithResourceMark(size_t initial_bufsize = 256) : + _embedded_resource_mark(), + _stream(initial_bufsize) {} + + virtual void write(const char* c, size_t len) { _stream.write(c, len); } + size_t size() { return _stream.size(); } + const char* base() { return _stream.base(); } + void reset() { _stream.reset(); } + char* as_string() { return _stream.as_string(); } +}; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in Resource memory. +// The caller is required to have a ResourceMark on the stack. +typedef LogStreamBase LogStreamNoResourceMark; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in CHeap memory. +typedef LogStreamBase LogStreamCHeap; + +// An output stream that logs to the logging framework, and embeds a ResourceMark. +// +// The backing buffer is allocated in Resource memory. +// The class is intended to be stack allocated. +// The class provides its own ResourceMark, +// so care needs to be taken when nested ResourceMarks are used. +typedef LogStreamBase LogStream; + +// Support creation of a LogStream without having to provide a LogTarget pointer. +#define LogStreamHandle(level, ...) LogStreamTemplate + +template +class LogStreamTemplate : public LogStream { +public: + LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} +}; + #endif // SHARE_VM_LOGGING_LOGSTREAM_HPP diff --git a/hotspot/src/share/vm/logging/logStream.inline.hpp b/hotspot/src/share/vm/logging/logStream.inline.hpp index 5be4754438d..5660a5616bb 100644 --- a/hotspot/src/share/vm/logging/logStream.inline.hpp +++ b/hotspot/src/share/vm/logging/logStream.inline.hpp @@ -30,11 +30,12 @@ #include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -inline void LogStreamNoResourceMark::write(const char* s, size_t len) { +template +inline void LogStreamBase::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); _current_line.write("\0", 1); - _tagset->write(_level, "%s", _current_line.base()); + _log_handle.print("%s", _current_line.base()); _current_line.reset(); } else { _current_line.write(s, len); @@ -42,54 +43,4 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) { update_position(s, len); } -// An output stream that logs to the logging framework, and embeds a ResourceMark. -// -// The class is intended to be stack allocated. -// Care needs to be taken when nested ResourceMarks are used. -class LogStream : public outputStream { -private: - ResourceMark _embedded_resource_mark; - LogStreamNoResourceMark _stream; - -public: - // Constructor to support creation from a LogTarget instance. - // - // LogTarget(Debug, gc) log; - // LogStream(log) stream; - template - LogStream(const LogTargetImpl& type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. - // - // LogStream stream(log.debug()); - // LogStream stream((LogTargetImpl*)NULL); - template - LogStream(const LogTargetImpl* type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from a LogTargetHandle. - // - // LogTarget(Debug, gc) log; - // LogTargetHandle(log) handle; - // LogStream stream(handle); - LogStream(LogTargetHandle handle) : - _embedded_resource_mark(), - _stream(handle._level, handle._tagset) {} - - // Override of outputStream::write. - void write(const char* s, size_t len) { _stream.write(s, len); } -}; - -// Support creation of a LogStream without having to provide a LogTarget pointer. -#define LogStreamHandle(level, ...) LogStreamTemplate - -template -class LogStreamTemplate : public LogStream { -public: - LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} -}; - #endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP From 1afb9e94277c9399488d57996e7f17f3a8aa1c75 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 11 Apr 2016 09:45:03 +0200 Subject: [PATCH 069/113] 8153845: UL log write method missing essential assert Reviewed-by: mlarsson, brutisso --- hotspot/src/share/vm/logging/logTagSet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/logging/logTagSet.cpp b/hotspot/src/share/vm/logging/logTagSet.cpp index db675a26854..96aae628857 100644 --- a/hotspot/src/share/vm/logging/logTagSet.cpp +++ b/hotspot/src/share/vm/logging/logTagSet.cpp @@ -98,6 +98,7 @@ void LogTagSet::write(LogLevelType level, const char* fmt, ...) { const size_t vwrite_buffer_size = 512; void LogTagSet::vwrite(LogLevelType level, const char* fmt, va_list args) { + assert(level >= LogLevel::First && level <= LogLevel::Last, "Log level:%d is incorrect", level); char buf[vwrite_buffer_size]; va_list saved_args; // For re-format on buf overflow. va_copy(saved_args, args); From 19cd9b20e8b929cbb502ce520a644e64665102cd Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Mon, 11 Apr 2016 09:49:10 +0200 Subject: [PATCH 070/113] 8153843: G1CardLiveDataHelper incorrectly sets next_live_bytes on dead humongous regions Reviewed-by: drwhite, tschatzl --- hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp | 10 ++++++++-- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 14 +++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp index 009179150a9..0a2ed25a29b 100644 --- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp @@ -206,8 +206,14 @@ public: return 0; } if (hr->is_humongous()) { - mark_card_bitmap_range(start, hr->top()); - return pointer_delta(hr->top(), start, 1); + HeapRegion* start_region = hr->humongous_start_region(); + if (mark_bitmap->isMarked(start_region->bottom())) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } else { + // Humongous start object was actually dead. + return 0; + } } assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2980eecdc0e..0f33720d7ca 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2946,13 +2946,17 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { : rset->is_empty(); } - bool is_typeArray_region(HeapRegion* region) const { - return oop(region->bottom())->is_typeArray(); - } - bool humongous_region_is_candidate(G1CollectedHeap* heap, HeapRegion* region) const { assert(region->is_starts_humongous(), "Must start a humongous object"); + oop obj = oop(region->bottom()); + + // Dead objects cannot be eager reclaim candidates. Due to class + // unloading it is unsafe to query their classes so we return early. + if (heap->is_obj_dead(obj, region)) { + return false; + } + // Candidate selection must satisfy the following constraints // while concurrent marking is in progress: // @@ -2989,7 +2993,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { // important use case for eager reclaim, and this special handling // may reduce needed headroom. - return is_typeArray_region(region) && is_remset_small(region); + return obj->is_typeArray() && is_remset_small(region); } public: From 8b2f63bd2b054550cc0305f0593e20c79d86a48e Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Mon, 11 Apr 2016 12:22:09 +0200 Subject: [PATCH 071/113] 8146879: Add option for handling existing log files in UL Reviewed-by: dsamersoff, gziemski, rehn --- hotspot/src/os/bsd/vm/os_bsd.cpp | 22 +++ hotspot/src/os/linux/vm/os_linux.cpp | 15 ++ hotspot/src/os/posix/vm/os_posix.cpp | 4 + hotspot/src/os/solaris/vm/os_solaris.cpp | 13 ++ hotspot/src/os/windows/vm/os_windows.cpp | 16 ++ hotspot/src/share/vm/logging/log.cpp | 142 +++++++++++++++++ .../src/share/vm/logging/logConfiguration.cpp | 2 +- .../src/share/vm/logging/logFileOutput.cpp | 143 ++++++++++++++++-- .../src/share/vm/logging/logFileOutput.hpp | 17 ++- .../share/vm/logging/logFileStreamOutput.hpp | 4 +- hotspot/src/share/vm/logging/logOutput.hpp | 2 +- hotspot/src/share/vm/runtime/os.hpp | 3 + .../share/vm/utilities/internalVMTests.cpp | 3 + .../logging/TestLogRotation.java | 6 +- .../logging/TestQuotedLogOutputs.java | 2 +- 15 files changed, 368 insertions(+), 26 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index ce3f6e005fd..78def166e58 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3732,6 +3732,28 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); +#ifdef __APPLE__ + return st.st_mtimespec; +#else + return st.st_mtim; +#endif +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} + + bool os::check_heap(bool force) { return true; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 228ac835ffb..4889870e8f4 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -6008,7 +6008,22 @@ bool os::start_debugging(char *buf, int buflen) { return yes; } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtim; +} +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} /////////////// Unit tests /////////////// diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 6d683eec706..1c6efe5b513 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -181,6 +181,10 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return vsnprintf(buf, len, fmt, args); } +int os::fileno(FILE* fp) { + return ::fileno(fp); +} + void os::Posix::print_load_average(outputStream* st) { st->print("load average:"); double loadavg[3]; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 6a10ba59434..1d68dcc7721 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1827,6 +1827,19 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + static bool _print_ascii_file(const char* filename, outputStream* st) { int fd = ::open(filename, O_RDONLY); if (fd == -1) { diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 72da7bae97b..fa401527ed7 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1594,6 +1594,19 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return ret; } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + void os::print_os_info_brief(outputStream* st) { os::print_os_info(st); } @@ -4589,6 +4602,9 @@ int os::ftruncate(int fd, jlong length) { return 0; } +int os::fileno(FILE* fp) { + return _fileno(fp); +} // This code is a copy of JDK's sysSync // from src/windows/hpi/src/sys_api_md.c diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 6621b0325a3..cdef6d8a7ab 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -31,6 +31,7 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logFileOutput.hpp" #include "logging/logOutput.hpp" #include "logging/logTagLevelExpression.hpp" #include "logging/logTagSet.hpp" @@ -138,6 +139,131 @@ void Test_configure_stdout() { assert_str_eq("all=off", stdoutput->config_string()); } +static size_t number_of_lines_with_substring_in_file(const char* filename, + const char* substr) { + ResourceMark rm; + size_t ret = 0; + FILE* fp = fopen(filename, "r"); + assert(fp != NULL, "error opening file %s: %s", filename, strerror(errno)); + + int buflen = 512; + char* buf = NEW_RESOURCE_ARRAY(char, buflen); + long pos = 0; + + while (fgets(buf, buflen, fp) != NULL) { + if (buf[strlen(buf) - 1] != '\n' && !feof(fp)) { + // retry with a larger buffer + buf = REALLOC_RESOURCE_ARRAY(char, buf, buflen, buflen * 2); + buflen *= 2; + // rewind to beginning of line + fseek(fp, pos, SEEK_SET); + continue; + } + pos = ftell(fp); + if (strstr(buf, substr) != NULL) { + ret++; + } + } + + fclose(fp); + return ret; +} + +static bool file_exists(const char* filename) { + struct stat st; + return os::stat(filename, &st) == 0; +} + +static void delete_file(const char* filename) { + if (!file_exists(filename)) { + return; + } + int ret = remove(filename); + assert(ret == 0, "failed to remove file '%s': %s", filename, strerror(errno)); +} + +static void create_directory(const char* name) { + assert(!file_exists(name), "can't create directory: %s already exists", name); + bool failed; +#ifdef _WINDOWS + failed = !CreateDirectory(name, NULL); +#else + failed = mkdir(name, 0777); +#endif + assert(!failed, "failed to create directory %s", name); +} + +static const char* ExpectedLine = "a (hopefully) unique log line for testing"; + +static void init_file(const char* filename, const char* options = "") { + LogConfiguration::parse_log_arguments(filename, "logging=trace", "", options, + Log(logging)::error_stream()); + log_debug(logging)("%s", ExpectedLine); + LogConfiguration::parse_log_arguments(filename, "all=off", "", "", + Log(logging)::error_stream()); +} + +void Test_log_file_startup_rotation() { + ResourceMark rm; + const size_t rotations = 5; + const char* filename = "start-rotate-test"; + char* rotated_file[rotations]; + for (size_t i = 0; i < rotations; i++) { + size_t len = strlen(filename) + 3; + rotated_file[i] = NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(rotated_file[i], len, "%s." SIZE_FORMAT, filename, i); + delete_file(rotated_file[i]); + }; + + delete_file(filename); + init_file(filename); + assert(file_exists(filename), + "configured logging to file '%s' but file was not found", filename); + + // Initialize the same file a bunch more times to trigger rotations + for (size_t i = 0; i < rotations; i++) { + init_file(filename); + assert(file_exists(rotated_file[i]), "existing file was not rotated"); + } + + // Remove a file and expect its slot to be re-used + delete_file(rotated_file[1]); + init_file(filename); + assert(file_exists(rotated_file[1]), "log file not properly rotated"); + + // Clean up after test + delete_file(filename); + for (size_t i = 0; i < rotations; i++) { + delete_file(rotated_file[i]); + } +} + +void Test_log_file_startup_truncation() { + ResourceMark rm; + const char* filename = "start-truncate-test"; + const char* archived_filename = "start-truncate-test.0"; + + delete_file(filename); + delete_file(archived_filename); + + // Use the same log file twice and expect it to be overwritten/truncated + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + assert(!file_exists(archived_filename), + "existing log file %s was not properly truncated when filecount was 0", + filename); + + // Verify that the file was really truncated and not just appended + assert(number_of_lines_with_substring_in_file(filename, ExpectedLine) == 1, + "log file %s appended rather than truncated", filename); + + delete_file(filename); + delete_file(archived_filename); +} + static int Test_logconfiguration_subscribe_triggered = 0; static void Test_logconfiguration_subscribe_helper() { @@ -741,4 +867,20 @@ void Test_log_gctracetime() { Test_log_gctracetime_no_heap_no_cause(); } +void Test_invalid_log_file() { + ResourceMark rm; + stringStream ss; + const char* target_name = "tmplogdir"; + + // Attempt to log to a directory (existing log not a regular file) + create_directory(target_name); + LogFileOutput bad_file("tmplogdir"); + assert(bad_file.initialize("", &ss) == false, "file was initialized " + "when there was an existing directory with the same name"); + assert(strstr(ss.as_string(), "tmplogdir is not a regular file") != NULL, + "missing expected error message, received msg: %s", ss.as_string()); + ss.reset(); + remove(target_name); +} + #endif // PRODUCT diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 67b63b782d9..6f9f7bb2a27 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -145,7 +145,7 @@ LogOutput* LogConfiguration::new_output(char* name, const char* options, outputS return NULL; } - bool success = output->initialize(options); + bool success = output->initialize(options, errstream); if (!success) { errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options); delete output; diff --git a/hotspot/src/share/vm/logging/logFileOutput.cpp b/hotspot/src/share/vm/logging/logFileOutput.cpp index 4084d5d2ce1..7f41bd995fb 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.cpp +++ b/hotspot/src/share/vm/logging/logFileOutput.cpp @@ -41,8 +41,9 @@ char LogFileOutput::_vm_start_time_str[StartTimeBufferSize]; LogFileOutput::LogFileOutput(const char* name) : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)), - _file_name(NULL), _archive_name(NULL), _archive_name_len(0), _current_size(0), - _rotate_size(0), _current_file(1), _file_count(0), _rotation_semaphore(1) { + _file_name(NULL), _archive_name(NULL), _archive_name_len(0), + _rotate_size(DefaultFileSize), _file_count(DefaultFileCount), + _current_size(0), _current_file(0), _rotation_semaphore(1) { _file_name = make_file_name(name, _pid_str, _vm_start_time_str); } @@ -59,9 +60,6 @@ void LogFileOutput::set_file_name_parameters(jlong vm_start_time) { LogFileOutput::~LogFileOutput() { if (_stream != NULL) { - if (_archive_name != NULL) { - archive(); - } if (fclose(_stream) != 0) { jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n", _file_name, os::strerror(errno)); @@ -72,7 +70,7 @@ LogFileOutput::~LogFileOutput() { os::free(const_cast(_name)); } -size_t LogFileOutput::parse_value(const char* value_str) { +static size_t parse_value(const char* value_str) { char* end; unsigned long long value = strtoull(value_str, &end, 10); if (!isdigit(*value_str) || end != value_str + strlen(value_str) || value >= SIZE_MAX) { @@ -81,7 +79,80 @@ size_t LogFileOutput::parse_value(const char* value_str) { return value; } -bool LogFileOutput::configure_rotation(const char* options) { +static bool file_exists(const char* filename) { + struct stat dummy_stat; + return os::stat(filename, &dummy_stat) == 0; +} + +static uint number_of_digits(uint number) { + return number < 10 ? 1 : (number < 100 ? 2 : 3); +} + +static bool is_regular_file(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + if (ret != 0) { + return false; + } +#ifdef _WINDOWS + return (st.st_mode & S_IFMT) == _S_IFREG; +#else + return S_ISREG(st.st_mode); +#endif +} + +// Try to find the next number that should be used for file rotation. +// Return UINT_MAX on error. +static uint next_file_number(const char* filename, + uint number_of_digits, + uint filecount, + outputStream* errstream) { + bool found = false; + uint next_num = 0; + + // len is filename + dot + digits + null char + size_t len = strlen(filename) + number_of_digits + 2; + char* archive_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + char* oldest_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + + for (uint i = 0; i < filecount; i++) { + int ret = jio_snprintf(archive_name, len, "%s.%0*u", + filename, number_of_digits, i); + assert(ret > 0 && static_cast(ret) == len - 1, + "incorrect buffer length calculation"); + + if (file_exists(archive_name) && !is_regular_file(archive_name)) { + // We've encountered something that's not a regular file among the + // possible file rotation targets. Fail immediately to prevent + // problems later. + errstream->print_cr("Possible rotation target file '%s' already exists " + "but is not a regular file.", archive_name); + next_num = UINT_MAX; + break; + } + + // Stop looking if we find an unused file name + if (!file_exists(archive_name)) { + next_num = i; + found = true; + break; + } + + // Keep track of oldest existing log file + if (!found + || os::compare_file_modified_times(oldest_name, archive_name) > 0) { + strcpy(oldest_name, archive_name); + next_num = i; + found = true; + } + } + + FREE_C_HEAP_ARRAY(char, oldest_name); + FREE_C_HEAP_ARRAY(char, archive_name); + return next_num; +} + +bool LogFileOutput::parse_options(const char* options, outputStream* errstream) { if (options == NULL || strlen(options) == 0) { return true; } @@ -107,22 +178,25 @@ bool LogFileOutput::configure_rotation(const char* options) { if (strcmp(FileCountOptionKey, key) == 0) { size_t value = parse_value(value_str); - if (value == SIZE_MAX || value >= UINT_MAX) { + if (value > MaxRotationFileCount) { + errstream->print_cr("Invalid option: %s must be in range [0, %u]", + FileCountOptionKey, + MaxRotationFileCount); success = false; break; } _file_count = static_cast(value); - _file_count_max_digits = static_cast(log10(static_cast(_file_count)) + 1); - _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; - _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); } else if (strcmp(FileSizeOptionKey, key) == 0) { size_t value = parse_value(value_str); if (value == SIZE_MAX || value > SIZE_MAX / K) { + errstream->print_cr("Invalid option: %s must be in range [0, " + SIZE_FORMAT "]", FileSizeOptionKey, SIZE_MAX / K); success = false; break; } _rotate_size = value * K; } else { + errstream->print_cr("Invalid option '%s' for log file output.", key); success = false; break; } @@ -133,15 +207,54 @@ bool LogFileOutput::configure_rotation(const char* options) { return success; } -bool LogFileOutput::initialize(const char* options) { - if (!configure_rotation(options)) { +bool LogFileOutput::initialize(const char* options, outputStream* errstream) { + if (!parse_options(options, errstream)) { return false; } + + if (_file_count > 0) { + // compute digits with filecount - 1 since numbers will start from 0 + _file_count_max_digits = number_of_digits(_file_count - 1); + _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; + _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); + } + + log_trace(logging)("Initializing logging to file '%s' (filecount: %u" + ", filesize: " SIZE_FORMAT " KiB).", + _file_name, _file_count, _rotate_size / K); + + if (_file_count > 0 && file_exists(_file_name)) { + if (!is_regular_file(_file_name)) { + errstream->print_cr("Unable to log to file %s with log file rotation: " + "%s is not a regular file", + _file_name, _file_name); + return false; + } + _current_file = next_file_number(_file_name, + _file_count_max_digits, + _file_count, + errstream); + if (_current_file == UINT_MAX) { + return false; + } + log_trace(logging)("Existing log file found, saving it as '%s.%0*u'", + _file_name, _file_count_max_digits, _current_file); + archive(); + increment_file_count(); + } + _stream = fopen(_file_name, FileOpenMode); if (_stream == NULL) { - log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, os::strerror(errno)); + errstream->print_cr("Error opening log file '%s': %s", + _file_name, strerror(errno)); return false; } + + if (_file_count == 0 && is_regular_file(_file_name)) { + log_trace(logging)("Truncating log file"); + os::ftruncate(os::fileno(_stream), 0); + } + return true; } @@ -210,7 +323,7 @@ void LogFileOutput::rotate() { // Reset accumulated size, increase current file counter, and check for file count wrap-around. _current_size = 0; - _current_file = (_current_file >= _file_count ? 1 : _current_file + 1); + increment_file_count(); } char* LogFileOutput::make_file_name(const char* file_name, diff --git a/hotspot/src/share/vm/logging/logFileOutput.hpp b/hotspot/src/share/vm/logging/logFileOutput.hpp index 935a176a5e3..adfd3722cef 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileOutput.hpp @@ -39,8 +39,11 @@ class LogFileOutput : public LogFileStreamOutput { static const char* PidFilenamePlaceholder; static const char* TimestampFilenamePlaceholder; static const char* TimestampFormat; + static const size_t DefaultFileCount = 5; + static const size_t DefaultFileSize = 20 * M; static const size_t StartTimeBufferSize = 20; - static const size_t PidBufferSize = 21; + static const size_t PidBufferSize = 21; + static const uint MaxRotationFileCount = 1000; static char _pid_str[PidBufferSize]; static char _vm_start_time_str[StartTimeBufferSize]; @@ -61,18 +64,24 @@ class LogFileOutput : public LogFileStreamOutput { void archive(); void rotate(); - bool configure_rotation(const char* options); + bool parse_options(const char* options, outputStream* errstream); char *make_file_name(const char* file_name, const char* pid_string, const char* timestamp_string); - static size_t parse_value(const char* value_str); bool should_rotate() { return _file_count > 0 && _rotate_size > 0 && _current_size >= _rotate_size; } + void increment_file_count() { + _current_file++; + if (_current_file == _file_count) { + _current_file = 0; + } + } + public: LogFileOutput(const char *name); virtual ~LogFileOutput(); - virtual bool initialize(const char* options); + virtual bool initialize(const char* options, outputStream* errstream); virtual int write(const LogDecorations& decorations, const char* msg); virtual void force_rotate(); diff --git a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp index 9c4ddf7b9c5..a4c739cfcfa 100644 --- a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp @@ -53,7 +53,7 @@ class LogStdoutOutput : public LogFileStreamOutput { LogStdoutOutput() : LogFileStreamOutput(stdout) { set_config_string("all=off"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: @@ -69,7 +69,7 @@ class LogStderrOutput : public LogFileStreamOutput { LogStderrOutput() : LogFileStreamOutput(stderr) { set_config_string("all=warning"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: diff --git a/hotspot/src/share/vm/logging/logOutput.hpp b/hotspot/src/share/vm/logging/logOutput.hpp index 1ca598c357f..5f06f388efd 100644 --- a/hotspot/src/share/vm/logging/logOutput.hpp +++ b/hotspot/src/share/vm/logging/logOutput.hpp @@ -82,7 +82,7 @@ class LogOutput : public CHeapObj { } virtual const char* name() const = 0; - virtual bool initialize(const char* options) = 0; + virtual bool initialize(const char* options, outputStream* errstream) = 0; virtual int write(const LogDecorations &decorations, const char* msg) = 0; }; diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index fcc9728f296..f8ee8918e8d 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -521,6 +521,9 @@ class os: AllStatic { static int ftruncate(int fd, jlong length); static int fsync(int fd); static int available(int fd, jlong *bytes); + static int fileno(FILE* fp); + + static int compare_file_modified_times(const char* file1, const char* file2); //File i/o operations diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 63bd284920d..985885c2edd 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -78,6 +78,9 @@ void InternalVMTests::run() { run_unit_test(Test_log_prefix); run_unit_test(Test_log_big); run_unit_test(Test_logtagset_duplicates); + run_unit_test(Test_log_file_startup_rotation); + run_unit_test(Test_log_file_startup_truncation); + run_unit_test(Test_invalid_log_file); run_unit_test(DirectivesParser_test); run_unit_test(Test_TempNewSymbol); #if INCLUDE_VM_STRUCTS diff --git a/hotspot/test/serviceability/logging/TestLogRotation.java b/hotspot/test/serviceability/logging/TestLogRotation.java index cd056dec1fe..025a9847a27 100644 --- a/hotspot/test/serviceability/logging/TestLogRotation.java +++ b/hotspot/test/serviceability/logging/TestLogRotation.java @@ -102,8 +102,10 @@ public class TestLogRotation { smallFilesNumber++; } } - if (logs.length != numberOfFiles) { - throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles); + // Expect one more log file since the number-of-files doesn't include the active log file + int expectedNumberOfFiles = numberOfFiles + 1; + if (logs.length != expectedNumberOfFiles) { + throw new Error("There are " + logs.length + " logs instead of the expected " + expectedNumberOfFiles); } if (smallFilesNumber > 1) { throw new Error("There should maximum one log with size < " + logFileSizeK + "K"); diff --git a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java index be2e76d9c51..39789ea01df 100644 --- a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java +++ b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java @@ -101,7 +101,7 @@ public class TestQuotedLogOutputs { output.shouldHaveExitValue(1); // Ensure error message was logged output.shouldMatch("([Mm]issing terminating quote)" - + "|(Could not open log file '')" + + "|(Error opening log file '')" + "|(Output name can not be partially quoted)"); } } From cf254af2fb7bf25ddd9cd9ed25b5619b94e5b6e4 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 12 Apr 2016 07:17:44 +0200 Subject: [PATCH 072/113] 8152491: Convert TracePageSizes to use UL Reviewed-by: sjohanss, pliden --- hotspot/src/os/windows/vm/os_windows.cpp | 14 +-- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 24 ++-- .../share/vm/gc/parallel/generationSizer.cpp | 15 --- .../share/vm/gc/parallel/generationSizer.hpp | 2 - .../share/vm/gc/parallel/parMarkBitMap.cpp | 2 +- .../vm/gc/parallel/parallelScavengeHeap.cpp | 6 +- .../vm/gc/parallel/psParallelCompact.cpp | 2 +- .../share/vm/gc/shared/cardTableModRefBS.cpp | 2 +- .../share/vm/gc/shared/genCollectedHeap.cpp | 8 ++ hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/globals.hpp | 3 - hotspot/src/share/vm/runtime/os.cpp | 71 ++++++++--- hotspot/src/share/vm/runtime/os.hpp | 20 ++-- .../share/vm/utilities/globalDefinitions.cpp | 110 +++++++++++++----- .../share/vm/utilities/globalDefinitions.hpp | 30 +++++ .../share/vm/utilities/internalVMTests.cpp | 2 +- .../gc/g1/TestLargePageUseForAuxMemory.java | 54 +++++++-- 17 files changed, 255 insertions(+), 111 deletions(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 53e4528c0cc..72da7bae97b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -3006,9 +3006,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, } #ifdef ASSERT if (should_inject_error) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving pages individually failed."); - } + log_develop_debug(pagesize)("Reserving pages individually failed."); } #endif return NULL; @@ -3192,9 +3190,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) // 2) NUMA Interleaving is enabled, in which case we use a different node for each page if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages individually."); - } + log_debug(pagesize)("Reserving large pages individually."); + char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError); if (p_buf == NULL) { // give an appropriate warning message @@ -3211,9 +3208,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, return p_buf; } else { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages in a single large chunk."); - } + log_debug(pagesize)("Reserving large pages in a single large chunk."); + // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; char * res = (char *)VirtualAlloc(addr, bytes, flag, prot); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2861baf232d..03c406e4bad 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1829,10 +1829,14 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des HeapRegion::GrainBytes, translation_factor, mtGC); - if (TracePageSizes) { - tty->print_cr("G1 '%s': pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT " size=" SIZE_FORMAT " alignment=" SIZE_FORMAT " reqsize=" SIZE_FORMAT, - description, preferred_page_size, p2i(rs.base()), rs.size(), rs.alignment(), size); - } + + os::trace_page_sizes_for_requested_size(description, + size, + preferred_page_size, + rs.alignment(), + rs.base(), + rs.size()); + return result; } @@ -1906,26 +1910,28 @@ jint G1CollectedHeap::initialize() { HeapRegion::GrainBytes, 1, mtJavaHeap); - os::trace_page_sizes("G1 Heap", collector_policy()->min_heap_byte_size(), - max_byte_size, page_size, + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + max_byte_size, + page_size, heap_rs.base(), heap_rs.size()); heap_storage->set_mapping_changed_listener(&_listener); // Create storage for the BOT, card table, card counts table (hot card cache) and the bitmaps. G1RegionToSpaceMapper* bot_storage = - create_aux_memory_mapper("Block offset table", + create_aux_memory_mapper("Block Offset Table", G1BlockOffsetTable::compute_size(g1_rs.size() / HeapWordSize), G1BlockOffsetTable::heap_map_factor()); ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize)); G1RegionToSpaceMapper* cardtable_storage = - create_aux_memory_mapper("Card table", + create_aux_memory_mapper("Card Table", G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize), G1SATBCardTableLoggingModRefBS::heap_map_factor()); G1RegionToSpaceMapper* card_counts_storage = - create_aux_memory_mapper("Card counts table", + create_aux_memory_mapper("Card Counts Table", G1CardCounts::compute_size(g1_rs.size() / HeapWordSize), G1CardCounts::heap_map_factor()); diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp index 03067d9bdae..565bb31043f 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp @@ -26,18 +26,6 @@ #include "gc/parallel/generationSizer.hpp" #include "gc/shared/collectorPolicy.hpp" -void GenerationSizer::trace_gen_sizes(const char* const str) { - if (TracePageSizes) { - tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT, - str, - _min_old_size / K, _max_old_size / K, - _min_young_size / K, _max_young_size / K, - _max_heap_byte_size / K); - } -} - void GenerationSizer::initialize_alignments() { _space_alignment = _gen_alignment = default_gen_alignment(); _heap_alignment = compute_heap_alignment(); @@ -60,7 +48,6 @@ void GenerationSizer::initialize_flags() { } void GenerationSizer::initialize_size_info() { - trace_gen_sizes("ps heap raw"); const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8); const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages); @@ -76,6 +63,4 @@ void GenerationSizer::initialize_size_info() { initialize_flags(); } GenCollectorPolicy::initialize_size_info(); - - trace_gen_sizes("ps heap rnd"); } diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp index 9db480f0bb7..539629b1c96 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp @@ -33,8 +33,6 @@ class GenerationSizer : public GenCollectorPolicy { private: - void trace_gen_sizes(const char* const str); - // The alignment used for boundary between young gen and old gen static size_t default_gen_alignment() { return 64 * K * HeapWordSize; } diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp index 569ff9ecbb1..76241d92692 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp @@ -49,7 +49,7 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz, + os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp index eb4b07f0410..89f384cb6a8 100644 --- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp @@ -60,8 +60,10 @@ jint ParallelScavengeHeap::initialize() { ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment()); - os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(), - heap_size, generation_alignment(), + os::trace_page_sizes("Heap", + _collector_policy->min_heap_byte_size(), + heap_size, + generation_alignment(), heap_rs.base(), heap_rs.size()); diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index a309ccd0c7d..6b145d17c00 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -426,7 +426,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par compact", raw_bytes, raw_bytes, page_sz, rs.base(), + os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp index e40cc62ca47..9053dedba0f 100644 --- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp @@ -93,7 +93,7 @@ void CardTableModRefBS::initialize() { MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC); - os::trace_page_sizes("card table", _guard_index + 1, _guard_index + 1, + os::trace_page_sizes("Card Table", _guard_index + 1, _guard_index + 1, _page_size, heap_rs.base(), heap_rs.size()); if (!heap_rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for the " diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 7f76efbcd10..c60e3a02092 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -167,6 +167,14 @@ char* GenCollectedHeap::allocate(size_t alignment, SIZE_FORMAT, total_reserved, alignment); *heap_rs = Universe::reserve_heap(total_reserved, alignment); + + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + total_reserved, + alignment, + heap_rs->base(), + heap_rs->size()); + return heap_rs->base(); } diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 5e4fcc6a142..ede507df242 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -70,6 +70,7 @@ LOG_TAG(monitorinflation) \ LOG_TAG(monitormismatch) \ LOG_TAG(os) \ + LOG_TAG(pagesize) \ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 67c8321b0ed..fe2d2e615f0 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -685,9 +685,6 @@ public: "Use large page memory in metaspace. " \ "Only used if UseLargePages is enabled.") \ \ - develop(bool, TracePageSizes, false, \ - "Trace page size selection and usage") \ - \ product(bool, UseNUMA, false, \ "Use NUMA if available") \ \ diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 1644e43eb0e..ec103436269 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -33,6 +33,7 @@ #include "gc/shared/vmGCOperations.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #ifdef ASSERT #include "memory/guardedMemory.hpp" @@ -1494,31 +1495,63 @@ const char* os::errno_name(int e) { return errno_to_string(e, true); } -#ifndef PRODUCT -void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) -{ - if (TracePageSizes) { - tty->print("%s: ", str); +void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) { + LogTarget(Info, pagesize) log; + if (log.is_enabled()) { + LogStreamCHeap out(log); + + out.print("%s: ", str); for (int i = 0; i < count; ++i) { - tty->print(" " SIZE_FORMAT, page_sizes[i]); + out.print(" " SIZE_FORMAT, page_sizes[i]); } - tty->cr(); + out.cr(); } } -void os::trace_page_sizes(const char* str, const size_t region_min_size, - const size_t region_max_size, const size_t page_size, - const char* base, const size_t size) -{ - if (TracePageSizes) { - tty->print_cr("%s: min=" SIZE_FORMAT " max=" SIZE_FORMAT - " pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT - " size=" SIZE_FORMAT, - str, region_min_size, region_max_size, - page_size, p2i(base), size); - } +#define trace_page_size_params(size) byte_size_in_exact_unit(size), exact_unit_for_byte_size(size) + +void os::trace_page_sizes(const char* str, + const size_t region_min_size, + const size_t region_max_size, + const size_t page_size, + const char* base, + const size_t size) { + + log_info(pagesize)("%s: " + " min=" SIZE_FORMAT "%s" + " max=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(region_min_size), + trace_page_size_params(region_max_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(size)); } -#endif // #ifndef PRODUCT + +void os::trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size) { + + log_info(pagesize)("%s:" + " req_size=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " alignment=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(requested_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(alignment), + trace_page_size_params(size)); +} + // This is the working definition of a server class machine: // >= 2 physical CPU's and >=2GB of memory, with some fuzz diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 04b19698cf3..fcc9728f296 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -286,18 +286,24 @@ class os: AllStatic { return _page_sizes[0]; } - // Methods for tracing page sizes returned by the above method; enabled by - // TracePageSizes. The region_{min,max}_size parameters should be the values + // Methods for tracing page sizes returned by the above method. + // The region_{min,max}_size parameters should be the values // passed to page_size_for_region() and page_size should be the result of that // call. The (optional) base and size parameters should come from the // ReservedSpace base() and size() methods. - static void trace_page_sizes(const char* str, const size_t* page_sizes, - int count) PRODUCT_RETURN; - static void trace_page_sizes(const char* str, const size_t region_min_size, + static void trace_page_sizes(const char* str, const size_t* page_sizes, int count); + static void trace_page_sizes(const char* str, + const size_t region_min_size, const size_t region_max_size, const size_t page_size, - const char* base = NULL, - const size_t size = 0) PRODUCT_RETURN; + const char* base, + const size_t size); + static void trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size); static int vm_allocation_granularity(); static char* reserve_memory(size_t bytes, char* addr = 0, diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 98abb71dbe1..0a653abcbe9 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -374,39 +374,89 @@ STATIC_ASSERT(left_n_bits(1|2) == (intptr_t) LP64_ONLY(0xE000000000000000) NOT_L #ifndef PRODUCT // For unit testing only -class GlobalDefinitions { +class TestGlobalDefinitions { +private: + + static void test_clamp_address_in_page() { + intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; + const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); + + for (int i = 0; i < num_page_sizes; i++) { + intptr_t page_size = page_sizes[i]; + + address a_page = (address)(10*page_size); + + // Check that address within page is returned as is + assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); + assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); + + // Check that address above page returns start of next page + assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); + + // Check that address below page returns start of page + assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); + } + } + + static void test_exact_unit_for_byte_size() { + assert(strcmp(exact_unit_for_byte_size(0), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + K), "K") == 0, "incorrect"); +#ifdef LP64 + assert(strcmp(exact_unit_for_byte_size(G - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G), "G") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M + K), "K") == 0, "incorrect"); +#endif + } + + static void test_byte_size_in_exact_unit() { + assert(byte_size_in_exact_unit(0) == 0, "incorrect"); + assert(byte_size_in_exact_unit(1) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K - 1) == K - 1, "incorrect"); + assert(byte_size_in_exact_unit(K) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K + 1) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(M - 1) == M - 1, "incorrect"); + assert(byte_size_in_exact_unit(M) == 1, "incorrect"); + assert(byte_size_in_exact_unit(M + 1) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(M + K) == K + 1, "incorrect"); +#ifdef LP64 + assert(byte_size_in_exact_unit(G - 1) == G - 1, "incorrect"); + assert(byte_size_in_exact_unit(G) == 1, "incorrect"); + assert(byte_size_in_exact_unit(G + 1) == G + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + K) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M + K) == M + K + 1, "incorrect"); +#endif + } + + static void test_exact_units() { + test_exact_unit_for_byte_size(); + test_byte_size_in_exact_unit(); + } + public: - static void test_globals(); + static void test() { + test_clamp_address_in_page(); + test_exact_units(); + } }; -void GlobalDefinitions::test_globals() { - intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; - const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); - - for (int i = 0; i < num_page_sizes; i++) { - intptr_t page_size = page_sizes[i]; - - address a_page = (address)(10*page_size); - - // Check that address within page is returned as is - assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); - assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); - - // Check that address above page returns start of next page - assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); - - // Check that address below page returns start of page - assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); - } -} - -void GlobalDefinitions_test() { - GlobalDefinitions::test_globals(); +void TestGlobalDefinitions_test() { + TestGlobalDefinitions::test(); } #endif // PRODUCT diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 5a080626ada..3c04e2a0f54 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -243,6 +243,36 @@ inline T byte_size_in_proper_unit(T s) { } } +inline const char* exact_unit_for_byte_size(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return "G"; + } +#endif + if (s >= M && (s % M) == 0) { + return "M"; + } + if (s >= K && (s % K) == 0) { + return "K"; + } + return "B"; +} + +inline size_t byte_size_in_exact_unit(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return s / G; + } +#endif + if (s >= M && (s % M) == 0) { + return s / M; + } + if (s >= K && (s % K) == 0) { + return s / K; + } + return s; +} + //---------------------------------------------------------------------------------------------------- // VM type definitions diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 4adaf307425..9b3df11e27b 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -50,7 +50,7 @@ void InternalVMTests::run() { run_unit_test(TestMetaspaceAux_test); run_unit_test(TestMetachunk_test); run_unit_test(TestVirtualSpaceNode_test); - run_unit_test(GlobalDefinitions_test); + run_unit_test(TestGlobalDefinitions_test); run_unit_test(GCTimer_test); run_unit_test(arrayOopDesc_test); run_unit_test(CollectedHeap_test); diff --git a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java index 03d214d19ec..28f1b166a4d 100644 --- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java +++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java @@ -36,6 +36,8 @@ */ import java.lang.Math; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import jdk.test.lib.*; import jdk.test.lib.Asserts; @@ -47,14 +49,29 @@ public class TestLargePageUseForAuxMemory { static long smallPageSize; static long allocGranularity; + static void checkSize(OutputAnalyzer output, long expectedSize, String pattern) { + String pageSizeStr = output.firstMatch(pattern, 1); + + if (pageSizeStr == null) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got 'null' expected: " + expectedSize); + } + + long size = parseMemoryString(pageSizeStr); + if (size != expectedSize) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got " + size + " expected: " + expectedSize); + } + } + static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Block offset table': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Card counts table': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Block Offset Table: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Card Counts Table: .*page_size=([^ ]+)"); } static void checkBitmaps(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Prev Bitmap': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Next Bitmap': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Prev Bitmap: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Next Bitmap: .*page_size=([^ ]+)"); } static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception { @@ -66,7 +83,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:+UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -82,7 +99,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:-UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -108,11 +125,6 @@ public class TestLargePageUseForAuxMemory { } public static void main(String[] args) throws Exception { - if (!Platform.isDebugBuild()) { - System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option."); - return; - } - // Size that a single card covers. final int cardSize = 512; WhiteBox wb = WhiteBox.getWhiteBox(); @@ -159,4 +171,24 @@ public class TestLargePageUseForAuxMemory { testVM("case5: only bitmap uses large pages (extra slack)", heapSizeForBitmapUsingLargePages + heapSizeDiffForBitmap, false, true); testVM("case6: nothing uses large pages (barely not)", heapSizeForBitmapUsingLargePages - heapSizeDiffForBitmap, false, false); } + + public static long parseMemoryString(String value) { + long multiplier = 1; + + if (value.endsWith("B")) { + multiplier = 1; + } else if (value.endsWith("K")) { + multiplier = 1024; + } else if (value.endsWith("M")) { + multiplier = 1024 * 1024; + } else if (value.endsWith("G")) { + multiplier = 1024 * 1024 * 1024; + } else { + throw new IllegalArgumentException("Expected memory string '" + value + "'to end with either of: B, K, M, G"); + } + + long longValue = Long.parseUnsignedLong(value.substring(0, value.length() - 1)); + + return longValue * multiplier; + } } From f78228b2eeeacf2db6873ab93bd1523e79d00aa5 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 12 Apr 2016 09:53:43 +0200 Subject: [PATCH 073/113] 8153967: Remove top.hpp Reviewed-by: coleenp, jwilhelm --- hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp | 1 - hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp | 1 - .../src/cpu/aarch64/vm/nativeInst_aarch64.hpp | 1 - .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 1 - hotspot/src/cpu/ppc/vm/debug_ppc.cpp | 1 - hotspot/src/cpu/ppc/vm/frame_ppc.hpp | 1 - hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 1 - hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 1 - hotspot/src/cpu/sparc/vm/debug_sparc.cpp | 1 - hotspot/src/cpu/sparc/vm/frame_sparc.hpp | 1 - hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp | 1 - .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 1 - hotspot/src/cpu/x86/vm/debug_x86.cpp | 1 - hotspot/src/cpu/x86/vm/frame_x86.hpp | 1 - hotspot/src/cpu/x86/vm/nativeInst_x86.hpp | 1 - .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 1 - .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 1 - hotspot/src/cpu/zero/vm/debug_zero.cpp | 1 - hotspot/src/cpu/zero/vm/frame_zero.hpp | 1 - hotspot/src/cpu/zero/vm/nativeInst_zero.hpp | 1 - .../src/cpu/zero/vm/stubGenerator_zero.cpp | 1 - hotspot/src/share/vm/asm/assembler.hpp | 1 - hotspot/src/share/vm/asm/register.hpp | 3 +- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 1 - hotspot/src/share/vm/ci/ciFlags.hpp | 1 + .../share/vm/classfile/classFileStream.hpp | 3 +- hotspot/src/share/vm/code/relocInfo.hpp | 3 +- hotspot/src/share/vm/code/vmreg.hpp | 3 +- .../vm/gc/parallel/psAdaptiveSizePolicy.cpp | 1 - .../vm/interpreter/abstractInterpreter.hpp | 1 - .../share/vm/interpreter/bytecodeTracer.hpp | 1 + .../src/share/vm/interpreter/bytecodes.hpp | 3 +- .../vm/interpreter/interpreterRuntime.hpp | 1 - .../src/share/vm/interpreter/linkResolver.hpp | 1 - hotspot/src/share/vm/memory/iterator.hpp | 3 +- hotspot/src/share/vm/oops/oop.hpp | 1 - hotspot/src/share/vm/oops/symbol.hpp | 3 +- .../src/share/vm/precompiled/precompiled.hpp | 1 - hotspot/src/share/vm/prims/jvm.cpp | 1 - hotspot/src/share/vm/prims/nativeLookup.hpp | 2 +- hotspot/src/share/vm/runtime/arguments.hpp | 1 - hotspot/src/share/vm/runtime/basicLock.hpp | 1 - hotspot/src/share/vm/runtime/frame.hpp | 1 - hotspot/src/share/vm/runtime/globals.cpp | 1 - .../share/vm/runtime/globals_extension.hpp | 14 ++++- hotspot/src/share/vm/runtime/init.hpp | 2 +- .../src/share/vm/runtime/interfaceSupport.hpp | 1 - hotspot/src/share/vm/runtime/jniHandles.hpp | 2 +- hotspot/src/share/vm/runtime/os.hpp | 1 - hotspot/src/share/vm/runtime/osThread.hpp | 1 - hotspot/src/share/vm/runtime/signature.hpp | 1 - hotspot/src/share/vm/runtime/stackValue.hpp | 1 - hotspot/src/share/vm/runtime/stubRoutines.hpp | 1 - hotspot/src/share/vm/runtime/synchronizer.hpp | 2 - hotspot/src/share/vm/runtime/task.hpp | 3 +- hotspot/src/share/vm/runtime/thread.hpp | 1 - .../share/vm/runtime/threadLocalStorage.hpp | 2 +- .../src/share/vm/runtime/vm_operations.hpp | 1 - .../src/share/vm/utilities/accessFlags.hpp | 3 +- hotspot/src/share/vm/utilities/bitMap.hpp | 1 - .../src/share/vm/utilities/constantTag.cpp | 1 + .../src/share/vm/utilities/constantTag.hpp | 2 +- hotspot/src/share/vm/utilities/debug.cpp | 1 - hotspot/src/share/vm/utilities/events.hpp | 1 - hotspot/src/share/vm/utilities/exceptions.hpp | 1 - .../share/vm/utilities/globalDefinitions.cpp | 1 - .../src/share/vm/utilities/growableArray.hpp | 1 - hotspot/src/share/vm/utilities/ostream.cpp | 1 - hotspot/src/share/vm/utilities/pair.hpp | 1 - .../src/share/vm/utilities/resourceHash.hpp | 1 - hotspot/src/share/vm/utilities/top.hpp | 52 ------------------- hotspot/src/share/vm/utilities/utf8.hpp | 1 - hotspot/src/share/vm/utilities/vmError.cpp | 1 - 73 files changed, 38 insertions(+), 123 deletions(-) delete mode 100644 hotspot/src/share/vm/utilities/top.hpp diff --git a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp index 107f6085474..72fc4d7df63 100644 --- a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp index d267036974e..4332abce9f4 100644 --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp @@ -27,7 +27,6 @@ #define CPU_AARCH64_VM_FRAME_AARCH64_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp index d83017c1770..a3a6d6a1302 100644 --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index d618c0351f7..b0787ddf4a9 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -39,7 +39,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp index 5427a1e4644..ff92dd4e50d 100644 --- a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp index 8115a20640e..6f8f0296f83 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -27,7 +27,6 @@ #define CPU_PPC_VM_FRAME_PPC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // C frame layout on PPC-64. // diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index 586dcaa9380..99aa11c4b20 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -31,7 +31,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 0f6c6f77fdb..2eba3edacef 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -37,7 +37,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" -#include "utilities/top.hpp" #include "runtime/thread.inline.hpp" #define __ _masm-> diff --git a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp index 8be1072fc65..9f3f40ada7c 100644 --- a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp @@ -29,7 +29,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" #ifndef PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index 5de8ad4bf1d..cd91f52fd17 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -26,7 +26,6 @@ #define CPU_SPARC_VM_FRAME_SPARC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index a5f04a8f5b9..d0582f34265 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interface for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 98d82ee07e5..db2c5eefac8 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -37,7 +37,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/debug_x86.cpp b/hotspot/src/cpu/x86/vm/debug_x86.cpp index b128439ef23..0bde483a789 100644 --- a/hotspot/src/cpu/x86/vm/debug_x86.cpp +++ b/hotspot/src/cpu/x86/vm/debug_x86.cpp @@ -29,6 +29,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.hpp b/hotspot/src/cpu/x86/vm/frame_x86.hpp index 6c85be06a81..b10f9ce37e6 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp @@ -26,7 +26,6 @@ #define CPU_X86_VM_FRAME_X86_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp index 6c527d49991..1bb1c6c8aff 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 756c032861e..0f11b9c0371 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 882969c5695..d51f3a696a0 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/zero/vm/debug_zero.cpp b/hotspot/src/cpu/zero/vm/debug_zero.cpp index 19d00e33cdc..24580fecf5f 100644 --- a/hotspot/src/cpu/zero/vm/debug_zero.cpp +++ b/hotspot/src/cpu/zero/vm/debug_zero.cpp @@ -30,7 +30,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) { ShouldNotCallThis(); diff --git a/hotspot/src/cpu/zero/vm/frame_zero.hpp b/hotspot/src/cpu/zero/vm/frame_zero.hpp index 56f0a1716b0..2f1c931c690 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp @@ -27,7 +27,6 @@ #define CPU_ZERO_VM_FRAME_ZERO_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame on the Zero stack. diff --git a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp index 559bde79ab6..8b60b358f5e 100644 --- a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp +++ b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp index 9d999a8c805..bdaec67cd73 100644 --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp @@ -40,7 +40,6 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "stack_zero.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index 40bd5d379e0..2ef9d993721 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -33,7 +33,6 @@ #include "runtime/vm_version.hpp" #include "utilities/debug.hpp" #include "utilities/growableArray.hpp" -#include "utilities/top.hpp" // This file contains platform-independent assembler declarations. diff --git a/hotspot/src/share/vm/asm/register.hpp b/hotspot/src/share/vm/asm/register.hpp index 5e43cfa68fd..e258e867c1d 100644 --- a/hotspot/src/share/vm/asm/register.hpp +++ b/hotspot/src/share/vm/asm/register.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_ASM_REGISTER_HPP #define SHARE_VM_ASM_REGISTER_HPP -#include "utilities/top.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" // Use AbstractRegister as shortcut class AbstractRegisterImpl; diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 8c2c97ece41..42e6f6642d3 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -28,7 +28,6 @@ #include "c1/c1_CodeStubs.hpp" #include "ci/ciMethodData.hpp" #include "oops/methodData.hpp" -#include "utilities/top.hpp" class Compilation; class ScopeValue; diff --git a/hotspot/src/share/vm/ci/ciFlags.hpp b/hotspot/src/share/vm/ci/ciFlags.hpp index 60d5632f4bb..783064253c1 100644 --- a/hotspot/src/share/vm/ci/ciFlags.hpp +++ b/hotspot/src/share/vm/ci/ciFlags.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" #include "prims/jvm.h" #include "utilities/accessFlags.hpp" +#include "utilities/ostream.hpp" // ciFlags // diff --git a/hotspot/src/share/vm/classfile/classFileStream.hpp b/hotspot/src/share/vm/classfile/classFileStream.hpp index 2d69de74b3a..90ae4e9d34a 100644 --- a/hotspot/src/share/vm/classfile/classFileStream.hpp +++ b/hotspot/src/share/vm/classfile/classFileStream.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP #define SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP +#include "memory/allocation.hpp" #include "utilities/bytes.hpp" -#include "utilities/top.hpp" +#include "utilities/exceptions.hpp" // Input stream for reading .class file // diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index b399c093759..86a454c153f 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.hpp @@ -26,8 +26,9 @@ #define SHARE_VM_CODE_RELOCINFO_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" +#include "runtime/os.hpp" +class Metadata; class NativeMovConstReg; // Types in this file: diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index fb9228c3ee9..e6bc343c07d 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -28,10 +28,9 @@ #include "asm/register.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" - +#include "utilities/ostream.hpp" #ifdef COMPILER2 #include "opto/adlcVMDeps.hpp" -#include "utilities/ostream.hpp" #endif //------------------------------VMReg------------------------------------------ diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp index 4506ed67ee3..c8554287512 100644 --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp @@ -32,7 +32,6 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" -#include "utilities/top.hpp" #include diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 2c527a8f893..8ec0db7e0de 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -30,7 +30,6 @@ #include "interpreter/bytecodes.hpp" #include "runtime/thread.hpp" #include "runtime/vmThread.hpp" -#include "utilities/top.hpp" // This file contains the platform-independent parts // of the abstract interpreter and the abstract interpreter generator. diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp index 06d2a1d8899..dff27c66022 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_INTERPRETER_BYTECODETRACER_HPP #include "memory/allocation.hpp" +#include "utilities/ostream.hpp" // The BytecodeTracer is a helper class used by the interpreter for run-time // bytecode tracing. If bytecode tracing is turned on, trace() will be called diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 20990d64b9e..4f52e7b4a1a 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -26,11 +26,12 @@ #define SHARE_VM_INTERPRETER_BYTECODES_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Bytecodes specifies all bytecodes used in the VM and // provides utility functions to get bytecode attributes. +class Method; + // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/interpreter/Bytecodes.java class Bytecodes: AllStatic { public: diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index dd4f797b0c7..d8ef297e21d 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -32,7 +32,6 @@ #include "runtime/frame.inline.hpp" #include "runtime/signature.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" // The InterpreterRuntime is called by the interpreter for everything // that cannot/should not be dealt with in assembly and needs C support. diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index a197070dadd..4dae8111e18 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_INTERPRETER_LINKRESOLVER_HPP #include "oops/method.hpp" -#include "utilities/top.hpp" // All the necessary definitions for run-time link resolution. diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp index 6d7d9d4fece..3a36dc6d5f5 100644 --- a/hotspot/src/share/vm/memory/iterator.hpp +++ b/hotspot/src/share/vm/memory/iterator.hpp @@ -27,7 +27,7 @@ #include "memory/allocation.hpp" #include "memory/memRegion.hpp" -#include "utilities/top.hpp" +#include "oops/oopsHierarchy.hpp" class CodeBlob; class nmethod; @@ -35,6 +35,7 @@ class ReferenceProcessor; class DataLayout; class KlassClosure; class ClassLoaderData; +class Symbol; // The following classes are C++ `closures` for iterating over objects, roots and spaces diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index d154f966568..23d73067178 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -30,7 +30,6 @@ #include "memory/memRegion.hpp" #include "oops/metadata.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe // the format of Java objects so the fields can be accessed from C++. diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index f4241d3ad8d..b2d71d51335 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_OOPS_SYMBOL_HPP #define SHARE_VM_OOPS_SYMBOL_HPP -#include "utilities/utf8.hpp" #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "utilities/exceptions.hpp" +#include "utilities/utf8.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index f3e0fea113f..81bd00eaaf8 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -242,7 +242,6 @@ # include "utilities/ostream.hpp" # include "utilities/preserveException.hpp" # include "utilities/sizes.hpp" -# include "utilities/top.hpp" # include "utilities/utf8.hpp" #ifdef COMPILER2 # include "libadt/dict.hpp" diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 0619af4f9fd..85e2c9ebb83 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -79,7 +79,6 @@ #include "utilities/events.hpp" #include "utilities/histogram.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/utf8.hpp" #if INCLUDE_CDS #include "classfile/sharedClassUtil.hpp" diff --git a/hotspot/src/share/vm/prims/nativeLookup.hpp b/hotspot/src/share/vm/prims/nativeLookup.hpp index d1cfcb9259a..3afc5039eb2 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.hpp +++ b/hotspot/src/share/vm/prims/nativeLookup.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_PRIMS_NATIVELOOKUP_HPP #define SHARE_VM_PRIMS_NATIVELOOKUP_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" // NativeLookup provides an interface for finding DLL entry points for // Java native functions. diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 1dc3135aff6..328a9d71872 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -31,7 +31,6 @@ #include "runtime/os.hpp" #include "runtime/perfData.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" // Arguments parses the command line and recognizes options diff --git a/hotspot/src/share/vm/runtime/basicLock.hpp b/hotspot/src/share/vm/runtime/basicLock.hpp index cc4e37eed52..f47c5add571 100644 --- a/hotspot/src/share/vm/runtime/basicLock.hpp +++ b/hotspot/src/share/vm/runtime/basicLock.hpp @@ -27,7 +27,6 @@ #include "oops/markOop.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class BasicLock VALUE_OBJ_CLASS_SPEC { friend class VMStructs; diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index cbd63cd20b2..0bb1d875071 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -29,7 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/monitorChunk.hpp" #include "runtime/registerMap.hpp" -#include "utilities/top.hpp" #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 1728da3e857..7e752adac01 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -35,7 +35,6 @@ #include "trace/tracing.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1_globals.hpp" #endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 45830e56623..b550f236042 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -27,7 +27,19 @@ #include "runtime/globals.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS +#include "gc/g1/g1_globals.hpp" +#endif +#if INCLUDE_JVMCI +#include "jvmci/jvmci_globals.hpp" +#endif +#ifdef COMPILER1 +#include "c1/c1_globals.hpp" +#endif +#ifdef COMPILER2 +#include "opto/c2_globals.hpp" +#endif // Construct enum of Flag_ constants. diff --git a/hotspot/src/share/vm/runtime/init.hpp b/hotspot/src/share/vm/runtime/init.hpp index fd9fdf6f64a..77158f5a937 100644 --- a/hotspot/src/share/vm/runtime/init.hpp +++ b/hotspot/src/share/vm/runtime/init.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_INIT_HPP #define SHARE_VM_RUNTIME_INIT_HPP -#include "utilities/top.hpp" +#include "utilities/globalDefinitions.hpp" // init_globals replaces C++ global objects so we can use the standard linker // to link Delta (which is at least twice as fast as using the GNU C++ linker). diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 8dbc6be317c..de3ef8f648b 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -35,7 +35,6 @@ #include "runtime/vmThread.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/preserveException.hpp" -#include "utilities/top.hpp" // Wrapper for all entry points to the virtual machine. // The HandleMarkCleaner is a faster version of HandleMark. diff --git a/hotspot/src/share/vm/runtime/jniHandles.hpp b/hotspot/src/share/vm/runtime/jniHandles.hpp index 1503a3696b6..ce37d940d7c 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.hpp +++ b/hotspot/src/share/vm/runtime/jniHandles.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_RUNTIME_JNIHANDLES_HPP #define SHARE_VM_RUNTIME_JNIHANDLES_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class JNIHandleBlock; diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index fcc9728f296..edd15f04a7e 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -28,7 +28,6 @@ #include "jvmtifiles/jvmti.h" #include "runtime/extendedPC.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" # include diff --git a/hotspot/src/share/vm/runtime/osThread.hpp b/hotspot/src/share/vm/runtime/osThread.hpp index 29912bd5187..16cc2e8055e 100644 --- a/hotspot/src/share/vm/runtime/osThread.hpp +++ b/hotspot/src/share/vm/runtime/osThread.hpp @@ -29,7 +29,6 @@ #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" #include "runtime/objectMonitor.hpp" -#include "utilities/top.hpp" // The OSThread class holds OS-specific thread information. It is equivalent // to the sys_thread_t structure of the classic JVM implementation. diff --git a/hotspot/src/share/vm/runtime/signature.hpp b/hotspot/src/share/vm/runtime/signature.hpp index 46e36e9f532..3e0bb829cfc 100644 --- a/hotspot/src/share/vm/runtime/signature.hpp +++ b/hotspot/src/share/vm/runtime/signature.hpp @@ -27,7 +27,6 @@ #include "memory/allocation.hpp" #include "oops/method.hpp" -#include "utilities/top.hpp" // SignatureIterators iterate over a Java signature (or parts of it). // (Syntax according to: "The Java Virtual Machine Specification" by diff --git a/hotspot/src/share/vm/runtime/stackValue.hpp b/hotspot/src/share/vm/runtime/stackValue.hpp index a7698f50b74..569ef58f89a 100644 --- a/hotspot/src/share/vm/runtime/stackValue.hpp +++ b/hotspot/src/share/vm/runtime/stackValue.hpp @@ -27,7 +27,6 @@ #include "code/location.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class StackValue : public ResourceObj { private: diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 38fe86e631b..55cd9934bd0 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -30,7 +30,6 @@ #include "runtime/frame.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/stubCodeGenerator.hpp" -#include "utilities/top.hpp" // StubRoutines provides entry points to assembly routines used by // compiled code and the run-time system. Platform-specific entry diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index ab3d145842c..777317b927c 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -29,8 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/handles.hpp" #include "runtime/perfData.hpp" -#include "utilities/top.hpp" - class ObjectMonitor; diff --git a/hotspot/src/share/vm/runtime/task.hpp b/hotspot/src/share/vm/runtime/task.hpp index c7181089ee2..b3e5f927aee 100644 --- a/hotspot/src/share/vm/runtime/task.hpp +++ b/hotspot/src/share/vm/runtime/task.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_RUNTIME_TASK_HPP #define SHARE_VM_RUNTIME_TASK_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" +#include "runtime/timer.hpp" // A PeriodicTask has the sole purpose of executing its task // function with regular intervals. diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 4f993ab8fa1..0d54deec3ef 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -46,7 +46,6 @@ #include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/satbMarkQueue.hpp" diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp index 016e1fc1196..fbd370ed867 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP #define SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" // forward-decl as we can't have an include cycle class Thread; diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 22626d2c2a8..2807768339f 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "code/codeCache.hpp" // The following classes are used for operations diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp index 8e9219fe8bc..d9c1685e2b9 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.hpp +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_UTILITIES_ACCESSFLAGS_HPP #define SHARE_VM_UTILITIES_ACCESSFLAGS_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" // AccessFlags is an abstraction over Java access flags. diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index b925d66442f..b41cc12062e 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_BITMAP_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Forward decl; class BitMapClosure; diff --git a/hotspot/src/share/vm/utilities/constantTag.cpp b/hotspot/src/share/vm/utilities/constantTag.cpp index 1495a42e624..187bb5ed200 100644 --- a/hotspot/src/share/vm/utilities/constantTag.cpp +++ b/hotspot/src/share/vm/utilities/constantTag.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "utilities/constantTag.hpp" +#include "utilities/ostream.hpp" #ifndef PRODUCT diff --git a/hotspot/src/share/vm/utilities/constantTag.hpp b/hotspot/src/share/vm/utilities/constantTag.hpp index ae99d570693..c083848c0bd 100644 --- a/hotspot/src/share/vm/utilities/constantTag.hpp +++ b/hotspot/src/share/vm/utilities/constantTag.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_UTILITIES_CONSTANTTAG_HPP #define SHARE_VM_UTILITIES_CONSTANTTAG_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" // constant tags in Java .class files diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index f6fd336bca8..ad1e9e43a78 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -52,7 +52,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" #if INCLUDE_TRACE diff --git a/hotspot/src/share/vm/utilities/events.hpp b/hotspot/src/share/vm/utilities/events.hpp index 5b65fcc1a6f..3ff1e52a1b4 100644 --- a/hotspot/src/share/vm/utilities/events.hpp +++ b/hotspot/src/share/vm/utilities/events.hpp @@ -28,7 +28,6 @@ #include "memory/allocation.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // Events and EventMark provide interfaces to log events taking place in the vm. diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index cdfa0bdf817..e7aaf800237 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -47,7 +47,6 @@ // Forward declarations to be independent of the include structure. -// This allows us to have exceptions.hpp included in top.hpp. class Thread; class Handle; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 0a653abcbe9..7f69396d84d 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // Basic error support diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp index a2780fecca5..fccbad3645f 100644 --- a/hotspot/src/share/vm/utilities/growableArray.hpp +++ b/hotspot/src/share/vm/utilities/growableArray.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.inline.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // A growable array. diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 0f1057ed1ce..e9cc5fc2f08 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -31,7 +31,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #include "utilities/xmlstream.hpp" extern "C" void jio_print(const char* s); // Declarationtion of jvm method diff --git a/hotspot/src/share/vm/utilities/pair.hpp b/hotspot/src/share/vm/utilities/pair.hpp index d0bb5d65c4b..7c901539c56 100644 --- a/hotspot/src/share/vm/utilities/pair.hpp +++ b/hotspot/src/share/vm/utilities/pair.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_PAIR_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template class Pair : public ALLOC_BASE { diff --git a/hotspot/src/share/vm/utilities/resourceHash.hpp b/hotspot/src/share/vm/utilities/resourceHash.hpp index 82c1219b465..bfd0a1f2d94 100644 --- a/hotspot/src/share/vm/utilities/resourceHash.hpp +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template struct ResourceHashtableFns { typedef unsigned (*hash_fn)(K const&); diff --git a/hotspot/src/share/vm/utilities/top.hpp b/hotspot/src/share/vm/utilities/top.hpp deleted file mode 100644 index de26d52bc02..00000000000 --- a/hotspot/src/share/vm/utilities/top.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 - * 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. - * - */ - -#ifndef SHARE_VM_UTILITIES_TOP_HPP -#define SHARE_VM_UTILITIES_TOP_HPP - -#include "oops/oopsHierarchy.hpp" -#include "runtime/globals.hpp" -#include "utilities/debug.hpp" -#include "utilities/exceptions.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" -#include "utilities/ostream.hpp" -#include "utilities/sizes.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1_globals.hpp" -#endif // INCLUDE_ALL_GCS -#ifdef COMPILER1 -#include "c1/c1_globals.hpp" -#endif -#ifdef COMPILER2 -#include "opto/c2_globals.hpp" -#endif -#if INCLUDE_JVMCI -#include "jvmci/jvmci_globals.hpp" -#endif - -// THIS FILE IS INTESIONALLY LEFT EMPTY -// IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB - -#endif // SHARE_VM_UTILITIES_TOP_HPP diff --git a/hotspot/src/share/vm/utilities/utf8.hpp b/hotspot/src/share/vm/utilities/utf8.hpp index 1a30cb456fc..34deeb953f7 100644 --- a/hotspot/src/share/vm/utilities/utf8.hpp +++ b/hotspot/src/share/vm/utilities/utf8.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_UTF8_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Low-level interface for UTF8 strings diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 0f128c1f286..4ca94f391a4 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -43,7 +43,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/errorReporter.hpp" #include "utilities/events.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // List of environment variables that should be reported in error log file. From 89282b0c72136010754d64ed1278f4656883b7fa Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Tue, 12 Apr 2016 14:03:31 +0200 Subject: [PATCH 074/113] 8153834: G1 Card table verification fails due to concurrent region cleanup Reviewed-by: ehelin, tschatzl --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 03c406e4bad..2980eecdc0e 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4824,6 +4824,9 @@ void G1CollectedHeap::cleanUpCardTable() { workers()->run_task(&cleanup_task); #ifndef PRODUCT + // Need to synchronize with concurrent cleanup since it needs to + // finish its card table clearing before we can verify. + wait_while_free_regions_coming(); _verifier->verify_card_table_cleanup(); #endif } From 8423e2c392543ba5f4d0bc8266cefa8966f2f46c Mon Sep 17 00:00:00 2001 From: Derek White Date: Tue, 12 Apr 2016 14:46:02 -0400 Subject: [PATCH 075/113] 8149405: OOM Error running java/lang/invoke/MethodHandlesTest.java on windows-x86 Add missing ResourceMarks to release memory more quickly. Reviewed-by: jmasa, kbarrett --- hotspot/src/share/vm/oops/methodData.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index d5f5d6ad454..85f7c9b6098 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1729,6 +1729,7 @@ void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { } void MethodData::clean_method_data(BoolObjectClosure* is_alive) { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1745,6 +1746,7 @@ void MethodData::clean_method_data(BoolObjectClosure* is_alive) { } void MethodData::clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1758,6 +1760,7 @@ void MethodData::clean_weak_method_links() { #ifdef ASSERT void MethodData::verify_clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { From 7e7ae63929c0fe629d2443bcd1bbd9892cea029c Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 13 Apr 2016 11:13:14 +0200 Subject: [PATCH 076/113] 8154087: Fix AIX and Linux/ppc64le after the integration of the new hotspot build Reviewed-by: erikj, goetz --- hotspot/makefiles/gensrc/GensrcAdlc.gmk | 7 +++---- hotspot/src/os/aix/vm/perfMemory_aix.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/hotspot/makefiles/gensrc/GensrcAdlc.gmk b/hotspot/makefiles/gensrc/GensrcAdlc.gmk index eb58ac7737c..a33d42db206 100644 --- a/hotspot/makefiles/gensrc/GensrcAdlc.gmk +++ b/hotspot/makefiles/gensrc/GensrcAdlc.gmk @@ -41,9 +41,8 @@ ifeq ($(call check-jvm-feature, compiler2), true) ADLC_CFLAGS := -m64 ADLC_CFLAGS_WARNINGS := +w else ifeq ($(OPENJDK_BUILD_OS), aix) - # FIXME: Not implemented. These flags are likely, however - # ADLC_LDFLAGS := -q64 - # ADLC_CFLAGS := -qnortti -qnoeh -q64 + ADLC_LDFLAGS := -q64 + ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX else ifeq ($(OPENJDK_BUILD_OS), windows) ADLC_LDFLAGS := -nologo ADLC_CFLAGS := -nologo -EHsc @@ -89,7 +88,7 @@ ifeq ($(call check-jvm-feature, compiler2), true) else ifeq ($(OPENJDK_TARGET_OS), solaris) ADLCFLAGS += -DSOLARIS=1 -DSPARC_WORKS=1 else ifeq ($(OPENJDK_TARGET_OS), aix) - # FIXME: Not implemented + ADLCFLAGS += -DAIX=1 else ifeq ($(OPENJDK_TARGET_OS), macosx) ADLCFLAGS += -D_ALLBSD_SOURCE=1 -D_GNU_SOURCE=1 endif diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index e9621012b7b..62212be7175 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -956,7 +956,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { #ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); #else - open_o_nofollow(filename, oflags); + result = open_o_nofollow(filename, oflags); #endif if (result == OS_ERR) { From bf3b2fe3608c363bed0e1aa1cefd9d31a73b668e Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 13 Apr 2016 11:13:14 +0200 Subject: [PATCH 077/113] 8154087: Fix AIX and Linux/ppc64le after the integration of the new hotspot build Reviewed-by: erikj, goetz --- common/autoconf/flags.m4 | 25 +++++------ common/autoconf/generated-configure.sh | 60 +++++++++++++++----------- common/autoconf/platform.m4 | 4 ++ 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 5e9fc128843..7789f01450e 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -929,20 +929,21 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], elif test "x$OPENJDK_$1_CPU" = xppc64; then if test "x$OPENJDK_$1_OS" = xlinux; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_$1_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_$1_OS" = xaix; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index d97c4b4ebc7..632dd15d1b0 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -5056,7 +5056,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1460103573 +DATE_WHEN_GENERATED=1460538705 ############################################################################### # @@ -15448,6 +15448,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_TARGET_CPU=sparc elif test "x$OPENJDK_TARGET_CPU" = xppc64; then HOTSPOT_TARGET_CPU=ppc_64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU=ppc_64 fi @@ -15466,6 +15468,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_TARGET_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_TARGET_CPU" = xppc64; then HOTSPOT_TARGET_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_TARGET_CPU" = xsparc; then @@ -15600,6 +15604,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_BUILD_CPU=sparc elif test "x$OPENJDK_BUILD_CPU" = xppc64; then HOTSPOT_BUILD_CPU=ppc_64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU=ppc_64 fi @@ -15618,6 +15624,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_BUILD_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_BUILD_CPU" = xppc64; then HOTSPOT_BUILD_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_BUILD_CPU" = xsparc; then @@ -49834,20 +49842,21 @@ $as_echo "$supports" >&6; } elif test "x$OPENJDK_TARGET_CPU" = xppc64; then if test "x$OPENJDK_TARGET_OS" = xlinux; then JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_TARGET_OS" = xaix; then JVM_CFLAGS="$JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then @@ -50610,20 +50619,21 @@ $as_echo "$supports" >&6; } elif test "x$OPENJDK_BUILD_CPU" = xppc64; then if test "x$OPENJDK_BUILD_OS" = xlinux; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_BUILD_OS" = xaix; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 587f80dbcd5..deaf22ed169 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -405,6 +405,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU=sparc elif test "x$OPENJDK_$1_CPU" = xppc64; then HOTSPOT_$1_CPU=ppc_64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU=ppc_64 fi AC_SUBST(HOTSPOT_$1_CPU) @@ -423,6 +425,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_$1_CPU" = xppc64; then HOTSPOT_$1_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then From 23da19a7903106b21f133b30a56107d98a158d4f Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Wed, 13 Apr 2016 19:55:40 +0400 Subject: [PATCH 078/113] 8153755: Improve test: stress/gc/TestStressRSetCoarsening.java Reviewed-by: tschatzl, kzhaldyb --- .../stress/gc/TestStressRSetCoarsening.java | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/stress/gc/TestStressRSetCoarsening.java index 10ac597facc..bf3cd499e13 100644 --- a/hotspot/test/stress/gc/TestStressRSetCoarsening.java +++ b/hotspot/test/stress/gc/TestStressRSetCoarsening.java @@ -38,29 +38,29 @@ import sun.hotspot.WhiteBox; * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 1 0 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=8m TestStressRSetCoarsening 1 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=32m TestStressRSetCoarsening 42 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 2 0 300 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 500 0 1800 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 10 10 1800 */ /** @@ -179,7 +179,13 @@ public class TestStressRSetCoarsening { // sizeOf(Object[N]) ~= (N+4)*refSize // ==> // N = regionSize / K / refSize - 4; - N = (int) ((regionSize / K) / refSize) - 5; + int n = (int) ((regionSize / K) / refSize) - 5; // best guess + long objSize = WB.getObjectSize(new Object[n]); + while (K*objSize > regionSize) { // adjust to avoid OOME + n = n - 1; + objSize = WB.getObjectSize(new Object[n]); + } + N = n; /* * -------------- @@ -202,8 +208,9 @@ public class TestStressRSetCoarsening { System.out.println("%% Objects"); System.out.println("%% N (array length) : " + N); System.out.println("%% K (objects in regions): " + K); + System.out.println("%% Object size : " + objSize + + " (sizeOf(new Object[" + N + "])"); System.out.println("%% Reference size : " + refSize); - System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); storage = new Object[regionCount * K][]; for (int i = 0; i < storage.length; i++) { From 8e63a10779d6c0d91479045785bdcb0dd3dfa577 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 13 Apr 2016 12:57:31 -0400 Subject: [PATCH 079/113] 8148772: VM crash in nsk/jvmti/RedefineClasses/StressRedefine: assert failed: Corrupted constant pool 8151546: nsk/jvmti/RedefineClasses/StressRedefine fails in hs nightly ConstantPool::resolve_constant_at_impl() isn't thread safe for MethodHandleInError and MethodTypeInError and Constant pool merging is not thread safe for source_file_name. Reviewed-by: sspitsyn, dcubed --- .../share/vm/classfile/javaClasses.inline.hpp | 23 ++++++------- hotspot/src/share/vm/oops/constantPool.cpp | 32 ++++++++--------- hotspot/src/share/vm/oops/constantPool.hpp | 34 ++++--------------- .../share/vm/prims/jvmtiRedefineClasses.cpp | 8 ++++- 4 files changed, 40 insertions(+), 57 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp index 1aba5b8f8c1..180bc5b40a4 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp @@ -222,20 +222,17 @@ inline int Backtrace::get_line_number(const methodHandle& method, int bci) { return line_number; } -/* - * Returns the source file name of a given InstanceKlass and version - */ inline Symbol* Backtrace::get_source_file_name(InstanceKlass* holder, int version) { - // Find the specific ik version that contains this source_file_name_index - // via the previous versions list, but use the current version's - // constant pool to look it up. The previous version's index has been - // merged for the current constant pool. - InstanceKlass* ik = holder->get_klass_version(version); - // This version has been cleaned up. - if (ik == NULL) return NULL; - int source_file_name_index = ik->source_file_name_index(); - return (source_file_name_index == 0) ? - (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index); + // RedefineClasses() currently permits redefine operations to + // happen in parallel using a "last one wins" philosophy. That + // spec laxness allows the constant pool entry associated with + // the source_file_name_index for any older constant pool version + // to be unstable so we shouldn't try to use it. + if (holder->constants()->version() != version) { + return NULL; + } else { + return holder->source_file_name(); + } } #endif // SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 996f5a50eef..708c2f77d86 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -395,7 +395,7 @@ int ConstantPool::impl_name_and_type_ref_index_at(int which, bool uncached) { int i = which; if (!uncached && cache() != NULL) { if (ConstantPool::is_invokedynamic_index(which)) { - // Invokedynamic index is index into resolved_references + // Invokedynamic index is index into the constant pool cache int pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index); assert(tag_at(pool_index).is_name_and_type(), ""); @@ -965,8 +965,8 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodType: { - int k1 = method_type_index_at_error_ok(index1); - int k2 = cp2->method_type_index_at_error_ok(index2); + int k1 = method_type_index_at(index1); + int k2 = cp2->method_type_index_at(index2); bool match = compare_entry_to(k1, cp2, k2, CHECK_false); if (match) { return true; @@ -975,11 +975,11 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodHandle: { - int k1 = method_handle_ref_kind_at_error_ok(index1); - int k2 = cp2->method_handle_ref_kind_at_error_ok(index2); + int k1 = method_handle_ref_kind_at(index1); + int k2 = cp2->method_handle_ref_kind_at(index2); if (k1 == k2) { - int i1 = method_handle_index_at_error_ok(index1); - int i2 = cp2->method_handle_index_at_error_ok(index2); + int i1 = method_handle_index_at(index1); + int i2 = cp2->method_handle_index_at(index2); bool match = compare_entry_to(i1, cp2, i2, CHECK_false); if (match) { return true; @@ -1311,15 +1311,15 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { - jint k = from_cp->method_type_index_at_error_ok(from_i); + jint k = from_cp->method_type_index_at(from_i); to_cp->method_type_index_at_put(to_i, k); } break; case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { - int k1 = from_cp->method_handle_ref_kind_at_error_ok(from_i); - int k2 = from_cp->method_handle_index_at_error_ok(from_i); + int k1 = from_cp->method_handle_ref_kind_at(from_i); + int k2 = from_cp->method_handle_index_at(from_i); to_cp->method_handle_index_at_put(to_i, k1, k2); } break; @@ -1755,8 +1755,8 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { *bytes = JVM_CONSTANT_MethodHandle; - int kind = method_handle_ref_kind_at_error_ok(idx); - idx1 = method_handle_index_at_error_ok(idx); + int kind = method_handle_ref_kind_at(idx); + idx1 = method_handle_index_at(idx); *(bytes+1) = (unsigned char) kind; Bytes::put_Java_u2((address) (bytes+2), idx1); DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1)); @@ -1765,7 +1765,7 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { *bytes = JVM_CONSTANT_MethodType; - idx1 = method_type_index_at_error_ok(idx); + idx1 = method_type_index_at(idx); Bytes::put_Java_u2((address) (bytes+1), idx1); DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1)); break; @@ -1953,12 +1953,12 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) { break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodHandleInError : - st->print("ref_kind=%d", method_handle_ref_kind_at_error_ok(index)); - st->print(" ref_index=%d", method_handle_index_at_error_ok(index)); + st->print("ref_kind=%d", method_handle_ref_kind_at(index)); + st->print(" ref_index=%d", method_handle_index_at(index)); break; case JVM_CONSTANT_MethodType : case JVM_CONSTANT_MethodTypeInError : - st->print("signature_index=%d", method_type_index_at_error_ok(index)); + st->print("signature_index=%d", method_type_index_at(index)); break; case JVM_CONSTANT_InvokeDynamic : { diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 9ed795cb303..75bca62917b 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -460,40 +460,20 @@ class ConstantPool : public Metadata { return *int_at_addr(which); } - private: - int method_handle_ref_kind_at(int which, bool error_ok) { + int method_handle_ref_kind_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits } - int method_handle_index_at(int which, bool error_ok) { + int method_handle_index_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits } - int method_type_index_at(int which, bool error_ok) { - assert(tag_at(which).is_method_type() || - (error_ok && tag_at(which).is_method_type_in_error()), "Corrupted constant pool"); - return *int_at_addr(which); - } - public: - int method_handle_ref_kind_at(int which) { - return method_handle_ref_kind_at(which, false); - } - int method_handle_ref_kind_at_error_ok(int which) { - return method_handle_ref_kind_at(which, true); - } - int method_handle_index_at(int which) { - return method_handle_index_at(which, false); - } - int method_handle_index_at_error_ok(int which) { - return method_handle_index_at(which, true); - } int method_type_index_at(int which) { - return method_type_index_at(which, false); - } - int method_type_index_at_error_ok(int which) { - return method_type_index_at(which, true); + assert(tag_at(which).is_method_type() || + tag_at(which).is_method_type_in_error(), "Corrupted constant pool"); + return *int_at_addr(which); } // Derived queries: diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 3410d9566c9..c6737e73617 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1443,8 +1443,9 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } - // Update the version number of the constant pool + // Update the version number of the constant pools (may keep scratch_cp) merge_cp->increment_and_save_version(old_cp->version()); + scratch_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; @@ -3911,6 +3912,11 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, method->set_constants(scratch_class->constants()); } + // NOTE: this doesn't work because you can redefine the same class in two + // threads, each getting their own constant pool data appended to the + // original constant pool. In order for the new methods to work when they + // become old methods, they need to keep their updated copy of the constant pool. + { // walk all previous versions of the klass InstanceKlass *ik = (InstanceKlass *)the_class(); From f474e970ba7fef84ed16ed7d5215ff940fff71b8 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Wed, 13 Apr 2016 15:53:46 -0500 Subject: [PATCH 080/113] 8153039: Command line processing should use mtCommand or mtArguments rather than mtInternal for NMT Added mtArguments and replaced argument related usages of mtInternal with the new flag. Reviewed-by: coleenp, gtriantafill --- hotspot/src/share/vm/memory/allocation.hpp | 5 +- hotspot/src/share/vm/runtime/arguments.cpp | 56 +++++++++---------- hotspot/src/share/vm/runtime/arguments.hpp | 16 +++--- .../runtime/commandLineFlagConstraintList.cpp | 2 +- .../runtime/commandLineFlagConstraintList.hpp | 2 +- .../vm/runtime/commandLineFlagRangeList.cpp | 2 +- .../vm/runtime/commandLineFlagRangeList.hpp | 2 +- hotspot/src/share/vm/runtime/globals.cpp | 4 +- hotspot/src/share/vm/services/nmtCommon.cpp | 1 + 9 files changed, 46 insertions(+), 44 deletions(-) diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 2705c6d8994..ec0e53977d6 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -143,8 +143,9 @@ enum MemoryType { mtTest = 0x0D, // Test type for verifying NMT mtTracing = 0x0E, // memory used for Tracing mtLogging = 0x0F, // memory for logging - mtNone = 0x10, // undefined - mt_number_of_types = 0x11 // number of memory types (mtDontTrack + mtArguments = 0x10, // memory for argument processing + mtNone = 0x11, // undefined + mt_number_of_types = 0x12 // number of memory types (mtDontTrack // is not included as validate type) }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d85c6a9fc3e..0ffe91cfb7e 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -698,7 +698,7 @@ char* ArgumentBootClassPath::combined_path() { assert(total_len > 0, "empty sysclasspath not allowed"); // Copy the _items to a single string. - char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal); + char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments); char* cp_tmp = cp; for (i = 0; i < _bcp_nitems; ++i) { if (_items[i] != NULL) { @@ -719,7 +719,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe assert(str != NULL, "just checking"); if (path == NULL) { size_t len = strlen(str) + 1; - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); memcpy(cp, str, len); // copy the trailing null } else { const char separator = *os::path_separator(); @@ -728,7 +728,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe size_t len = old_len + str_len + 2; if (prepend) { - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); char* cp_tmp = cp; memcpy(cp_tmp, str, str_len); cp_tmp += str_len; @@ -736,7 +736,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null FREE_C_HEAP_ARRAY(char, path); } else { - cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtInternal); + cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments); char* cp_tmp = cp + old_len; *cp_tmp = separator; memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null @@ -758,7 +758,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) /* Scan the directory for jars/zips, appending them to path. */ struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; const char* ext = name + strlen(name) - 4; @@ -766,7 +766,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) (os::file_name_strcmp(ext, ".jar") == 0 || os::file_name_strcmp(ext, ".zip") == 0); if (isJarOrZip) { - char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal); + char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments); sprintf(jarpath, "%s%s%s", directory, dir_sep, name); path = add_to_path(path, jarpath, false); FREE_C_HEAP_ARRAY(char, jarpath); @@ -943,7 +943,7 @@ static bool append_to_string_flag(const char* name, const char* new_value, Flag: } else if (new_len == 0) { value = old_value; } else { - char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal); + char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtArguments); // each new setting adds another LINE to the switch: sprintf(buf, "%s\n%s", old_value, new_value); value = buf; @@ -1134,9 +1134,9 @@ void Arguments::add_string(char*** bldarray, int* count, const char* arg) { // expand the array and add arg to the last element if (*bldarray == NULL) { - *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtInternal); + *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtArguments); } else { - *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal); + *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtArguments); } (*bldarray)[*count] = os::strdup_check_oom(arg); *count = new_count; @@ -1400,7 +1400,7 @@ bool Arguments::add_property(const char* prop) { // property have a value, thus extract it and save to the // allocated string size_t key_len = eq - prop; - char* tmp_key = AllocateHeap(key_len + 1, mtInternal); + char* tmp_key = AllocateHeap(key_len + 1, mtArguments); strncpy(tmp_key, prop, key_len); tmp_key[key_len] = '\0'; @@ -1422,7 +1422,7 @@ bool Arguments::add_property(const char* prop) { } else { if (strcmp(key, "sun.java.command") == 0) { char *old_java_command = _java_command; - _java_command = os::strdup_check_oom(value, mtInternal); + _java_command = os::strdup_check_oom(value, mtArguments); if (old_java_command != NULL) { os::free(old_java_command); } @@ -1430,7 +1430,7 @@ bool Arguments::add_property(const char* prop) { const char* old_java_vendor_url_bug = _java_vendor_url_bug; // save it in _java_vendor_url_bug, so JVM fatal error handler can access // its value without going through the property list or making a Java call. - _java_vendor_url_bug = os::strdup_check_oom(value, mtInternal); + _java_vendor_url_bug = os::strdup_check_oom(value, mtArguments); if (old_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) { assert(old_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL"); os::free((void *)old_java_vendor_url_bug); @@ -1458,7 +1458,7 @@ bool Arguments::append_to_addmods_property(const char* module_name) { if (old_value != NULL) { buf_len += strlen(old_value) + 1; } - char* new_value = AllocateHeap(buf_len, mtInternal); + char* new_value = AllocateHeap(buf_len, mtArguments); if (new_value == NULL) { return false; } @@ -2852,13 +2852,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if (tail != NULL) { const char* pos = strchr(tail, ':'); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { size_t len2 = strlen(pos+1) + 1; // options start after ':'. Final zero must be copied. - options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2); + options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtArguments), pos+1, len2); } #if !INCLUDE_JVMTI if (strcmp(name, "jdwp") == 0) { @@ -2875,12 +2875,12 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if(tail != NULL) { const char* pos = strchr(tail, '='); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { - options = os::strdup_check_oom(pos + 1, mtInternal); + options = os::strdup_check_oom(pos + 1, mtArguments); } #if !INCLUDE_JVMTI if (valid_jdwp_agent(name, is_absolute_path)) { @@ -2899,7 +2899,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_ERR; #else if (tail != NULL) { - char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail); + char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail); add_init_agent("instrument", options, false); // java agents need module java.instrument. Also -addmods ALL-SYSTEM because // the java agent is in the unmamed module of the application class loader @@ -3201,7 +3201,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, size_t len = strlen(patch_dirs[x]); if (len != 0) { // Ignore empty strings. len += 11; // file_sep + "java.base" + null terminator. - char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal); + char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments); jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep); // See if Xpatch module path exists. @@ -3507,7 +3507,7 @@ void Arguments::fix_appclasspath() { src ++; } - char* copy = os::strdup_check_oom(src, mtInternal); + char* copy = os::strdup_check_oom(src, mtArguments); // trim all trailing empty paths for (char* tail = copy + strlen(copy) - 1; tail >= copy && *tail == separator; tail--) { @@ -3531,7 +3531,7 @@ static bool has_jar_files(const char* directory) { if (dir == NULL) return false; struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); bool hasJarFile = false; while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; @@ -3557,7 +3557,7 @@ static int check_non_empty_dirs(const char* path) { } path = end; } else { - char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal); + char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtArguments); memcpy(dirpath, path, tmp_end - path); dirpath[tmp_end - path] = '\0'; if (has_jar_files(dirpath)) { @@ -3729,7 +3729,7 @@ class ScopedVMInitArgs : public StackObj { jint set_args(GrowableArray* options) { _is_set = true; JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL( - JavaVMOption, options->length(), mtInternal); + JavaVMOption, options->length(), mtArguments); if (options_arr == NULL) { return JNI_ENOMEM; } @@ -3784,7 +3784,7 @@ class ScopedVMInitArgs : public StackObj { assert(vm_options_file_pos != -1, "vm_options_file_pos should be set"); int length = args->nOptions + args_to_insert->nOptions - 1; - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(length, true); // Construct new option array for (int i = 0; i < args->nOptions; i++) { if (i == vm_options_file_pos) { @@ -3861,7 +3861,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v // '+ 1' for NULL termination even with max bytes size_t bytes_alloc = stbuf.st_size + 1; - char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtInternal); + char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtArguments); if (NULL == buf) { jio_fprintf(defaultStream::error_stream(), "Could not allocate read buffer for options file parse\n"); @@ -3898,7 +3898,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v } jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args) { - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(2, true); // Construct option array + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(2, true); // Construct option array // some pointers to help with parsing char *buffer_end = buffer + buf_len; @@ -4002,13 +4002,13 @@ static char* get_shared_archive_path() { size_t jvm_path_len = strlen(jvm_path); size_t file_sep_len = strlen(os::file_separator()); const size_t len = jvm_path_len + file_sep_len + 20; - shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal); + shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); if (shared_archive_path != NULL) { jio_snprintf(shared_archive_path, len, "%s%sclasses.jsa", jvm_path, os::file_separator()); } } else { - shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtInternal); + shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); } return shared_archive_path; } diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 328a9d71872..4df23a5b485 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -47,7 +47,7 @@ class ArgumentBootClassPath; // PathString is used as the underlying value container for a // SystemProperty and for the string that represents the system // boot class path, Arguments::_system_boot_class_path. -class PathString : public CHeapObj { +class PathString : public CHeapObj { protected: char* _value; public: @@ -57,7 +57,7 @@ class PathString : public CHeapObj { if (_value != NULL) { FreeHeap(_value); } - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); assert(_value != NULL, "Unable to allocate space for new path value"); if (_value != NULL) { strcpy(_value, value); @@ -76,7 +76,7 @@ class PathString : public CHeapObj { if (_value != NULL) { len += strlen(_value); } - sp = AllocateHeap(len+2, mtInternal); + sp = AllocateHeap(len+2, mtArguments); assert(sp != NULL, "Unable to allocate space for new append path value"); if (sp != NULL) { if (_value != NULL) { @@ -97,7 +97,7 @@ class PathString : public CHeapObj { if (value == NULL) { _value = NULL; } else { - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); strcpy(_value, value); } } @@ -143,7 +143,7 @@ class SystemProperty : public PathString { if (key == NULL) { _key = NULL; } else { - _key = AllocateHeap(strlen(key)+1, mtInternal); + _key = AllocateHeap(strlen(key)+1, mtArguments); strcpy(_key, key); } _next = NULL; @@ -154,7 +154,7 @@ class SystemProperty : public PathString { // For use by -agentlib, -agentpath and -Xrun -class AgentLibrary : public CHeapObj { +class AgentLibrary : public CHeapObj { friend class AgentLibraryList; public: // Is this library valid or not. Don't rely on os_lib == NULL as statically @@ -189,12 +189,12 @@ public: // Constructor AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) { - _name = AllocateHeap(strlen(name)+1, mtInternal); + _name = AllocateHeap(strlen(name)+1, mtArguments); strcpy(_name, name); if (options == NULL) { _options = NULL; } else { - _options = AllocateHeap(strlen(options)+1, mtInternal); + _options = AllocateHeap(strlen(options)+1, mtArguments); strcpy(_options, options); } _is_absolute_path = is_absolute_path; diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp index 2e0139c39e5..c79a48c9700 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp @@ -226,7 +226,7 @@ CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_valida // Check the ranges of all flags that have them or print them out and exit if requested void CommandLineFlagConstraintList::init(void) { - _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); + _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp index 5affa729c34..e7df3e9d551 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp @@ -48,7 +48,7 @@ typedef Flag::Error (*CommandLineFlagConstraintFunc_uint64_t)(uint64_t value, bo typedef Flag::Error (*CommandLineFlagConstraintFunc_size_t)(size_t value, bool verbose); typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(double value, bool verbose); -class CommandLineFlagConstraint : public CHeapObj { +class CommandLineFlagConstraint : public CHeapObj { public: // During VM initialization, constraint validation will be done order of ConstraintType. enum ConstraintType { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp index 2af4847d67a..89acace33f7 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp @@ -292,7 +292,7 @@ GrowableArray* CommandLineFlagRangeList::_ranges = NULL; // Check the ranges of all flags that have them void CommandLineFlagRangeList::init(void) { - _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_RANGES_SIZE, true); + _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_RANGES_SIZE, true); emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, EMIT_RANGE_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp index 4b2c1ea7caa..bc299d4f2a5 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp @@ -44,7 +44,7 @@ public: static void print(bool verbose, const char* msg, ...); }; -class CommandLineFlagRange : public CHeapObj { +class CommandLineFlagRange : public CHeapObj { private: const char* _name; public: diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 7e752adac01..ef98dd77f94 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -1292,7 +1292,7 @@ void CommandLineFlags::printSetFlags(outputStream* out) { const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } @@ -1326,7 +1326,7 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } diff --git a/hotspot/src/share/vm/services/nmtCommon.cpp b/hotspot/src/share/vm/services/nmtCommon.cpp index cffce8c7099..8633bbe301e 100644 --- a/hotspot/src/share/vm/services/nmtCommon.cpp +++ b/hotspot/src/share/vm/services/nmtCommon.cpp @@ -41,6 +41,7 @@ const char* NMTUtil::_memory_type_names[] = { "Test", "Tracing", "Logging", + "Arguments", "Unknown" }; From 1326ae31c82f077dedde31d2a0ee8579a8e3c62e Mon Sep 17 00:00:00 2001 From: Derek White Date: Wed, 13 Apr 2016 17:00:54 -0400 Subject: [PATCH 081/113] 8152905: hs_err file is missing gc threads List the GC threads in the hs_err file in the "Other Threads" section Reviewed-by: dcubed, coleenp --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 5 +- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 4 + .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 1 + hotspot/src/share/vm/runtime/thread.cpp | 81 +++++++++++-------- hotspot/src/share/vm/runtime/thread.hpp | 2 + 5 files changed, 56 insertions(+), 37 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 0f33720d7ca..75342af7fd5 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2742,7 +2742,7 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { _cmThread->print_on(st); st->cr(); _cm->print_worker_threads_on(st); - _cg1r->print_worker_threads_on(st); + _cg1r->print_worker_threads_on(st); // also prints the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::print_worker_threads_on(st); } @@ -2751,7 +2751,8 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { workers()->threads_do(tc); tc->do_thread(_cmThread); - _cg1r->threads_do(tc); + _cm->threads_do(tc); + _cg1r->threads_do(tc); // also iterates over the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::threads_do(tc); } diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 526387c018e..b36583e9822 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -2112,6 +2112,10 @@ void G1ConcurrentMark::print_worker_threads_on(outputStream* st) const { _parallel_workers->print_worker_threads_on(st); } +void G1ConcurrentMark::threads_do(ThreadClosure* tc) const { + _parallel_workers->threads_do(tc); +} + void G1ConcurrentMark::print_on_error(outputStream* st) const { st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, p2i(_prevMarkBitMap), p2i(_nextMarkBitMap)); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 36fb602de82..3b077d97a8a 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -621,6 +621,7 @@ public: void print_summary_info(); void print_worker_threads_on(outputStream* st) const; + void threads_do(ThreadClosure* tc) const; void print_on_error(outputStream* st) const; diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 1e56369bc3e..0a9ce34352d 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -818,13 +818,17 @@ void Thread::print_on(outputStream* st) const { // Thread::print_on_error() is called by fatal error handler. Don't use // any lock or allocate memory. void Thread::print_on_error(outputStream* st, char* buf, int buflen) const { - if (is_VM_thread()) st->print("VMThread"); - else if (is_Compiler_thread()) st->print("CompilerThread"); - else if (is_Java_thread()) st->print("JavaThread"); - else if (is_GC_task_thread()) st->print("GCTaskThread"); - else if (is_Watcher_thread()) st->print("WatcherThread"); - else if (is_ConcurrentGC_thread()) st->print("ConcurrentGCThread"); - else st->print("Thread"); + assert(!(is_Compiler_thread() || is_Java_thread()), "Can't call name() here if it allocates"); + + if (is_VM_thread()) { st->print("VMThread"); } + else if (is_GC_task_thread()) { st->print("GCTaskThread"); } + else if (is_Watcher_thread()) { st->print("WatcherThread"); } + else if (is_ConcurrentGC_thread()) { st->print("ConcurrentGCThread"); } + else { st->print("Thread"); } + + if (is_Named_thread()) { + st->print(" \"%s\"", name()); + } st->print(" [stack: " PTR_FORMAT "," PTR_FORMAT "]", p2i(stack_end()), p2i(stack_base())); @@ -4498,6 +4502,36 @@ void Threads::print_on(outputStream* st, bool print_stacks, st->flush(); } +void Threads::print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) { + if (this_thread != NULL) { + bool is_current = (current == this_thread); + *found_current = *found_current || is_current; + st->print("%s", is_current ? "=>" : " "); + + st->print(PTR_FORMAT, p2i(this_thread)); + st->print(" "); + this_thread->print_on_error(st, buf, buflen); + st->cr(); + } +} + +class PrintOnErrorClosure : public ThreadClosure { + outputStream* _st; + Thread* _current; + char* _buf; + int _buflen; + bool* _found_current; + public: + PrintOnErrorClosure(outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) : + _st(st), _current(current), _buf(buf), _buflen(buflen), _found_current(found_current) {} + + virtual void do_thread(Thread* thread) { + Threads::print_on_error(thread, _st, _current, _buf, _buflen, _found_current); + } +}; + // Threads::print_on_error() is called by fatal error handler. It's possible // that VM is not at safepoint and/or current thread is inside signal handler. // Don't print stack trace, as the stack may not be walkable. Don't allocate @@ -4507,40 +4541,17 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, bool found_current = false; st->print_cr("Java Threads: ( => current thread )"); ALL_JAVA_THREADS(thread) { - bool is_current = (current == thread); - found_current = found_current || is_current; - - st->print("%s", is_current ? "=>" : " "); - - st->print(PTR_FORMAT, p2i(thread)); - st->print(" "); - thread->print_on_error(st, buf, buflen); - st->cr(); + print_on_error(thread, st, current, buf, buflen, &found_current); } st->cr(); st->print_cr("Other Threads:"); - if (VMThread::vm_thread()) { - bool is_current = (current == VMThread::vm_thread()); - found_current = found_current || is_current; - st->print("%s", current == VMThread::vm_thread() ? "=>" : " "); + print_on_error(VMThread::vm_thread(), st, current, buf, buflen, &found_current); + print_on_error(WatcherThread::watcher_thread(), st, current, buf, buflen, &found_current); - st->print(PTR_FORMAT, p2i(VMThread::vm_thread())); - st->print(" "); - VMThread::vm_thread()->print_on_error(st, buf, buflen); - st->cr(); - } - WatcherThread* wt = WatcherThread::watcher_thread(); - if (wt != NULL) { - bool is_current = (current == wt); - found_current = found_current || is_current; - st->print("%s", is_current ? "=>" : " "); + PrintOnErrorClosure print_closure(st, current, buf, buflen, &found_current); + Universe::heap()->gc_threads_do(&print_closure); - st->print(PTR_FORMAT, p2i(wt)); - st->print(" "); - wt->print_on_error(st, buf, buflen); - st->cr(); - } if (!found_current) { st->cr(); st->print("=>" PTR_FORMAT " (exited) ", p2i(current)); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 0d54deec3ef..f5d7ac5b74d 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -2156,6 +2156,8 @@ class Threads: AllStatic { print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */); } static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen); + static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current); static void print_threads_compiling(outputStream* st, char* buf, int buflen); // Get Java threads that are waiting to enter a monitor. If doLock From a9e64aa5727667d690bc051047117b760bbe9d54 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 14 Apr 2016 08:30:15 +0200 Subject: [PATCH 082/113] 8154051: Change G1YoungGenSizer to use UL log_warning instead of warning Reviewed-by: brutisso, mgerdin --- hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp index cf7866770d5..e049f4da639 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp @@ -25,12 +25,13 @@ #include "precompiled.hpp" #include "gc/g1/g1YoungGenSizer.hpp" #include "gc/g1/heapRegion.hpp" +#include "logging/log.hpp" G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true), _min_desired_young_length(0), _max_desired_young_length(0) { if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { - warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); + log_warning(gc, ergo)("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { _sizer_kind = SizerNewRatio; _adaptive_size = false; @@ -40,9 +41,9 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size( if (NewSize > MaxNewSize) { if (FLAG_IS_CMDLINE(MaxNewSize)) { - warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " - "A new max generation size of " SIZE_FORMAT "k will be used.", - NewSize/K, MaxNewSize/K, NewSize/K); + log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " + "A new max generation size of " SIZE_FORMAT "k will be used.", + NewSize/K, MaxNewSize/K, NewSize/K); } MaxNewSize = NewSize; } From e79c2a2d8b8d7da1f677bc2164e114bfe2ecacc2 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 14 Apr 2016 08:30:37 +0200 Subject: [PATCH 083/113] 8153745: Avoid spawning G1ParPreserveCMReferentsTask when there is no work to be done Reviewed-by: brutisso, jmasa, tschatzl --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 25 ++++++++++++------- .../share/vm/gc/shared/referenceProcessor.cpp | 9 +++++++ .../share/vm/gc/shared/referenceProcessor.hpp | 3 +++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 75342af7fd5..3a775d5bca1 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4452,7 +4452,6 @@ void G1CollectedHeap::process_weak_jni_handles() { } void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { - double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4473,16 +4472,24 @@ void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_ // objects discovered by the STW ref processor in case one of these // referents points to another object which is also referenced by an // object discovered by the STW ref processor. + double preserve_cm_referents_time = 0.0; - uint no_of_gc_workers = workers()->active_workers(); + // To avoid spawning task when there is no work to do, check that + // a concurrent cycle is active and that some references have been + // discovered. + if (concurrent_mark()->cmThread()->during_cycle() && + ref_processor_cm()->has_discovered_references()) { + double preserve_cm_referents_start = os::elapsedTime(); + uint no_of_gc_workers = workers()->active_workers(); + G1ParPreserveCMReferentsTask keep_cm_referents(this, + per_thread_states, + no_of_gc_workers, + _task_queues); + workers()->run_task(&keep_cm_referents); + preserve_cm_referents_time = os::elapsedTime() - preserve_cm_referents_start; + } - G1ParPreserveCMReferentsTask keep_cm_referents(this, - per_thread_states, - no_of_gc_workers, - _task_queues); - workers()->run_task(&keep_cm_referents); - - g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms(preserve_cm_referents_time * 1000.0); } // Weak Reference processing during an evacuation pause (part 1). diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 22ed7b25d81..2200e7620a4 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -1090,6 +1090,15 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { return true; } +bool ReferenceProcessor::has_discovered_references() { + for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + if (!_discovered_refs[i].is_empty()) { + return true; + } + } + return false; +} + // Preclean the discovered references by removing those // whose referents are alive, and by marking from those that // are not active. These lists can be handled here diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp index 125f55bde72..c5d0f5f8321 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp @@ -412,6 +412,9 @@ class ReferenceProcessor : public CHeapObj { // Discover a Reference object, using appropriate discovery criteria bool discover_reference(oop obj, ReferenceType rt); + // Has discovered references that need handling + bool has_discovered_references(); + // Process references found during GC (called by the garbage collector) ReferenceProcessorStats process_discovered_references(BoolObjectClosure* is_alive, From 3bb96580fbb3fe61fb3b43ab7fb132681462a039 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 14 Apr 2016 11:17:34 +0200 Subject: [PATCH 084/113] 8073321: assert(q > prev_q) failed: we should be moving forward through memory Reviewed-by: jmasa, mgerdin --- .../vm/gc/cms/compactibleFreeListSpace.hpp | 2 + hotspot/src/share/vm/gc/shared/space.cpp | 16 - hotspot/src/share/vm/gc/shared/space.hpp | 16 +- .../src/share/vm/gc/shared/space.inline.hpp | 347 ++++++++++-------- 4 files changed, 194 insertions(+), 187 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index 92a2764afd0..d8f8e89b684 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -82,6 +82,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { template friend void CompactibleSpace::scan_and_compact(SpaceType* space); template + friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); + template friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp); // "Size" of chunks of work (executed during parallel remark phases diff --git a/hotspot/src/share/vm/gc/shared/space.cpp b/hotspot/src/share/vm/gc/shared/space.cpp index 5a020b1f74f..c207dcd74b5 100644 --- a/hotspot/src/share/vm/gc/shared/space.cpp +++ b/hotspot/src/share/vm/gc/shared/space.cpp @@ -411,22 +411,6 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, return compact_top; } - -bool CompactibleSpace::insert_deadspace(size_t& allowed_deadspace_words, - HeapWord* q, size_t deadlength) { - if (allowed_deadspace_words >= deadlength) { - allowed_deadspace_words -= deadlength; - CollectedHeap::fill_with_object(q, deadlength); - oop(q)->set_mark(oop(q)->mark()->set_marked()); - assert((int) deadlength == oop(q)->size(), "bad filler object size"); - // Recall that we required "q == compaction_top". - return true; - } else { - allowed_deadspace_words = 0; - return false; - } -} - void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { scan_and_forward(this, cp); } diff --git a/hotspot/src/share/vm/gc/shared/space.hpp b/hotspot/src/share/vm/gc/shared/space.hpp index 465dca90eb6..05eb3e1f27c 100644 --- a/hotspot/src/share/vm/gc/shared/space.hpp +++ b/hotspot/src/share/vm/gc/shared/space.hpp @@ -362,6 +362,12 @@ private: inline size_t obj_size(const HeapWord* addr) const; + template + static inline void verify_up_to_first_dead(SpaceType* space) NOT_DEBUG_RETURN; + + template + static inline void clear_empty_region(SpaceType* space); + public: CompactibleSpace() : _compaction_top(NULL), _next_compaction_space(NULL) {} @@ -455,16 +461,6 @@ protected: return end(); } - // Requires "allowed_deadspace_words > 0", that "q" is the start of a - // free block of the given "word_len", and that "q", were it an object, - // would not move if forwarded. If the size allows, fill the free - // block with an object, to prevent excessive compaction. Returns "true" - // iff the free region was made deadspace, and modifies - // "allowed_deadspace_words" to reflect the number of available deadspace - // words remaining after this operation. - bool insert_deadspace(size_t& allowed_deadspace_words, HeapWord* q, - size_t word_len); - // Below are template functions for scan_and_* algorithms (avoiding virtual calls). // The space argument should be a subclass of CompactibleSpace, implementing // scan_limit(), scanned_block_is_obj(), and scanned_block_size(), diff --git a/hotspot/src/share/vm/gc/shared/space.inline.hpp b/hotspot/src/share/vm/gc/shared/space.inline.hpp index 24cfb6213e8..3943a6da5dc 100644 --- a/hotspot/src/share/vm/gc/shared/space.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/space.inline.hpp @@ -31,6 +31,7 @@ #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "memory/universe.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" @@ -75,11 +76,61 @@ size_t CompactibleSpace::obj_size(const HeapWord* addr) const { return oop(addr)->size(); } +class DeadSpacer : StackObj { + size_t _allowed_deadspace_words; + bool _active; + CompactibleSpace* _space; + +public: + DeadSpacer(CompactibleSpace* space) : _space(space), _allowed_deadspace_words(0) { + size_t ratio = _space->allowed_dead_ratio(); + _active = ratio > 0; + + if (_active) { + assert(!UseG1GC, "G1 should not be using dead space"); + + // We allow some amount of garbage towards the bottom of the space, so + // we don't start compacting before there is a significant gain to be made. + // Occasionally, we want to ensure a full compaction, which is determined + // by the MarkSweepAlwaysCompactCount parameter. + if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { + _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; + } else { + _active = false; + } + } + } + + + bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { + if (!_active) { + return false; + } + + size_t dead_length = pointer_delta(dead_end, dead_start); + if (_allowed_deadspace_words >= dead_length) { + _allowed_deadspace_words -= dead_length; + CollectedHeap::fill_with_object(dead_start, dead_length); + oop obj = oop(dead_start); + obj->set_mark(obj->mark()->set_marked()); + + assert(dead_length == (size_t)obj->size(), "bad filler object size"); + log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", + p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); + + return true; + } else { + _active = false; + return false; + } + } + +}; + template inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { // Compute the new addresses for the live objects and store it in the mark // Used by universe::mark_sweep_phase2() - HeapWord* compact_top; // This is where we are currently compacting to. // We're sure to be here before any objects are compacted into this // space, so this is a good time to initialize this: @@ -90,89 +141,73 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c assert(cp->threshold == NULL, "just checking"); assert(cp->gen->first_compaction_space() == space, "just checking"); cp->space = cp->gen->first_compaction_space(); - compact_top = cp->space->bottom(); - cp->space->set_compaction_top(compact_top); cp->threshold = cp->space->initialize_threshold(); - } else { - compact_top = cp->space->compaction_top(); + cp->space->set_compaction_top(cp->space->bottom()); } - // We allow some amount of garbage towards the bottom of the space, so - // we don't start compacting before there is a significant gain to be made. - // Occasionally, we want to ensure a full compaction, which is determined - // by the MarkSweepAlwaysCompactCount parameter. - uint invocations = MarkSweep::total_invocations(); - bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); + HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to. - size_t allowed_deadspace = 0; - if (skip_dead) { - const size_t ratio = space->allowed_dead_ratio(); - allowed_deadspace = (space->capacity() * ratio / 100) / HeapWordSize; - } + DeadSpacer dead_spacer(space); - HeapWord* q = space->bottom(); - HeapWord* t = space->scan_limit(); - - HeapWord* end_of_live= q; // One byte beyond the last byte of the last - // live object. - HeapWord* first_dead = space->end(); // The first dead object. + HeapWord* end_of_live = space->bottom(); // One byte beyond the last byte of the last live object. + HeapWord* first_dead = NULL; // The first dead object. const intx interval = PrefetchScanIntervalInBytes; - while (q < t) { - assert(!space->scanned_block_is_obj(q) || - oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || - oop(q)->mark()->has_bias_pattern(), + HeapWord* cur_obj = space->bottom(); + HeapWord* scan_limit = space->scan_limit(); + + while (cur_obj < scan_limit) { + assert(!space->scanned_block_is_obj(cur_obj) || + oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() || + oop(cur_obj)->mark()->has_bias_pattern(), "these are the only valid states during a mark sweep"); - if (space->scanned_block_is_obj(q) && oop(q)->is_gc_marked()) { - // prefetch beyond q - Prefetch::write(q, interval); - size_t size = space->scanned_block_size(q); - compact_top = cp->space->forward(oop(q), size, cp, compact_top); - q += size; - end_of_live = q; + if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) { + // prefetch beyond cur_obj + Prefetch::write(cur_obj, interval); + size_t size = space->scanned_block_size(cur_obj); + compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); + cur_obj += size; + end_of_live = cur_obj; } else { // run over all the contiguous dead objects - HeapWord* end = q; + HeapWord* end = cur_obj; do { // prefetch beyond end Prefetch::write(end, interval); end += space->scanned_block_size(end); - } while (end < t && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); + } while (end < scan_limit && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); // see if we might want to pretend this object is alive so that // we don't have to compact quite as often. - if (allowed_deadspace > 0 && q == compact_top) { - size_t sz = pointer_delta(end, q); - if (space->insert_deadspace(allowed_deadspace, q, sz)) { - compact_top = cp->space->forward(oop(q), sz, cp, compact_top); - q = end; - end_of_live = end; - continue; + if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { + oop obj = oop(cur_obj); + compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); + end_of_live = end; + } else { + // otherwise, it really is a free region. + + // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. + *(HeapWord**)cur_obj = end; + + // see if this is the first dead region. + if (first_dead == NULL) { + first_dead = cur_obj; } } - // otherwise, it really is a free region. - - // q is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. - (*(HeapWord**)q) = end; - - // see if this is the first dead region. - if (q < first_dead) { - first_dead = q; - } - // move on to the next object - q = end; + cur_obj = end; } } - assert(q == t, "just checking"); + assert(cur_obj == scan_limit, "just checking"); space->_end_of_live = end_of_live; - if (end_of_live < first_dead) { - first_dead = end_of_live; + if (first_dead != NULL) { + space->_first_dead = first_dead; + } else { + space->_first_dead = end_of_live; } - space->_first_dead = first_dead; // save the compaction_top of the compaction space. cp->space->set_compaction_top(compact_top); @@ -183,127 +218,58 @@ inline void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space) { // adjust all the interior pointers to point at the new locations of objects // Used by MarkSweep::mark_sweep_phase3() - HeapWord* q = space->bottom(); - HeapWord* t = space->_end_of_live; // Established by "prepare_for_compaction". + HeapWord* cur_obj = space->bottom(); + HeapWord* const end_of_live = space->_end_of_live; // Established by "scan_and_forward". + HeapWord* const first_dead = space->_first_dead; // Established by "scan_and_forward". - assert(space->_first_dead <= space->_end_of_live, "Stands to reason, no?"); - - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - // we have a chunk of the space which hasn't moved and we've - // reinitialized the mark word during the previous pass, so we can't - // use is_gc_marked for the traversal. - HeapWord* end = space->_first_dead; - - while (q < end) { - // I originally tried to conjoin "block_start(q) == q" to the - // assertion below, but that doesn't work, because you can't - // accurately traverse previous objects to get to the current one - // after their pointers have been - // updated, until the actual compaction is done. dld, 4/00 - assert(space->block_is_obj(q), "should be at block boundaries, and should be looking at objs"); - - // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); - size = space->adjust_obj_size(size); - - q += size; - } - - if (space->_first_dead == t) { - q = t; - } else { - // The first dead object is no longer an object. At that memory address, - // there is a pointer to the first live object that the previous phase found. - q = *((HeapWord**)(space->_first_dead)); - } - } + assert(first_dead <= end_of_live, "Stands to reason, no?"); const intx interval = PrefetchScanIntervalInBytes; - debug_only(HeapWord* prev_q = NULL); - while (q < t) { - // prefetch beyond q - Prefetch::write(q, interval); - if (oop(q)->is_gc_marked()) { - // q is alive + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + Prefetch::write(cur_obj, interval); + if (cur_obj < first_dead || oop(cur_obj)->is_gc_marked()) { + // cur_obj is alive // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); + size_t size = MarkSweep::adjust_pointers(oop(cur_obj)); size = space->adjust_obj_size(size); - debug_only(prev_q = q); - q += size; + debug_only(prev_obj = cur_obj); + cur_obj += size; } else { - debug_only(prev_q = q); - // q is not a live object, instead it points at the next live object - q = *(HeapWord**)q; - assert(q > prev_q, "we should be moving forward through memory, q: " PTR_FORMAT ", prev_q: " PTR_FORMAT, p2i(q), p2i(prev_q)); + debug_only(prev_obj = cur_obj); + // cur_obj is not a live object, instead it points at the next live object + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory, cur_obj: " PTR_FORMAT ", prev_obj: " PTR_FORMAT, p2i(cur_obj), p2i(prev_obj)); } } - assert(q == t, "just checking"); + assert(cur_obj == end_of_live, "just checking"); } +#ifdef ASSERT template -inline void CompactibleSpace::scan_and_compact(SpaceType* space) { - // Copy all live objects to their new location - // Used by MarkSweep::mark_sweep_phase4() +inline void CompactibleSpace::verify_up_to_first_dead(SpaceType* space) { + HeapWord* cur_obj = space->bottom(); - HeapWord* q = space->bottom(); - HeapWord* const t = space->_end_of_live; - debug_only(HeapWord* prev_q = NULL); + if (cur_obj < space->_end_of_live && space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // we have a chunk of the space which hasn't moved and we've reinitialized + // the mark word during the previous pass, so we can't use is_gc_marked for + // the traversal. + HeapWord* prev_obj = NULL; - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - #ifdef ASSERT // Debug only - // we have a chunk of the space which hasn't moved and we've reinitialized - // the mark word during the previous pass, so we can't use is_gc_marked for - // the traversal. - HeapWord* const end = space->_first_dead; - - while (q < end) { - size_t size = space->obj_size(q); - assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); - prev_q = q; - q += size; - } - #endif - - if (space->_first_dead == t) { - q = t; - } else { - // $$$ Funky - q = (HeapWord*) oop(space->_first_dead)->mark()->decode_pointer(); - } - } - - const intx scan_interval = PrefetchScanIntervalInBytes; - const intx copy_interval = PrefetchCopyIntervalInBytes; - while (q < t) { - if (!oop(q)->is_gc_marked()) { - // mark is pointer to next marked oop - debug_only(prev_q = q); - q = (HeapWord*) oop(q)->mark()->decode_pointer(); - assert(q > prev_q, "we should be moving forward through memory"); - } else { - // prefetch beyond q - Prefetch::read(q, scan_interval); - - // size and destination - size_t size = space->obj_size(q); - HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); - - // prefetch beyond compaction_top - Prefetch::write(compaction_top, copy_interval); - - // copy object and reinit its mark - assert(q != compaction_top, "everything in this pass should be moving"); - Copy::aligned_conjoint_words(q, compaction_top, size); - oop(compaction_top)->init_mark(); - assert(oop(compaction_top)->klass() != NULL, "should have a class"); - - debug_only(prev_q = q); - q += size; - } + while (cur_obj < space->_first_dead) { + size_t size = space->obj_size(cur_obj); + assert(!oop(cur_obj)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); + prev_obj = cur_obj; + cur_obj += size; + } } +} +#endif +template +inline void CompactibleSpace::clear_empty_region(SpaceType* space) { // Let's remember if we were empty before we did the compaction. bool was_empty = space->used_region().is_empty(); // Reset space after compaction is complete @@ -320,6 +286,65 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { } } +template +inline void CompactibleSpace::scan_and_compact(SpaceType* space) { + // Copy all live objects to their new location + // Used by MarkSweep::mark_sweep_phase4() + + verify_up_to_first_dead(space); + + HeapWord* const end_of_live = space->_end_of_live; + + assert(space->_first_dead <= end_of_live, "Invariant. _first_dead: " PTR_FORMAT " <= end_of_live: " PTR_FORMAT, p2i(space->_first_dead), p2i(end_of_live)); + if (space->_first_dead == end_of_live && !oop(space->bottom())->is_gc_marked()) { + // Nothing to compact. The space is either empty or all live object should be left in place. + clear_empty_region(space); + return; + } + + const intx scan_interval = PrefetchScanIntervalInBytes; + const intx copy_interval = PrefetchCopyIntervalInBytes; + + assert(space->bottom() < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(space->bottom()), p2i(end_of_live)); + HeapWord* cur_obj = space->bottom(); + if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // All object before _first_dead can be skipped. They should not be moved. + // A pointer to the first live object is stored at the memory location for _first_dead. + cur_obj = *(HeapWord**)(space->_first_dead); + } + + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + if (!oop(cur_obj)->is_gc_marked()) { + debug_only(prev_obj = cur_obj); + // The first word of the dead object contains a pointer to the next live object or end of space. + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory"); + } else { + // prefetch beyond q + Prefetch::read(cur_obj, scan_interval); + + // size and destination + size_t size = space->obj_size(cur_obj); + HeapWord* compaction_top = (HeapWord*)oop(cur_obj)->forwardee(); + + // prefetch beyond compaction_top + Prefetch::write(compaction_top, copy_interval); + + // copy object and reinit its mark + assert(cur_obj != compaction_top, "everything in this pass should be moving"); + Copy::aligned_conjoint_words(cur_obj, compaction_top, size); + oop(compaction_top)->init_mark(); + assert(oop(compaction_top)->klass() != NULL, "should have a class"); + + debug_only(prev_obj = cur_obj); + cur_obj += size; + } + } + + clear_empty_region(space); +} + size_t ContiguousSpace::scanned_block_size(const HeapWord* addr) const { return oop(addr)->size(); } From e13ecd97b08dcb07ae1f8232a9fab2920379f815 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 14 Apr 2016 11:55:28 +0200 Subject: [PATCH 085/113] 8154064: JVMTI trace event crashes Reviewed-by: sla, stefank --- hotspot/src/share/vm/prims/jvmtiExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 20de3f979cb..edaea323658 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2260,7 +2260,7 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) { EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s", JvmtiTrace::safe_get_thread_name(thread), - object==NULL? "NULL" : java_lang_Class::as_Klass(object)->external_name())); + object==NULL? "NULL" : object->klass()->external_name())); JvmtiVMObjectAllocEventMark jem(thread, h()); JvmtiJavaThreadEventTransition jet(thread); From 8c6cc265f69f61c9a260520d8e1c591c76c27adc Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 14 Apr 2016 15:45:38 +0300 Subject: [PATCH 086/113] 8153222: [TESTBUG] Move tests in stress/gc to gc/stress Reviewed-by: dfazunen, jwilhelm --- hotspot/test/TEST.groups | 3 ++- hotspot/test/{stress/gc => gc/stress}/TestGCOld.java | 0 .../{stress/gc => gc/stress}/TestMultiThreadStressRSet.java | 0 .../{stress/gc => gc/stress}/TestStressIHOPMultiThread.java | 0 .../{stress/gc => gc/stress}/TestStressRSetCoarsening.java | 0 5 files changed, 2 insertions(+), 1 deletion(-) rename hotspot/test/{stress/gc => gc/stress}/TestGCOld.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestMultiThreadStressRSet.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestStressIHOPMultiThread.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestStressRSetCoarsening.java (100%) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 5705527c728..18dc949a024 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -338,6 +338,7 @@ hotspot_fast_gc_2 = \ sanity/ExecuteInternalVMTests.java \ gc/ \ -gc/g1/ \ + -gc/stress \ -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \ -gc/cms/TestMBeanCMS.java \ -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -346,7 +347,7 @@ hotspot_fast_gc_closed = \ sanity/ExecuteInternalVMTests.java hotspot_fast_gc_gcold = \ - stress/gc/TestGCOld.java + gc/stress/TestGCOld.java hotspot_fast_runtime = \ runtime/ \ diff --git a/hotspot/test/stress/gc/TestGCOld.java b/hotspot/test/gc/stress/TestGCOld.java similarity index 100% rename from hotspot/test/stress/gc/TestGCOld.java rename to hotspot/test/gc/stress/TestGCOld.java diff --git a/hotspot/test/stress/gc/TestMultiThreadStressRSet.java b/hotspot/test/gc/stress/TestMultiThreadStressRSet.java similarity index 100% rename from hotspot/test/stress/gc/TestMultiThreadStressRSet.java rename to hotspot/test/gc/stress/TestMultiThreadStressRSet.java diff --git a/hotspot/test/stress/gc/TestStressIHOPMultiThread.java b/hotspot/test/gc/stress/TestStressIHOPMultiThread.java similarity index 100% rename from hotspot/test/stress/gc/TestStressIHOPMultiThread.java rename to hotspot/test/gc/stress/TestStressIHOPMultiThread.java diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/gc/stress/TestStressRSetCoarsening.java similarity index 100% rename from hotspot/test/stress/gc/TestStressRSetCoarsening.java rename to hotspot/test/gc/stress/TestStressRSetCoarsening.java From acd52761a2d4edc68f4961a49dbdde3b1a2c4415 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 14 Apr 2016 09:46:03 -0400 Subject: [PATCH 087/113] 8152845: Improve PackageEntry and ModuleEntry print methods for future logging Changed print methods for PackageEntry and ModuleEntry to take an outputStream Reviewed-by: lfoltan, hseigel, coleenp --- .../src/share/vm/classfile/moduleEntry.cpp | 29 +++++++++---------- .../src/share/vm/classfile/moduleEntry.hpp | 5 ++-- .../src/share/vm/classfile/packageEntry.cpp | 23 +++++++-------- .../src/share/vm/classfile/packageEntry.hpp | 5 ++-- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index e86ed6acabf..3386dc43c1e 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -36,6 +36,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" ModuleEntry* ModuleEntryTable::_javabase_module = NULL; @@ -359,31 +360,29 @@ void ModuleEntryTable::patch_javabase_entries(Handle module_handle) { java_lang_Class::set_fixup_module_field_list(NULL); } -#ifndef PRODUCT -void ModuleEntryTable::print() { - tty->print_cr("Module Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void ModuleEntryTable::print(outputStream* st) { + st->print_cr("Module Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (ModuleEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void ModuleEntry::print() { +void ModuleEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, - p2i(this), - name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), - p2i(module()), - loader()->loader_name(), - version() != NULL ? version()->as_C_string() : "NULL", - location() != NULL ? location()->as_C_string() : "NULL", - BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); + st->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, + p2i(this), + name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), + p2i(module()), + loader()->loader_name(), + version() != NULL ? version()->as_C_string() : "NULL", + location() != NULL ? location()->as_C_string() : "NULL", + BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); } -#endif void ModuleEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp index d67251c1869..87accbeab41 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.hpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp @@ -33,6 +33,7 @@ #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" #define UNNAMED_MODULE "Unnamed Module" @@ -141,7 +142,7 @@ public: void purge_reads(); void delete_reads(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -223,7 +224,7 @@ public: static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location); static void patch_javabase_entries(Handle module_handle); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp index b3117d483c1..ec6d4d08428 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.cpp +++ b/hotspot/src/share/vm/classfile/packageEntry.cpp @@ -32,6 +32,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" // Return true if this package is exported to m. bool PackageEntry::is_qexported_to(ModuleEntry* m) const { @@ -265,28 +266,26 @@ void PackageEntryTable::purge_all_package_exports() { } } -#ifndef PRODUCT -void PackageEntryTable::print() { - tty->print_cr("Package Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void PackageEntryTable::print(outputStream* st) { + st->print_cr("Package Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (PackageEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void PackageEntry::print() { +void PackageEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " - INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, - p2i(this), name()->as_C_string(), - (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), - _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); + st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " + INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, + p2i(this), name()->as_C_string(), + (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), + _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); } -#endif void PackageEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp index 368609c21b6..00b7b9d160f 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.hpp +++ b/hotspot/src/share/vm/classfile/packageEntry.hpp @@ -29,6 +29,7 @@ #include "oops/symbol.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" // A PackageEntry basically represents a Java package. It contains: // - Symbol* containing the package's name. @@ -144,7 +145,7 @@ public: void purge_qualified_exports(); void delete_qualified_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -195,7 +196,7 @@ public: // purge dead weak references out of exported list void purge_all_package_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; From 33aa33f03a83d5fd09dee99d89397a7b572b2cd5 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 18 Apr 2016 13:42:52 -0400 Subject: [PATCH 088/113] 8154268: [TESTBUG] Compilation of ExportAllUnnamed.java failed, missing @modules Add missing @modules and @build tags Reviewed-by: ctornqvi, lfoltan, gtriantafill --- .../test/runtime/modules/AccessCheck/ExportAllUnnamed.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java index cb09a5315d6..a75fda9668f 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java @@ -28,11 +28,12 @@ * @summary Test if package p2 in module m2 is exported to all unnamed, * then class p1.c1 in an unnamed module can read p2.c2 in module m2. * @library /testlibrary /test/lib + * @modules java.base/jdk.internal.module * @compile myloaders/MySameClassLoader.java * @compile p2/c2.java * @compile p1/c1.java - * @compile -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED ExportAllUnnamed.java - * @run main/othervm -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED -Xbootclasspath/a:. ExportAllUnnamed + * @build ExportAllUnnamed + * @run main/othervm -Xbootclasspath/a:. ExportAllUnnamed */ import static jdk.test.lib.Asserts.*; From 3079c942b60af576b0293cf26e755403b230e5f3 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 18 Apr 2016 14:52:31 -0400 Subject: [PATCH 089/113] 8133051: Concurrent refinement threads may be activated and deactivated at random Establish min threshold step; earlier primary refinement thread activation. Reviewed-by: tschatzl, drwhite, mgerdin, jmasa --- .../src/share/vm/gc/g1/concurrentG1Refine.cpp | 301 ++++++++++++++---- .../src/share/vm/gc/g1/concurrentG1Refine.hpp | 32 +- .../vm/gc/g1/concurrentG1RefineThread.cpp | 34 +- .../vm/gc/g1/concurrentG1RefineThread.hpp | 12 +- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 16 +- hotspot/src/share/vm/logging/logPrefix.hpp | 1 + hotspot/src/share/vm/runtime/arguments.cpp | 4 +- .../share/vm/utilities/globalDefinitions.hpp | 11 +- .../TestG1ConcRefinementThreads.java | 8 +- 9 files changed, 302 insertions(+), 117 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index 3a4d5ede251..e67c8932a8b 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -29,42 +29,174 @@ #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1Predictions.hpp" #include "runtime/java.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/pair.hpp" +#include -ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictor) : - _threads(NULL), - _sample_thread(NULL), - _predictor_sigma(predictor->sigma()), - _hot_card_cache(g1h) -{ - // Ergonomically select initial concurrent refinement parameters - if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); +// Arbitrary but large limits, to simplify some of the zone calculations. +// The general idea is to allow expressions like +// MIN2(x OP y, max_XXX_zone) +// without needing to check for overflow in "x OP y", because the +// ranges for x and y have been restricted. +STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)); +const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort); +const size_t max_green_zone = max_yellow_zone / 2; +const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue. +STATIC_ASSERT(max_yellow_zone <= max_red_zone); + +// Range check assertions for green zone values. +#define assert_zone_constraints_g(green) \ + do { \ + size_t azc_g_green = (green); \ + assert(azc_g_green <= max_green_zone, \ + "green exceeds max: " SIZE_FORMAT, azc_g_green); \ + } while (0) + +// Range check assertions for green and yellow zone values. +#define assert_zone_constraints_gy(green, yellow) \ + do { \ + size_t azc_gy_green = (green); \ + size_t azc_gy_yellow = (yellow); \ + assert_zone_constraints_g(azc_gy_green); \ + assert(azc_gy_yellow <= max_yellow_zone, \ + "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \ + assert(azc_gy_green <= azc_gy_yellow, \ + "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \ + azc_gy_green, azc_gy_yellow); \ + } while (0) + +// Range check assertions for green, yellow, and red zone values. +#define assert_zone_constraints_gyr(green, yellow, red) \ + do { \ + size_t azc_gyr_green = (green); \ + size_t azc_gyr_yellow = (yellow); \ + size_t azc_gyr_red = (red); \ + assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \ + assert(azc_gyr_red <= max_red_zone, \ + "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \ + assert(azc_gyr_yellow <= azc_gyr_red, \ + "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \ + azc_gyr_yellow, azc_gyr_red); \ + } while (0) + +// Logging tag sequence for refinement control updates. +#define CTRL_TAGS gc, ergo, refine + +// For logging zone values, ensuring consistency of level and tags. +#define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__) + +// Package for pair of refinement thread activation and deactivation +// thresholds. The activation and deactivation levels are resp. the first +// and second values of the pair. +typedef Pair Thresholds; +inline size_t activation_level(const Thresholds& t) { return t.first; } +inline size_t deactivation_level(const Thresholds& t) { return t.second; } + +static Thresholds calc_thresholds(size_t green_zone, + size_t yellow_zone, + uint worker_i) { + double yellow_size = yellow_zone - green_zone; + double step = yellow_size / ConcurrentG1Refine::thread_num(); + if (worker_i == 0) { + // Potentially activate worker 0 more aggressively, to keep + // available buffers near green_zone value. When yellow_size is + // large we don't want to allow a full step to accumulate before + // doing any processing, as that might lead to significantly more + // than green_zone buffers to be processed by update_rs. + step = MIN2(step, ParallelGCThreads / 2.0); } - set_green_zone(G1ConcRefinementGreenZone); - - if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); - } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); - - if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); - } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); - + size_t activate_offset = static_cast(ceil(step * (worker_i + 1))); + size_t deactivate_offset = static_cast(floor(step * worker_i)); + return Thresholds(green_zone + activate_offset, + green_zone + deactivate_offset); } -ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { - G1CollectorPolicy* policy = g1h->g1_policy(); - ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, &policy->predictor()); +ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size) : + _threads(NULL), + _sample_thread(NULL), + _n_worker_threads(thread_num()), + _green_zone(green_zone), + _yellow_zone(yellow_zone), + _red_zone(red_zone), + _min_yellow_zone_size(min_yellow_zone_size), + _hot_card_cache(g1h) +{ + assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone); +} + +static size_t calc_min_yellow_zone_size() { + size_t step = G1ConcRefinementThresholdStep; + uint n_workers = ConcurrentG1Refine::thread_num(); + if ((max_yellow_zone / step) < n_workers) { + return max_yellow_zone; + } else { + return step * n_workers; + } +} + +static size_t calc_init_green_zone() { + size_t green = G1ConcRefinementGreenZone; + if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { + green = ParallelGCThreads; + } + return MIN2(green, max_green_zone); +} + +static size_t calc_init_yellow_zone(size_t green, size_t min_size) { + size_t config = G1ConcRefinementYellowZone; + size_t size = 0; + if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { + size = green * 2; + } else if (green < config) { + size = config - green; + } + size = MAX2(size, min_size); + size = MIN2(size, max_yellow_zone); + return MIN2(green + size, max_yellow_zone); +} + +static size_t calc_init_red_zone(size_t green, size_t yellow) { + size_t size = yellow - green; + if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { + size_t config = G1ConcRefinementRedZone; + if (yellow < config) { + size = MAX2(size, config - yellow); + } + } + return MIN2(yellow + size, max_red_zone); +} + +ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, + CardTableEntryClosure* refine_closure, + jint* ecode) { + size_t min_yellow_zone_size = calc_min_yellow_zone_size(); + size_t green_zone = calc_init_green_zone(); + size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size); + size_t red_zone = calc_init_red_zone(green_zone, yellow_zone); + + LOG_ZONES("Initial Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT ", " + "min yellow size: " SIZE_FORMAT, + green_zone, yellow_zone, red_zone, min_yellow_zone_size); + + ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, + green_zone, + yellow_zone, + red_zone, + min_yellow_zone_size); + if (cg1r == NULL) { *ecode = JNI_ENOMEM; vm_shutdown_during_initialization("Could not create ConcurrentG1Refine"); return NULL; } - cg1r->_n_worker_threads = thread_num(); - - cg1r->reset_threshold_step(); cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC); if (cg1r->_threads == NULL) { @@ -77,7 +209,15 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn ConcurrentG1RefineThread *next = NULL; for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) { - ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i); + Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i); + ConcurrentG1RefineThread* t = + new ConcurrentG1RefineThread(cg1r, + next, + refine_closure, + worker_id_offset, + i, + activation_level(thresholds), + deactivation_level(thresholds)); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { *ecode = JNI_ENOMEM; @@ -101,14 +241,6 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn return cg1r; } -void ConcurrentG1Refine::reset_threshold_step() { - if (FLAG_IS_DEFAULT(G1ConcRefinementThresholdStep)) { - _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1); - } else { - _thread_threshold_step = G1ConcRefinementThresholdStep; - } -} - void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) { _hot_card_cache.initialize(card_counts_storage); } @@ -120,10 +252,11 @@ void ConcurrentG1Refine::stop() { _sample_thread->stop(); } -void ConcurrentG1Refine::reinitialize_threads() { - reset_threshold_step(); +void ConcurrentG1Refine::update_thread_thresholds() { for (uint i = 0; i < _n_worker_threads; i++) { - _threads[i]->initialize(); + Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i); + _threads[i]->update_thresholds(activation_level(thresholds), + deactivation_level(thresholds)); } } @@ -142,7 +275,7 @@ void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { } void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { - for (uint i = 0; i < worker_thread_num(); i++) { + for (uint i = 0; i < _n_worker_threads; i++) { tc->do_thread(_threads[i]); } } @@ -160,34 +293,80 @@ void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { st->cr(); } +static size_t calc_new_green_zone(size_t green, + double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + // Adjust green zone based on whether we're meeting the time goal. + // Limit to max_green_zone. + const double inc_k = 1.1, dec_k = 0.9; + if (update_rs_time > goal_ms) { + if (green > 0) { + green = static_cast(green * dec_k); + } + } else if (update_rs_time < goal_ms && + update_rs_processed_buffers > green) { + green = static_cast(MAX2(green * inc_k, green + 1.0)); + green = MIN2(green, max_green_zone); + } + return green; +} + +static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) { + size_t size = green * 2; + size = MAX2(size, min_yellow_size); + return MIN2(green + size, max_yellow_zone); +} + +static size_t calc_new_red_zone(size_t green, size_t yellow) { + return MIN2(yellow + (yellow - green), max_red_zone); +} + +void ConcurrentG1Refine::update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + log_trace( CTRL_TAGS )("Updating Refinement Zones: " + "update_rs time: %.3fms, " + "update_rs buffers: " SIZE_FORMAT ", " + "update_rs goal time: %.3fms", + update_rs_time, + update_rs_processed_buffers, + goal_ms); + + _green_zone = calc_new_green_zone(_green_zone, + update_rs_time, + update_rs_processed_buffers, + goal_ms); + _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); + _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); + + assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone); + LOG_ZONES("Updated Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT, + _green_zone, _yellow_zone, _red_zone); +} + void ConcurrentG1Refine::adjust(double update_rs_time, - double update_rs_processed_buffers, + size_t update_rs_processed_buffers, double goal_ms) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); if (G1UseAdaptiveConcRefinement) { - const int k_gy = 3, k_gr = 6; - const double inc_k = 1.1, dec_k = 0.9; + update_zones(update_rs_time, update_rs_processed_buffers, goal_ms); + update_thread_thresholds(); - size_t g = green_zone(); - if (update_rs_time > goal_ms) { - g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. - } else { - if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (size_t)MAX2(g * inc_k, g + 1.0); - } - } - // Change the refinement threads params - set_green_zone(g); - set_yellow_zone(g * k_gy); - set_red_zone(g * k_gr); - reinitialize_threads(); - - size_t processing_threshold_delta = MAX2(green_zone() * _predictor_sigma, 1); - size_t processing_threshold = MIN2(green_zone() + processing_threshold_delta, - yellow_zone()); // Change the barrier params - dcqs.set_process_completed_threshold((int)processing_threshold); + if (_n_worker_threads == 0) { + // Disable dcqs notification when there are no threads to notify. + dcqs.set_process_completed_threshold(INT_MAX); + } else { + // Worker 0 is the primary; wakeup is via dcqs notification. + STATIC_ASSERT(max_yellow_zone <= INT_MAX); + size_t activate = _threads[0]->activation_threshold(); + dcqs.set_process_completed_threshold((int)activate); + } dcqs.set_max_completed_queue((int)red_zone()); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index 3161f62f2b2..098d49e801d 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -65,18 +65,24 @@ class ConcurrentG1Refine: public CHeapObj { size_t _green_zone; size_t _yellow_zone; size_t _red_zone; - - size_t _thread_threshold_step; - - double _predictor_sigma; + size_t _min_yellow_zone_size; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; - // Reset the threshold step value based of the current zone boundaries. - void reset_threshold_step(); + ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size); - ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictions); + // Update green/yellow/red zone values based on how well goals are being met. + void update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms); + + // Update thread thresholds to account for updated zone values. + void update_thread_thresholds(); public: ~ConcurrentG1Refine(); @@ -88,9 +94,7 @@ class ConcurrentG1Refine: public CHeapObj { void init(G1RegionToSpaceMapper* card_counts_storage); void stop(); - void adjust(double update_rs_time, double update_rs_processed_buffers, double goal_ms); - - void reinitialize_threads(); + void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms); // Iterate over all concurrent refinement threads void threads_do(ThreadClosure *tc); @@ -105,18 +109,10 @@ class ConcurrentG1Refine: public CHeapObj { void print_worker_threads_on(outputStream* st) const; - void set_green_zone(size_t x) { _green_zone = x; } - void set_yellow_zone(size_t x) { _yellow_zone = x; } - void set_red_zone(size_t x) { _red_zone = x; } - size_t green_zone() const { return _green_zone; } size_t yellow_zone() const { return _yellow_zone; } size_t red_zone() const { return _red_zone; } - uint worker_thread_num() const { return _n_worker_threads; } - - size_t thread_threshold_step() const { return _thread_threshold_step; } - G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } static bool hot_card_cache_enabled() { return G1HotCardCache::default_use_cache(); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index 78bea91e71b..8f9ebfbfb68 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -36,7 +36,8 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id) : + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate) : ConcurrentGCThread(), _refine_closure(refine_closure), _worker_id_offset(worker_id_offset), @@ -45,7 +46,9 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex _next(next), _monitor(NULL), _cg1r(cg1r), - _vtime_accum(0.0) + _vtime_accum(0.0), + _activation_threshold(activate), + _deactivation_threshold(deactivate) { // Each thread has its own monitor. The i-th thread is responsible for signaling @@ -58,21 +61,17 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex } else { _monitor = DirtyCardQ_CBL_mon; } - initialize(); // set name set_name("G1 Refine#%d", worker_id); create_and_start(); } -void ConcurrentG1RefineThread::initialize() { - // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); - // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = - MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), - cg1r()->green_zone()); +void ConcurrentG1RefineThread::update_thresholds(size_t activate, + size_t deactivate) { + assert(deactivate < activate, "precondition"); + _activation_threshold = activate; + _deactivation_threshold = deactivate; } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -118,9 +117,10 @@ void ConcurrentG1RefineThread::run_service() { break; } + size_t buffers_processed = 0; DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _threshold, dcqs.completed_buffers_num()); + _worker_id, _activation_threshold, dcqs.completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; @@ -139,7 +139,9 @@ void ConcurrentG1RefineThread::run_service() { } // Check if we need to activate the next thread. - if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { + if ((_next != NULL) && + !_next->is_active() && + (curr_buffer_num > _next->_activation_threshold)) { _next->activate(); } @@ -150,14 +152,16 @@ void ConcurrentG1RefineThread::run_service() { false /* during_pause */)) { break; // Deactivate, number of buffers fell below threshold. } + ++buffers_processed; } } deactivate(); log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT - ", current: " SIZE_FORMAT, + ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, _worker_id, _deactivation_threshold, - dcqs.completed_buffers_num()); + dcqs.completed_buffers_num(), + buffers_processed); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index 9f325599cfc..902d77cb9f6 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -53,10 +53,8 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - size_t _thread_threshold_step; - // This thread activation threshold - size_t _threshold; - // This thread deactivation threshold + // This thread's activation/deactivation thresholds + size_t _activation_threshold; size_t _deactivation_threshold; void wait_for_completed_buffers(); @@ -75,9 +73,11 @@ public: // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id); + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate); - void initialize(); + void update_thresholds(size_t activate, size_t deactivate); + size_t activation_threshold() const { return _activation_threshold; } // Total virtual time so far. double vtime_accum() { return _vtime_accum; } diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index f015e4e9ee1..ce8d96ea3ec 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -112,8 +112,7 @@ product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ - "Will be selected ergonomically by default. Zero will disable " \ - "concurrent processing.") \ + "Will be selected ergonomically by default.") \ range(0, max_intx) \ \ product(size_t, G1ConcRefinementGreenZone, 0, \ @@ -127,11 +126,12 @@ "specified number of milliseconds to do miscellaneous work.") \ range(0, max_jint) \ \ - product(size_t, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 2, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ - "Will be selected ergonomically by default.") \ - range(0, SIZE_MAX) \ + "The actual step size will be selected ergonomically by " \ + "default, with this value used to determine a lower bound.") \ + range(1, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ @@ -201,9 +201,9 @@ range(0, 32*M) \ constraint(G1HeapRegionSizeConstraintFunc,AfterMemoryInit) \ \ - product(uintx, G1ConcRefinementThreads, 0, \ - "If non-0 is the number of parallel rem set update threads, " \ - "otherwise the value is determined ergonomically.") \ + product(uint, G1ConcRefinementThreads, 0, \ + "The number of parallel rem set update threads. " \ + "Will be set ergonomically by default.") \ range(0, (max_jint-1)/wordSize) \ \ develop(bool, G1VerifyCTCleanup, false, \ diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 48d342d1ba8..8d2ae12adf3 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -55,6 +55,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);) LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, cset)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, ihop)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, refine)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, freelist)) \ diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 0ffe91cfb7e..7fa2ea8a7ad 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2095,8 +2095,8 @@ void Arguments::set_g1_gc_flags() { } #if INCLUDE_ALL_GCS - if (G1ConcRefinementThreads == 0) { - FLAG_SET_DEFAULT(G1ConcRefinementThreads, ParallelGCThreads); + if (FLAG_IS_DEFAULT(G1ConcRefinementThreads)) { + FLAG_SET_ERGO(uint, G1ConcRefinementThreads, ParallelGCThreads); } #endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3c04e2a0f54..85186c1ffab 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -199,9 +199,6 @@ const size_t M = K*K; const size_t G = M*K; const size_t HWperKB = K / sizeof(HeapWord); -const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint -const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint - // Constants for converting from a base unit to milli-base units. For // example from seconds to milliseconds and microseconds @@ -381,6 +378,14 @@ typedef jshort s2; typedef jint s4; typedef jlong s8; +const jbyte min_jbyte = -(1 << 7); // smallest jbyte +const jbyte max_jbyte = (1 << 7) - 1; // largest jbyte +const jshort min_jshort = -(1 << 15); // smallest jshort +const jshort max_jshort = (1 << 15) - 1; // largest jshort + +const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint +const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint + //---------------------------------------------------------------------------------------------------- // JVM spec restrictions diff --git a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java index 0a470191560..25b8e34414a 100644 --- a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java +++ b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java @@ -38,7 +38,7 @@ import java.util.regex.*; public class TestG1ConcRefinementThreads { - static final int AUTO_SELECT_THREADS_COUNT = 0; + static final int AUTO_SELECT_THREADS_COUNT = -1; static final int PASSED_THREADS_COUNT = 11; public static void main(String args[]) throws Exception { @@ -49,8 +49,8 @@ public class TestG1ConcRefinementThreads { // zero setting case runG1ConcRefinementThreadsTest( - new String[]{"-XX:G1ConcRefinementThreads=0"}, // automatically selected - AUTO_SELECT_THREADS_COUNT /* set to zero */); + new String[]{"-XX:G1ConcRefinementThreads=0"}, + 0); // non-zero sestting case runG1ConcRefinementThreadsTest( @@ -77,7 +77,7 @@ public class TestG1ConcRefinementThreads { private static void checkG1ConcRefinementThreadsConsistency(String output, int expectedValue) { int actualValue = getIntValue("G1ConcRefinementThreads", output); - if (expectedValue == 0) { + if (expectedValue == AUTO_SELECT_THREADS_COUNT) { // If expectedValue is automatically selected, set it same as ParallelGCThreads. expectedValue = getIntValue("ParallelGCThreads", output); } From 5acf187999317e172bc783dbb8ed6b87aaae1447 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 18 Apr 2016 14:11:16 -0700 Subject: [PATCH 090/113] 8145468: update java.lang APIs with new deprecations Reviewed-by: lancea, alanb --- make/CompileJavaModules.gmk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index c4275f863e3..4ce9cca25bf 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -98,7 +98,8 @@ java.datatransfer_COPY := flavormap.properties ################################################################################ -java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' +java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \ + '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties From ebb86eaa4f6da5ab0985b8ad4c8981fa43c494eb Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 19 Apr 2016 14:34:43 +0100 Subject: [PATCH 091/113] 8148863: Remove sun.misc.ManagedLocalsThread from corba Reviewed-by: alanb, coffeys, msheppar --- .../classes/com/sun/corba/se/impl/corba/RequestImpl.java | 2 +- .../classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java | 3 ++- .../share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java | 3 ++- .../classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java | 2 +- .../sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java | 3 ++- .../share/classes/com/sun/corba/se/impl/orb/ORBImpl.java | 2 +- .../sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java | 4 ++-- .../classes/com/sun/corba/se/impl/transport/SelectorImpl.java | 4 ++-- corba/src/java.corba/share/classes/module-info.java | 2 -- 9 files changed, 13 insertions(+), 12 deletions(-) diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java index 3c357f61c38..69b58393d95 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java @@ -255,7 +255,7 @@ public class RequestImpl public synchronized void send_deferred() { AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "Async-Request-Invoker-Thread", 0, false).start(); } public synchronized boolean poll_response() diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java index d9dceac7ba8..a9ae337883e 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java @@ -751,12 +751,13 @@ public class Util implements javax.rmi.CORBA.UtilDelegate } } -class KeepAlive extends sun.misc.ManagedLocalsThread +class KeepAlive extends Thread { boolean quit = false; public KeepAlive () { + super(null, null, "Servant-KeepAlive-Thread", 0, false); setDaemon(false); } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java index 546914d623d..3205a5c24be 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java @@ -516,7 +516,7 @@ public class POAImpl extends ObjectAdapterBase implements POA // Converted from anonymous class to local class // so that we can call performDestroy() directly. - static class DestroyThread extends sun.misc.ManagedLocalsThread { + static class DestroyThread extends Thread { private boolean wait ; private boolean etherealize ; private boolean debug ; @@ -524,6 +524,7 @@ public class POAImpl extends ObjectAdapterBase implements POA public DestroyThread( boolean etherealize, boolean debug ) { + super(null, null, "POA-Destroy-Thread", 0, false); this.etherealize = etherealize ; this.debug = debug ; } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java index 22610dda9ba..eb51310fcd3 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java @@ -357,7 +357,7 @@ public class POAManagerImpl extends org.omg.CORBA.LocalObject implements if (wait_for_completion) deactivator.run() ; else { - Thread thr = new sun.misc.ManagedLocalsThread(deactivator) ; + Thread thr = new Thread(null, deactivator, "POA-Deactivator-Thread", 0, false) ; thr.start() ; } } finally { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java index 9e9fce8a47d..1a8badc0930 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java @@ -302,7 +302,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { throw new WrongPolicy(); } - class Etherealizer extends sun.misc.ManagedLocalsThread { + class Etherealizer extends Thread { private POAPolicyMediatorImpl_R_USM mediator ; private ActiveObjectMap.Key key ; private AOMEntry entry ; @@ -314,6 +314,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { ActiveObjectMap.Key key, AOMEntry entry, Servant servant, boolean debug ) { + super(null, null, "PAO-Etherealizer-Thread", 0, false); this.mediator = mediator ; this.key = key ; this.entry = entry; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java index 82da35a7921..007e6b8dc28 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java @@ -691,7 +691,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB for (int i = 0; i < req.length; i++) { AsynchInvoke invokeObject = new AsynchInvoke( this, (com.sun.corba.se.impl.corba.RequestImpl)req[i], true); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "ORB-Request-Thread", 0, false).start(); } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java index 9a0e56afc4f..7f3ad89869c 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java @@ -459,7 +459,7 @@ public class ThreadPoolImpl implements ThreadPool } - private class WorkerThread extends sun.misc.ManagedLocalsThread implements Closeable + private class WorkerThread extends Thread implements Closeable { private Work currentWork; private int threadId = 0; // unique id for the thread @@ -469,7 +469,7 @@ public class ThreadPoolImpl implements ThreadPool private StringBuffer workerThreadName = new StringBuffer(); WorkerThread(ThreadGroup tg, String threadPoolName) { - super(tg, "Idle"); + super(tg, null, "Idle", 0, false); this.threadId = ThreadPoolImpl.getUniqueThreadId(); this.threadPoolName = threadPoolName; setName(composeWorkerThreadName(threadPoolName, "Idle")); diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index 016fd945abf..ac87ef9c932 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -61,7 +61,7 @@ import com.sun.corba.se.impl.orbutil.ORBUtility; */ class SelectorImpl extends - sun.misc.ManagedLocalsThread + Thread implements com.sun.corba.se.pept.transport.Selector { @@ -79,6 +79,7 @@ class SelectorImpl public SelectorImpl(ORB orb) { + super(null, null, "ORB-Selector-Thread", 0, false); this.orb = orb; selector = null; selectorStarted = false; @@ -277,7 +278,6 @@ class SelectorImpl public void run() { - setName("SelectorThread"); while (!closed) { try { int n = 0; diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java index 25f79def5cb..23da4b785a9 100644 --- a/corba/src/java.corba/share/classes/module-info.java +++ b/corba/src/java.corba/share/classes/module-info.java @@ -29,8 +29,6 @@ module java.corba { requires java.logging; requires java.naming; requires java.transaction; - // 8148863 - requires jdk.unsupported; exports javax.activity; exports javax.rmi; From d03b60789684f8a9e96b47c89b05b3c2e639c26a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Tue, 19 Apr 2016 23:01:06 -0700 Subject: [PATCH 092/113] 8153781: Issue in XMLScanner: EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET when skipping large DOCTYPE section with CRLF at wrong place Reviewed-by: joehw --- .../internal/impl/XML11EntityScanner.java | 25 +++--- .../internal/impl/XMLDTDScannerImpl.java | 55 +++++++----- .../impl/XMLDocumentFragmentScannerImpl.java | 14 +-- .../internal/impl/XMLDocumentScannerImpl.java | 17 ++-- .../internal/impl/XMLEntityScanner.java | 61 +++++++------ .../xerces/internal/impl/XMLScanner.java | 14 +-- .../internal/impl/msg/XMLMessages.properties | 1 + .../impl/msg/XMLMessages_de.properties | 1 + .../impl/msg/XMLMessages_es.properties | 1 + .../impl/msg/XMLMessages_fr.properties | 1 + .../impl/msg/XMLMessages_it.properties | 1 + .../xerces/internal/util/HTTPInputSource.java | 30 +++---- .../javax/xml/jaxp/unittest/TEST.properties | 3 +- .../XMLEventReaderTest/Bug6668115Test.java | 3 +- .../stream/XMLEventReaderTest/Bug8153781.java | 90 +++++++++++++++++++ 15 files changed, 210 insertions(+), 107 deletions(-) create mode 100644 jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java index a425067224c..8e1eaef54e1 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,7 +25,6 @@ import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLString; @@ -815,7 +815,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -960,7 +960,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.startPosition = 0; @@ -1397,7 +1397,7 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged) { @@ -1446,8 +1446,9 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; - entityChanged = load(1, true, true); + entityChanged = load(1, true, false); if (!entityChanged) { // the load change the position to be 1, // need to restore it when entity not changed diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java index 4daa5f0e333..d695936f67d 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,17 +20,17 @@ */ package com.sun.org.apache.xerces.internal.impl; -import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; -import java.io.EOFException; -import java.io.IOException; +import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; - +import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; +import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; - +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; @@ -41,11 +42,9 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.impl.Constants; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; +import java.io.EOFException; +import java.io.IOException; /** * This class is responsible for scanning the declarations found @@ -387,15 +386,25 @@ implements XMLDTDScanner, XMLComponent, XMLEntityHandler { */ @Override public boolean skipDTD(boolean supportDTD) throws IOException { - if (!supportDTD) { - fStringBuffer.clear(); - if (!fEntityScanner.scanData("]", fStringBuffer)) { - fEntityScanner.fCurrentEntity.position--; - } + if (supportDTD) + return false; - return true; + fStringBuffer.clear(); + while (fEntityScanner.scanData("]", fStringBuffer)) { + int c = fEntityScanner.peekChar(); + if (c != -1) { + if (XMLChar.isHighSurrogate(c)) { + scanSurrogates(fStringBuffer); + } + if (isInvalidLiteral(c)) { + reportFatalError("InvalidCharInDTD", + new Object[] { Integer.toHexString(c) }); + fEntityScanner.scanChar(); + } + } } - return false; + fEntityScanner.fCurrentEntity.position--; + return true; } // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index e31e838c8e8..c817111e067 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +19,6 @@ * limitations under the License. */ - package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.XMLBufferListener; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index 7f1bbf10226..235d27ba5d8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; @@ -1106,8 +1106,7 @@ public class XMLDocumentScannerImpl if (!moreToScan) { // end doctype declaration if (!fEntityScanner.skipChar(']')) { - reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET", - null); + reportFatalError("DoctypedeclNotClosed", new Object[]{fDoctypeName}); } fEntityScanner.skipSpaces(); if (!fEntityScanner.skipChar('>')) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index 1c0eca636a8..b7922312371 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,8 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - - import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; import com.sun.org.apache.xerces.internal.impl.io.UCSReader; import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; @@ -44,8 +43,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.ArrayList; import java.util.Locale; -import java.util.Vector; /** * Implements the entity scanner methods. @@ -58,11 +57,10 @@ import java.util.Vector; */ public class XMLEntityScanner implements XMLLocator { - - protected Entity.ScannedEntity fCurrentEntity = null ; + protected Entity.ScannedEntity fCurrentEntity = null; protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE; - protected XMLEntityManager fEntityManager ; + protected XMLEntityManager fEntityManager; /** Security manager. */ protected XMLSecurityManager fSecurityManager = null; @@ -72,8 +70,9 @@ public class XMLEntityScanner implements XMLLocator { /** Debug switching readers for encodings. */ private static final boolean DEBUG_ENCODINGS = false; + /** Listeners which should know when load is being called */ - private Vector listeners = new Vector(); + private ArrayList listeners = new ArrayList<>(); private static final boolean [] VALID_NAMES = new boolean[127]; @@ -140,9 +139,11 @@ public class XMLEntityScanner implements XMLLocator { VALID_NAMES[58]=true; VALID_NAMES[95]=true; } - // SAPJVM: Remember, that the XML version has explicitly been set, + + // Remember, that the XML version has explicitly been set, // so that XMLStreamReader.getVersion() can find that out. - boolean xmlVersionSetExplicitly = false; + protected boolean xmlVersionSetExplicitly = false; + // // Constructors // @@ -257,7 +258,7 @@ public class XMLEntityScanner implements XMLLocator { * @param xmlVersion the XML version of the current entity */ public final void setXMLVersion(String xmlVersion) { - xmlVersionSetExplicitly = true; // SAPJVM + xmlVersionSetExplicitly = true; fCurrentEntity.xmlVersion = xmlVersion; } // setXMLVersion(String) @@ -546,8 +547,7 @@ public class XMLEntityScanner implements XMLLocator { // scan character int c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\n' || - (c == '\r' && isExternal)) { + if (c == '\n' || (c == '\r' && isExternal)) { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { @@ -953,7 +953,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1105,7 +1105,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1256,8 +1256,8 @@ public class XMLEntityScanner implements XMLLocator { *

    * Note: The characters are consumed. *

    - * Note: This assumes that the length of the delimiter - * and that the delimiter contains at least one character. + * Note: This assumes that the delimiter contains at + * least one character. *

    * Note: This method does not guarantee to return * the longest run of character data. This method may return before @@ -1436,7 +1436,7 @@ public class XMLEntityScanner implements XMLLocator { } while (!done); return !done; - } // scanData(String,XMLString) + } // scanData(String, XMLStringBuffer) /** * Skips a character appearing immediately on the input. @@ -1558,7 +1558,7 @@ public class XMLEntityScanner implements XMLLocator { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged){ @@ -1727,8 +1727,7 @@ public class XMLEntityScanner implements XMLLocator { final int length = s.length; //first make sure that required capacity is avaible if(arrangeCapacity(length, false)){ - int beforeSkip = fCurrentEntity.position ; - int afterSkip = fCurrentEntity.position + length ; + int beforeSkip = fCurrentEntity.position; if(DEBUG_SKIP_STRING){ System.out.println("skipString,length = " + new String(s) + "," + length); @@ -2107,8 +2106,9 @@ public class XMLEntityScanner implements XMLLocator { * is being changed. */ public void registerListener(XMLBufferListener listener) { - if(!listeners.contains(listener)) + if (!listeners.contains(listener)) { listeners.add(listener); + } } /** @@ -2116,9 +2116,8 @@ public class XMLEntityScanner implements XMLLocator { * @param loadPos Starting position from which new data is being loaded into scanner buffer. */ public void invokeListeners(int loadPos){ - for(int i=0;i''. + DoctypedeclNotClosed = The document type declaration for root element type \"{0}\" must be closed with '']''. PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index c82bc5b80d0..55c9d3a3c92 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Leerstelle nach "" enden. + DoctypedeclNotClosed = Dokumenttypdeklaration f\u00FCr Root-Elementtyp "{0}" muss mit "]" abgeschlossen werden. PEReferenceWithinMarkup = Parameterentit\u00E4tsreferenz "%{0};" darf nicht in Markup in der internen Teilmenge der DTD vorkommen. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Die Markup-Deklarationen, die in der Dokumenttypdeklaration enthalten sind bzw. auf die von der Dokumenttypdeklaration verwiesen wird, m\u00FCssen ordnungsgem\u00E4\u00DF formatiert sein. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties index 1243b215cec..51491f84075 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Es necesario un espacio en blanco despu\u00E9s de "''. + DoctypedeclNotClosed = La declaraci\u00F3n de tipo de documento para el tipo de elemento ra\u00EDz "{0}" debe cerrar en '']''. PEReferenceWithinMarkup = La referencia de entidad del par\u00E1metro "%{0};" no puede producirse en el marcador en el subconjunto interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Las declaraciones de marcador que se incluyen o a las que apunta la declaraci\u00F3n de tipo de documento deben tener el formato correcto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties index 5a2b76c13b7..2be672257f3 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Un espace est obligatoire apr\u00E8s "''. + DoctypedeclNotClosed = La d\u00E9claration de type de document pour le type d''\u00E9l\u00E9ment racine "{0}" doit se conclure par '']''. PEReferenceWithinMarkup = La r\u00E9f\u00E9rence d''entit\u00E9 de param\u00E8tre "%{0};" ne peut pas survenir dans le balisage du sous-ensemble interne de la DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Les d\u00E9clarations de balisage contenues dans la d\u00E9claration de type de document ou sur lesquelles pointe cette derni\u00E8re doivent avoir un format correct. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties index 1f8ec89276a..aa229f49bf2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = \u00C8 richiesto uno spazio dopo "''. + DoctypedeclNotClosed = La dichiarazione del tipo di documento per il tipo di elemento radice "{0}" deve chiudere con '']''. PEReferenceWithinMarkup = Il riferimento di entit\u00E0 di parametro "%{0};" non pu\u00F2 essere presente nel markup del set secondario interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Le dichiarazioni di markup contenute o indicate dalla dichiarazione del tipo di documento devono avere un formato corretto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java index bdd0750d0fa..c9bbed93511 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java @@ -1,15 +1,16 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. */ + /* - * Copyright 2004,2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,17 +18,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.util; -import java.io.InputStream; -import java.io.Reader; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; +import java.io.InputStream; +import java.io.Reader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** * This class represents an input source for an XML resource diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties index 93da2fdba82..b6e235b5124 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties +++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties @@ -4,5 +4,6 @@ TestNG.dirs = . lib.dirs = /javax/xml/jaxp/libs # Declare module dependency -modules=java.xml/com.sun.org.apache.xerces.internal.jaxp \ +modules=java.xml/com.sun.org.apache.xerces.internal.impl \ + java.xml/com.sun.org.apache.xerces.internal.jaxp \ java.xml/com.sun.org.apache.xml.internal.serialize diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java index c56e7569c3c..188d003621a 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java @@ -28,7 +28,6 @@ import java.io.File; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.events.XMLEvent; import org.testng.Assert; import org.testng.annotations.Test; @@ -74,7 +73,7 @@ public class Bug6668115Test { er.nextTag(); er.nextTag(); - XMLEvent event = er.peek(); + er.peek(); System.out.println(er.getElementText()); er.nextTag(); System.out.println(er.getElementText()); diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java new file mode 100644 index 00000000000..f973b3bf33d --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package stream.XMLEventReaderTest; + +import java.io.StringReader; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; + +/* + * @bug 8153781 + * @summary Test if method skipDTD of class XMLDTDScannerImpl will correctly skip the DTD section, + * even if a call to XMLEntityScanner.scanData for skipping to the closing ']' returns true. + */ +public class Bug8153781 { + public static int DOCTYPE_SECTION_LENGTH = XMLEntityManager.DEFAULT_BUFFER_SIZE * 2; + public static int DOCUMENT_LENGTH = DOCTYPE_SECTION_LENGTH + 4096; + + public String createXMLDocument(int doctypeoffset) { + StringBuilder xmlcontentbuilder = new StringBuilder(DOCUMENT_LENGTH); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append(" \r\n"); + xmlcontentbuilder.append(" ]\r\n"); + xmlcontentbuilder.append(">\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + System.out.println("Document length:" + xmlcontentbuilder.length()); + return xmlcontentbuilder.toString(); + } + + public void runReader(XMLInputFactory factory, int offset) throws XMLStreamException { + StringReader stringReader = new StringReader(createXMLDocument(offset)); + XMLEventReader reader = factory.createXMLEventReader(stringReader); + + while (reader.hasNext()) { + XMLEvent event = reader.nextEvent(); + System.out.println("Event Type: " + event.getEventType()); + } + } + + @Test + public void test() { + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + for (int i = 0; i < 3; i++) { + runReader(factory, i); + } + } catch (XMLStreamException xe) { + xe.printStackTrace(); + Assert.fail(xe.getMessage()); + } + } +} From 4b1ef0a20be4c6444aea5b8f281135cc7a6a5595 Mon Sep 17 00:00:00 2001 From: Frank Yuan Date: Tue, 19 Apr 2016 23:56:52 -0700 Subject: [PATCH 093/113] 8078820: Test deploying a XML parser as a module Reviewed-by: joehw, alanb --- .../jaxp/libs/jdk/testlibrary/Asserts.java | 566 +++++++++++++++++ .../libs/jdk/testlibrary/CompilerUtils.java | 81 +++ .../libs/jdk/testlibrary/JDKToolFinder.java | 111 ++++ .../libs/jdk/testlibrary/JDKToolLauncher.java | 136 ++++ .../libs/jdk/testlibrary/OutputAnalyzer.java | 576 +++++++++++++++++ .../libs/jdk/testlibrary/OutputBuffer.java | 113 ++++ .../jaxp/libs/jdk/testlibrary/Platform.java | 213 +++++++ .../libs/jdk/testlibrary/ProcessTools.java | 579 ++++++++++++++++++ .../xml/jaxp/libs/jdk/testlibrary/README.txt | 1 + .../libs/jdk/testlibrary/StreamPumper.java | 204 ++++++ .../xml/jaxp/libs/jdk/testlibrary/Utils.java | 365 +++++++++++ .../BasicModularXMLParserTest.java | 120 ++++ .../LayerModularXMLParserTest.java | 187 ++++++ .../src/test/module-info.java | 27 + .../src/test/test/XMLFactoryHelper.java | 55 ++ .../ServiceProviderTest/src/unnamed/Main.java | 107 ++++ .../src/xmlprovider1/module-info.java | 34 + .../xp1/DocumentBuilderFactoryImpl.java | 57 ++ .../xp1/SAXParserFactoryImpl.java | 53 ++ .../xmlprovider1/xp1/SchemaFactoryImpl.java | 77 +++ .../xp1/TransformerFactoryImpl.java | 97 +++ .../xmlprovider1/xp1/XMLInputFactoryImpl.java | 166 +++++ .../xp1/XMLOutputFactoryImpl.java | 94 +++ .../xmlprovider1/xp1/XPathFactoryImpl.java | 65 ++ .../src/xmlprovider2/module-info.java | 29 + .../xmlprovider2/xp2/DatatypeFactoryImpl.java | 73 +++ .../xmlprovider2/xp2/XMLEventFactoryImpl.java | 180 ++++++ .../javax/xml/jaxp/module/TEST.properties | 5 + 28 files changed, 4371 insertions(+) create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/TEST.properties diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java new file mode 100644 index 00000000000..594b12e3ede --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.Objects; + +/** + * Asserts that can be used for verifying assumptions in tests. + * + * An assertion will throw a {@link RuntimeException} if the assertion isn't true. + * All the asserts can be imported into a test by using a static import: + * + *

    + * {@code
    + * import static jdk.testlibrary.Asserts.*;
    + * }
    + *
    + * Always provide a message describing the assumption if the line number of the
    + * failing assertion isn't enough to understand why the assumption failed. For
    + * example, if the assertion is in a loop or in a method that is called
    + * multiple times, then the line number won't provide enough context to
    + * understand the failure.
    + * 
    + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Asserts { + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable) + */ + public static > void assertLT(T lhs, T rhs) { + assertLessThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLT(T lhs, T rhs, String msg) { + assertLessThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLessThan(T lhs, T rhs) { + assertLessThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static >void assertLessThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) < 0)) { + msg = Objects.toString(msg, "assertLessThan") + + ": expected that " + Objects.toString(lhs) + + " < " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable) + */ + public static > void assertLTE(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLTE(T lhs, T rhs, String msg) { + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLessThanOrEqual(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertLessThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) <= 0)) { + msg = Objects.toString(msg, "assertLessThanOrEqual") + + ": expected that " + Objects.toString(lhs) + + " <= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object) + */ + public static void assertEQ(Object lhs, Object rhs) { + assertEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEQ(Object lhs, Object rhs, String msg) { + assertEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEquals(Object lhs, Object rhs) { + assertEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertEquals(Object lhs, Object rhs, String msg) { + if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) { + msg = Objects.toString(msg, "assertEquals") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertSame(Object, Object, String) + */ + public static void assertSame(Object lhs, Object rhs) { + assertSame(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is the same as {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertSame(Object lhs, Object rhs, String msg) { + if (lhs != rhs) { + msg = Objects.toString(msg, "assertSame") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable) + */ + public static > void assertGTE(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGTE(T lhs, T rhs, String msg) { + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) >= 0)) { + msg = Objects.toString(msg, "assertGreaterThanOrEqual") + + ": expected " + Objects.toString(lhs) + + " >= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThan(Comparable, Comparable) + */ + public static > void assertGT(T lhs, T rhs) { + assertGreaterThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGT(T lhs, T rhs, String msg) { + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGreaterThan(T lhs, T rhs) { + assertGreaterThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) > 0)) { + msg = Objects.toString(msg, "assertGreaterThan") + + ": expected " + Objects.toString(lhs) + + " > " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object) + */ + public static void assertNE(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNE(Object lhs, Object rhs, String msg) { + assertNotEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertNotEquals(Object, Object, String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNotEquals(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is not equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotEquals(Object lhs, Object rhs, String msg) { + if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) { + msg = Objects.toString(msg, "assertNotEquals") + + ": expected " + Objects.toString(lhs) + + " to not equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertNull(Object, String)} with a default message. + * + * @param o The reference assumed to be null. + * @see #assertNull(Object, String) + */ + public static void assertNull(Object o) { + assertNull(o, null); + } + + /** + * Asserts that {@code o} is null. + * + * @param o The reference assumed to be null. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNull(Object o, String msg) { + assertEquals(o, null, msg); + } + + /** + * Calls {@link #assertNotNull(Object, String)} with a default message. + * + * @param o The reference assumed not to be null, + * @see #assertNotNull(Object, String) + */ + public static void assertNotNull(Object o) { + assertNotNull(o, null); + } + + /** + * Asserts that {@code o} is not null. + * + * @param o The reference assumed not to be null, + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotNull(Object o, String msg) { + assertNotEquals(o, null, msg); + } + + /** + * Calls {@link #assertFalse(boolean, String)} with a default message. + * + * @param value The value assumed to be false. + * @see #assertFalse(boolean, String) + */ + public static void assertFalse(boolean value) { + assertFalse(value, null); + } + + /** + * Asserts that {@code value} is {@code false}. + * + * @param value The value assumed to be false. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertFalse(boolean value, String msg) { + if (value) { + msg = Objects.toString(msg, "assertFalse") + + ": expected false, was true"; + fail(msg); + } + } + + /** + * Calls {@link #assertTrue(boolean, String)} with a default message. + * + * @param value The value assumed to be true. + * @see #assertTrue(boolean, String) + */ + public static void assertTrue(boolean value) { + assertTrue(value, null); + } + + /** + * Asserts that {@code value} is {@code true}. + * + * @param value The value assumed to be true. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertTrue(boolean value, String msg) { + if (!value) { + msg = Objects.toString(msg, "assertTrue") + + ": expected true, was false"; + fail(msg); + } + } + + private static > int compare(T lhs, T rhs, String msg) { + if (lhs == null || rhs == null) { + fail(lhs, rhs, msg + ": values must be non-null:", ","); + } + return lhs.compareTo(rhs); + } + + /** + * Returns a string formatted with a message and expected and actual values. + * @param lhs the actual value + * @param rhs the expected value + * @param message the actual value + * @param relation the asserted relationship between lhs and rhs + * @return a formatted string + */ + public static String format(Object lhs, Object rhs, String message, String relation) { + StringBuilder sb = new StringBuilder(80); + if (message != null) { + sb.append(message); + sb.append(' '); + } + sb.append("<"); + sb.append(Objects.toString(lhs)); + sb.append("> "); + sb.append(Objects.toString(relation, ",")); + sb.append(" <"); + sb.append(Objects.toString(rhs)); + sb.append(">"); + return sb.toString(); + } + + /** + * Fail reports a failure with message fail. + * + * @throws RuntimeException always + */ + public static void fail() { + fail("fail"); + } + + /** + * Fail reports a failure with a message. + * @param message for the failure + * @throws RuntimeException always + */ + public static void fail(String message) { + throw new RuntimeException(message); + } + + /** + * Fail reports a failure with a formatted message. + * + * @param lhs the actual value + * @param rhs the expected value + * @param message to be format before the expected and actual values + * @param relation the asserted relationship between lhs and rhs + * @throws RuntimeException always + */ + public static void fail(Object lhs, Object rhs, String message, String relation) { + throw new RuntimeException(format(lhs, rhs, message, relation)); + } + + /** + * Fail reports a failure with a message and a cause. + * @param message to be format before the expected and actual values + * @param cause the exception that caused this failure + * @throws RuntimeException always + */ + public static void fail(String message, Throwable cause) { + throw new RuntimeException(message, cause); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java new file mode 100644 index 00000000000..afabfd7cc52 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package jdk.testlibrary; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + */ + +public final class CompilerUtils { + private CompilerUtils() { } + + /** + * Compile all the java sources in {@code /**} to + * {@code /**}. The destination directory will be created if + * it doesn't exist. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @return true if the compilation is successful + * + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + */ + public static boolean compile(Path source, Path destination, String ... options) + throws IOException + { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List sources + = Files.find(source, Integer.MAX_VALUE, + (file, attrs) -> (file.toString().endsWith(".java"))) + .collect(Collectors.toList()); + + Files.createDirectories(destination); + jfm.setLocation(StandardLocation.CLASS_PATH, Collections.EMPTY_LIST); + jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, + Arrays.asList(destination)); + + List opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromPaths(sources)); + + return task.call(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java new file mode 100644 index 00000000000..c4815229eb7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java new file mode 100644 index 00000000000..777e8cf5336 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following + * code run {@code jmap -heap} against a process with GC logging turned on for + * the {@code jmap} process: + * + *
    + * {@code
    + * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
    + *                                       .addVMArg("-Xlog:gc*=debug")
    + *                                       .addToolArg("-heap")
    + *                                       .addToolArg(pid);
    + * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
    + * Process p = pb.start();
    + * }
    + * 
    + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class JDKToolLauncher { + private final String executable; + private final List vmArgs = new ArrayList(); + private final List toolArgs = new ArrayList(); + + private JDKToolLauncher(String tool, boolean useCompilerJDK) { + if (useCompilerJDK) { + executable = JDKToolFinder.getJDKTool(tool); + } else { + executable = JDKToolFinder.getTestJDKTool(tool); + } + vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); + } + + /** + * Creates a new JDKToolLauncher for the specified tool. Using tools path + * from the compiler JDK. + * + * @param tool + * The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool, true); + } + + /** + * Creates a new JDKToolLauncher for the specified tool in the Tested JDK. + * + * @param tool + * The name of the tool + * + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher createUsingTestJDK(String tool) { + return new JDKToolLauncher(tool, false); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg + * The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add(arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg + * The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List command = new ArrayList(); + command.add(executable); + // Add -J in front of all vmArgs + for (String arg : vmArgs) { + command.add("-J" + arg); + } + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..839c3228294 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import static jdk.testlibrary.Asserts.*; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class for verifying output and exit value from a {@code Process}. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + * + */ +@Deprecated +public final class OutputAnalyzer { + private final OutputBuffer output; + private final String stdout; + private final String stderr; + private final int exitValue; // useless now. output contains exit value. + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process. + *

    + * OutputAnalyzer should never be instantiated directly - + * use {@linkplain ProcessTools#executeProcess(ProcessBuilder)} instead + * + * @param process + * Process to analyze + * @throws IOException + * If an I/O error occurs. + */ + OutputAnalyzer(Process process) throws IOException { + output = new OutputBuffer(process); + exitValue = -1; + this.stdout = null; + this.stderr = null; + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output. + * + * @param buf + * String buffer to analyze + */ + OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout + * stdout buffer to analyze + * @param stderr + * stderr buffer to analyze + */ + OutputAnalyzer(String stdout, String stderr) { + this.output = null; + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the + * string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer shouldContain(String expectedString) { + if (!getStdout().contains(expectedString) + && !getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stdoutShouldContain(String expectedString) { + if (!getStdout().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stderrShouldContain(String expectedString) { + if (!getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * contain the string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer shouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout: '" + + matcher.group() + "' \n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr: '" + + matcher.group() + "' \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr \n"); + } + return this; + } + + /** + * Get the captured group of the first string matching the pattern. stderr + * is searched before stdout. + * + * @param pattern + * The multi-line pattern to match + * @param group + * The group to capture + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern, int group) { + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. stderr is searched before + * stdout. + * + * @param pattern + * The multi-line pattern to match + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern) { + return firstMatch(pattern, 0); + } + + /** + * Verify the exit value of the process + * + * @param expectedExitValue + * Expected exit value from process + * @throws RuntimeException + * If the exit value from the process did not match the expected + * value + */ + public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Expected to get exit value of [" + + expectedExitValue + "]\n"); + } + return this; + } + + /** + * Report summary that will help to diagnose the problem Currently includes: + * - standard input produced by the process under test - standard output - + * exit code Note: the command line is printed by the ProcessTools + */ + private OutputAnalyzer reportDiagnosticSummary() { + String msg = " stdout: [" + getStdout() + "];\n" + " stderr: [" + getStderr() + + "]\n" + " exitValue = " + getExitValue() + "\n"; + + System.err.println(msg); + return this; + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return getStdout() + getStderr(); + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return output == null ? stdout : output.getStdout(); + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return output == null ? stderr : output.getStderr(); + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return output == null ? exitValue : output.getExitValue(); + } + + + /** + * Print the stdout buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer outputTo(PrintStream out) { + out.println(getStdout()); + return this; + } + + /** + * Print the stderr buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer errorTo(PrintStream out) { + out.println(getStderr()); + return this; + } + + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by system property 'line.separator'. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + List l = new ArrayList<>(); + String[] a = buffer.split(Utils.NEW_LINE); + for (String string : a) { + l.add(string); + } + return l; + } + + /** + * Check if there is a line matching {@code pattern} and return its index + * + * @param pattern Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String pattern) { + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).matches(pattern)) { + return i; + } + } + return -1; + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #stdoutShouldMatchByLine(String, String, String) + */ + public int stdoutShouldMatchByLine(String pattern) { + return stdoutShouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int shouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getOutput(), from, to, pattern); + } + + /** + * Verify that the stdout contents of output buffer matches the + * {@code pattern} line by line. The whole stdout could be matched or + * just a subset of it. + * + * @param from + * The line from where stdout will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where stdout will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int stdoutShouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getStdout(), from, to, pattern); + } + + private int shouldMatchByLine(String buffer, String from, String to, String pattern) { + List lines = asLines(buffer); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + int matchedCount = 0; + for (String line : subList) { + assertTrue(line.matches(pattern), + "The line '" + line + "' does not match pattern '" + pattern + "'"); + matchedCount++; + } + + return matchedCount; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..c8a5d7aab12 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +class OutputBuffer { + private static class OutputBufferException extends RuntimeException { + private static final long serialVersionUID = 8528687792643129571L; + + public OutputBufferException(Throwable cause) { + super(cause); + } + } + + private final Process p; + private final Future outTask; + private final Future errTask; + private final ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + + /** + * Create an OutputBuffer, a class for storing and managing stdout and + * stderr results separately + * + * @param stdout + * stdout result + * @param stderr + * stderr result + */ + OutputBuffer(Process p) { + this.p = p; + StreamPumper outPumper = new StreamPumper(p.getInputStream(), + stdoutBuffer); + StreamPumper errPumper = new StreamPumper(p.getErrorStream(), + stderrBuffer); + + outTask = outPumper.process(); + errTask = errPumper.process(); + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + try { + outTask.get(); + return stdoutBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + try { + errTask.get(); + return stderrBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + public int getExitValue() { + try { + return p.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java new file mode 100644 index 00000000000..523e6e6a074 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; +import java.util.regex.Pattern; +import java.io.RandomAccessFile; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Platform { + private static final String osName = System.getProperty("os.name"); + private static final String dataModel = System.getProperty("sun.arch.data.model"); + private static final String vmVersion = System.getProperty("java.vm.version"); + private static final String jdkDebug = System.getProperty("jdk.debug"); + private static final String osArch = System.getProperty("os.arch"); + private static final String vmName = System.getProperty("java.vm.name"); + private static final String userName = System.getProperty("user.name"); + private static final String compiler = System.getProperty("sun.management.compiler"); + + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } + + public static boolean isGraal() { + return vmName.endsWith(" Graal VM"); + } + + public static boolean isMinimal() { + return vmName.endsWith(" Minimal VM"); + } + + public static boolean isEmbedded() { + return vmName.contains("Embedded"); + } + + public static boolean isTieredSupported() { + return compiler.contains("Tiered Compilers"); + } + + + public static boolean is32bit() { + return dataModel.equals("32"); + } + + public static boolean is64bit() { + return dataModel.equals("64"); + } + + public static boolean isAix() { + return isOs("aix"); + } + + public static boolean isLinux() { + return isOs("linux"); + } + + public static boolean isOSX() { + return isOs("mac"); + } + + public static boolean isSolaris() { + return isOs("sunos"); + } + + public static boolean isWindows() { + return isOs("win"); + } + + private static boolean isOs(String osname) { + return osName.toLowerCase().startsWith(osname.toLowerCase()); + } + + public static String getOsName() { + return osName; + } + + public static boolean isDebugBuild() { + return (jdkDebug.toLowerCase().contains("debug")); + } + + public static String getVMVersion() { + return vmVersion; + } + + // Returns true for sparc and sparcv9. + public static boolean isSparc() { + return isArch("sparc.*"); + } + + public static boolean isARM() { + return isArch("arm.*"); + } + + public static boolean isPPC() { + return isArch("ppc.*"); + } + + public static boolean isX86() { + // On Linux it's 'i386', Windows 'x86' without '_64' suffix. + return isArch("(i386)|(x86(?!_64))"); + } + + public static boolean isX64() { + // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' + return isArch("(amd64)|(x86_64)"); + } + + private static boolean isArch(String archnameRE) { + return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE) + .matcher(osArch) + .matches(); + } + + public static String getOsArch() { + return osArch; + } + + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. + */ + public static boolean shouldSAAttach() + throws IOException { + + if (isAix()) { + return false; // SA not implemented. + } else if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". + */ + public static boolean canPtraceAttachLinux() + throws IOException { + + // SELinux deny_ptrace: + try(RandomAccessFile file = new RandomAccessFile("/sys/fs/selinux/booleans/deny_ptrace", "r")) { + if (file.readByte() != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // YAMA enhanced security ptrace_scope: + // 0 - a process can PTRACE_ATTACH to any other process running under the same uid + // 1 - restricted ptrace: a process must be a children of the inferior or user is root + // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root + // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH + + try(RandomAccessFile file = new RandomAccessFile("/proc/sys/kernel/yama/ptrace_scope", "r")) { + byte yama_scope = file.readByte(); + if (yama_scope == '3') { + return false; + } + + if (!userName.equals("root") && yama_scope != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + public static boolean canAttachOSX() { + return userName.equals("root"); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..35cffc1c994 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; +import java.util.function.Consumer; +import java.util.stream.Collectors; + + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class ProcessTools { + private static final class LineForwarder extends StreamPumper.LinePump { + private final PrintStream ps; + private final String prefix; + LineForwarder(String prefix, PrintStream os) { + this.ps = os; + this.prefix = prefix; + } + @Override + protected void processLine(String line) { + ps.println("[" + prefix + "] " + line); + } + } + + private ProcessTools() { + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + * @param name The process name + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder) + throws IOException { + return startProcess(name, processBuilder, (Consumer)null); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    It is possible to monitor the in-streams via the provided {@code consumer} + * @param name The process name + * @param consumer {@linkplain Consumer} instance to process the in-streams + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + Consumer consumer) + throws IOException { + try { + return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS); + } catch (InterruptedException | TimeoutException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT + *

    + * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, null, linePredicate, timeout, unit); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT and monitor the + * in-streams via the provided {@linkplain Consumer} + *

    + * @param name The process name + * @param processBuilder The process builder + * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Consumer lineConsumer, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" "))); + Process p = processBuilder.start(); + StreamPumper stdout = new StreamPumper(p.getInputStream()); + StreamPumper stderr = new StreamPumper(p.getErrorStream()); + + stdout.addPump(new LineForwarder(name, System.out)); + stderr.addPump(new LineForwarder(name, System.err)); + if (lineConsumer != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + lineConsumer.accept(line); + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } + + + CountDownLatch latch = new CountDownLatch(1); + if (linePredicate != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + if (latch.getCount() > 0 && linePredicate.test(line)) { + latch.countDown(); + } + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } else { + latch.countDown(); + } + final Future stdoutTask = stdout.process(); + final Future stderrTask = stderr.process(); + + try { + if (timeout > -1) { + if (timeout == 0) { + latch.await(); + } else { + if (!latch.await(Utils.adjustTimeout(timeout), unit)) { + throw new TimeoutException(); + } + } + } + } catch (TimeoutException | InterruptedException e) { + System.err.println("Failed to start a process (thread dump follows)"); + for(Map.Entry s : Thread.getAllStackTraces().entrySet()) { + printStack(s.getKey(), s.getValue()); + } + + if (p.isAlive()) { + p.destroyForcibly(); + } + + stdoutTask.cancel(true); + stderrTask.cancel(true); + throw e; + } + + return new ProcessImpl(p, stdoutTask, stderrTask); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT. The warm-up will + * wait indefinitely. + *

    + * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static long getProcessId() { + return ProcessHandle.current().getPid(); + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are + * none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) + throws Exception { + return createJavaProcessBuilder(false, command); + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts + * to the java arguments. + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + + if (addTestVmAndJavaOptions) { + // -cp is needed to make sure the same classpath is used whether the test is + // run in AgentVM mode or OtherVM mode. It was added to the hotspot version + // of this API as part of 8077608. However, for the jdk version it is only + // added when addTestVmAndJavaOptions is true in order to minimize + // disruption to existing JDK tests, which have yet to be tested with -cp + // being added. At some point -cp should always be added to be consistent + // with what the hotspot version does. + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + Collections.addAll(args, Utils.getTestJavaOpts()); + } + + Collections.addAll(args, command); + + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String cmd : args) + cmdLine.append(cmd).append(' '); + System.out.println("Command line: [" + cmdLine.toString() + "]"); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + } + + private static void printStack(Thread t, StackTraceElement[] stack) { + System.out.println("\t" + t + + " stack: (length = " + stack.length + ")"); + if (t != null) { + for (StackTraceElement stack1 : stack) { + System.out.println("\t" + stack1); + } + System.out.println(); + } + } + + /** + * Executes a test java process, waits for it to finish and returns the process output. + * The default options from jtreg, test.vm.opts and test.java.opts, are added. + * The java from the test.jdk is used to execute the command. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * + * The java process will have exited before this method returns. + * + * @param cmds User specifed arguments. + * @return The output from the process. + */ + public static OutputAnalyzer executeTestJava(String... options) throws Exception { + ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(options)); + return executeProcess(pb); + } + + /** + * @deprecated Use executeTestJava instead + */ + public static OutputAnalyzer executeTestJvm(String... options) throws Exception { + return executeTestJava(options); + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) + throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = pb.start(); + if (input != null) { + try (OutputStream os = p.getOutputStream(); + PrintStream ps = new PrintStream(os)) { + ps.print(input); + ps.flush(); + } + } + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The output from the process. + */ + public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + return executeProcess(new ProcessBuilder(cmds)); + } + + /** + * Used to log command line, stdout, stderr and exit code from an executed process. + * @param pb The executed process. + * @param output The output from the process. + */ + public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) { + String stderr = output == null ? "null" : output.getStderr(); + String stdout = output == null ? "null" : output.getStdout(); + String exitValue = output == null ? "null": Integer.toString(output.getExitValue()); + StringBuilder logMsg = new StringBuilder(); + final String nl = System.getProperty("line.separator"); + logMsg.append("--- ProcessLog ---" + nl); + logMsg.append("cmd: " + getCommandLine(pb) + nl); + logMsg.append("exitvalue: " + exitValue + nl); + logMsg.append("stderr: " + stderr + nl); + logMsg.append("stdout: " + stdout + nl); + + return logMsg.toString(); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + if (pb == null) { + return "null"; + } + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString().trim(); + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout, and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(String... cmds) + throws Throwable { + String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout and returns the process output. + * + * The process will have exited before this method returns. + * + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(ProcessBuilder pb) + throws Throwable { + String cmdLine = pb.command().stream().collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + private static class ProcessImpl extends Process { + + private final Process p; + private final Future stdoutTask; + private final Future stderrTask; + + public ProcessImpl(Process p, Future stdoutTask, Future stderrTask) { + this.p = p; + this.stdoutTask = stdoutTask; + this.stderrTask = stderrTask; + } + + @Override + public OutputStream getOutputStream() { + return p.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return p.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return p.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + int rslt = p.waitFor(); + waitForStreams(); + return rslt; + } + + @Override + public int exitValue() { + return p.exitValue(); + } + + @Override + public void destroy() { + p.destroy(); + } + + @Override + public long getPid() { + return p.getPid(); + } + + @Override + public boolean isAlive() { + return p.isAlive(); + } + + @Override + public Process destroyForcibly() { + return p.destroyForcibly(); + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + boolean rslt = p.waitFor(timeout, unit); + if (rslt) { + waitForStreams(); + } + return rslt; + } + + private void waitForStreams() throws InterruptedException { + try { + stdoutTask.get(); + } catch (ExecutionException e) { + } + try { + stderrTask.get(); + } catch (ExecutionException e) { + } + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt new file mode 100644 index 00000000000..c4fd572cd04 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt @@ -0,0 +1 @@ +These files are copies of the corresponding files in test/lib/testlibrary/ from jdk repo. diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..2f3c205db3c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + /** + * Pump will be called by the StreamPumper to process the incoming data + */ + abstract public static class Pump { + abstract void register(StreamPumper d); + } + + /** + * OutputStream -> Pump adapter + */ + final public static class StreamPump extends Pump { + private final OutputStream out; + public StreamPump(OutputStream out) { + this.out = out; + } + + @Override + void register(StreamPumper sp) { + sp.addOutputStream(out); + } + } + + /** + * Used to process the incoming data line-by-line + */ + abstract public static class LinePump extends Pump { + @Override + final void register(StreamPumper sp) { + sp.addLineProcessor(this); + } + + abstract protected void processLine(String line); + } + + private final InputStream in; + private final Set outStreams = new HashSet<>(); + private final Set linePumps = new HashSet<>(); + + private final AtomicBoolean processing = new AtomicBoolean(false); + private final FutureTask processingTask = new FutureTask<>(this, null); + + public StreamPumper(InputStream in) { + this.in = in; + } + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in + * The stream to read from. + * @param out + * The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this(in); + this.addOutputStream(out); + } + + /** + * Implements Thread.run(). Continuously read from {@code in} and write to + * {@code out} until {@code in} has reached end of stream. Abort on + * interruption. Abort on IOExceptions. + */ + @Override + public void run() { + try (BufferedInputStream is = new BufferedInputStream(in)) { + ByteArrayOutputStream lineBos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + int linelen = 0; + + while ((len = is.read(buf)) > 0 && !Thread.interrupted()) { + for(OutputStream out : outStreams) { + out.write(buf, 0, len); + } + if (!linePumps.isEmpty()) { + int i = 0; + int lastcrlf = -1; + while (i < len) { + if (buf[i] == '\n' || buf[i] == '\r') { + int bufLinelen = i - lastcrlf - 1; + if (bufLinelen > 0) { + lineBos.write(buf, lastcrlf + 1, bufLinelen); + } + linelen += bufLinelen; + + if (linelen > 0) { + lineBos.flush(); + final String line = lineBos.toString(); + linePumps.stream().forEach((lp) -> { + lp.processLine(line); + }); + lineBos.reset(); + linelen = 0; + } + lastcrlf = i; + } + + i++; + } + if (lastcrlf == -1) { + lineBos.write(buf, 0, len); + linelen += len; + } else if (lastcrlf < len - 1) { + lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1); + linelen += len - lastcrlf - 1; + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + for(OutputStream out : outStreams) { + try { + out.flush(); + } catch (IOException e) {} + } + try { + in.close(); + } catch (IOException e) {} + } + } + + final void addOutputStream(OutputStream out) { + outStreams.add(out); + } + + final void addLineProcessor(LinePump lp) { + linePumps.add(lp); + } + + final public StreamPumper addPump(Pump ... pump) { + if (processing.get()) { + throw new IllegalStateException("Can not modify pumper while " + + "processing is in progress"); + } + for(Pump p : pump) { + p.register(this); + } + return this; + } + + final public Future process() { + if (!processing.compareAndSet(false, true)) { + throw new IllegalStateException("Can not re-run the processing"); + } + Thread t = new Thread(new Runnable() { + @Override + public void run() { + processingTask.run(); + } + }); + t.setDaemon(true); + t.start(); + + return processingTask; + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java new file mode 100644 index 00000000000..c76339107c8 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import static jdk.testlibrary.Asserts.assertTrue; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import java.util.function.Function; + +/** + * Common library for various test helper functions. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class Utils { + + /** + * Returns the sequence used by operating system to separate lines. + */ + public static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Returns the value of 'test.vm.opts'system property. + */ + public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim(); + + /** + * Returns the value of 'test.java.opts'system property. + */ + public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + + /** + * Returns the value of 'test.timeout.factor' system property + * converted to {@code double}. + */ + public static final double TIMEOUT_FACTOR; + static { + String toFactor = System.getProperty("test.timeout.factor", "1.0"); + TIMEOUT_FACTOR = Double.parseDouble(toFactor); + } + + /** + * Returns the value of JTREG default test timeout in milliseconds + * converted to {@code long}. + */ + public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + + private Utils() { + // Private constructor to prevent class instantiation + } + + /** + * Returns the list of VM options. + * + * @return List of VM options + */ + public static List getVmOptions() { + return Arrays.asList(safeSplitString(VM_OPTIONS)); + } + + /** + * Returns the list of VM options with -J prefix. + * + * @return The list of VM options with -J prefix + */ + public static List getForwardVmOptions() { + String[] opts = safeSplitString(VM_OPTIONS); + for (int i = 0; i < opts.length; i++) { + opts[i] = "-J" + opts[i]; + } + return Arrays.asList(opts); + } + + /** + * Returns the default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @return An array of options, or an empty array if no opptions. + */ + public static String[] getTestJavaOpts() { + List opts = new ArrayList(); + Collections.addAll(opts, safeSplitString(VM_OPTIONS)); + Collections.addAll(opts, safeSplitString(JAVA_OPTIONS)); + return opts.toArray(new String[0]); + } + + /** + * Combines given arguments with default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts + * @return The combination of JTReg test java options and user args. + */ + public static String[] addTestJavaOpts(String... userArgs) { + List opts = new ArrayList(); + Collections.addAll(opts, getTestJavaOpts()); + Collections.addAll(opts, userArgs); + return opts.toArray(new String[0]); + } + + /** + * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". + * Removes any options matching: -XX:(+/-)Use*GC + * Used when a test need to set its own GC version. Then any + * GC specified by the framework must first be removed. + * @return A copy of given opts with all GC options removed. + */ + private static final Pattern useGcPattern = Pattern.compile( + "(?:\\-XX\\:[\\+\\-]Use.+GC)" + + "|(?:\\-Xconcgc)"); + public static List removeGcOpts(List opts) { + List optsWithoutGC = new ArrayList(); + for (String opt : opts) { + if (useGcPattern.matcher(opt).matches()) { + System.out.println("removeGcOpts: removed " + opt); + } else { + optsWithoutGC.add(opt); + } + } + return optsWithoutGC; + } + + /** + * Splits a string by white space. + * Works like String.split(), but returns an empty array + * if the string is null or empty. + */ + private static String[] safeSplitString(String s) { + if (s == null || s.trim().isEmpty()) { + return new String[] {}; + } + return s.trim().split("\\s+"); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString(); + } + + /** + * Returns the free port on the local host. + * The function will spin until a valid port number is found. + * + * @return The port number + * @throws InterruptedException if any thread has interrupted the current thread + * @throws IOException if an I/O error occurs when opening the socket + */ + public static int getFreePort() throws InterruptedException, IOException { + int port = -1; + + while (port <= 0) { + Thread.sleep(100); + + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(0); + port = serverSocket.getLocalPort(); + } finally { + serverSocket.close(); + } + } + + return port; + } + + /** + * Returns the name of the local host. + * + * @return The host name + * @throws UnknownHostException if IP address of a host could not be determined + */ + public static String getHostname() throws UnknownHostException { + InetAddress inetAddress = InetAddress.getLocalHost(); + String hostName = inetAddress.getHostName(); + + assertTrue((hostName != null && !hostName.isEmpty()), + "Cannot get hostname"); + + return hostName; + } + + /** + * Uses "jcmd -l" to search for a jvm pid. This function will wait + * forever (until jtreg timeout) for the pid to be found. + * @param key Regular expression to search for + * @return The found pid. + */ + public static int waitForJvmPid(String key) throws Throwable { + final long iterationSleepMillis = 250; + System.out.println("waitForJvmPid: Waiting for key '" + key + "'"); + System.out.flush(); + while (true) { + int pid = tryFindJvmPid(key); + if (pid >= 0) { + return pid; + } + Thread.sleep(iterationSleepMillis); + } + } + + /** + * Searches for a jvm pid in the output from "jcmd -l". + * + * Example output from jcmd is: + * 12498 sun.tools.jcmd.JCmd -l + * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar + * + * @param key A regular expression to search for. + * @return The found pid, or -1 if Enot found. + * @throws Exception If multiple matching jvms are found. + */ + public static int tryFindJvmPid(String key) throws Throwable { + OutputAnalyzer output = null; + try { + JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd"); + jcmdLauncher.addToolArg("-l"); + output = ProcessTools.executeProcess(jcmdLauncher.getCommand()); + output.shouldHaveExitValue(0); + + // Search for a line starting with numbers (pid), follwed by the key. + Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n"); + Matcher matcher = pattern.matcher(output.getStdout()); + + int pid = -1; + if (matcher.find()) { + pid = Integer.parseInt(matcher.group(1)); + System.out.println("findJvmPid.pid: " + pid); + if (matcher.find()) { + throw new Exception("Found multiple JVM pids for key: " + key); + } + } + return pid; + } catch (Throwable t) { + System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t)); + throw t; + } + } + + /** + * Adjusts the provided timeout value for the TIMEOUT_FACTOR + * @param tOut the timeout value to be adjusted + * @return The timeout value adjusted for the value of "test.timeout.factor" + * system property + */ + public static long adjustTimeout(long tOut) { + return Math.round(tOut * Utils.TIMEOUT_FACTOR); + } + + /** + * Wait for condition to be true + * + * @param condition, a condition to wait for + */ + public static final void waitForCondition(BooleanSupplier condition) { + waitForCondition(condition, -1L, 100L); + } + + /** + * Wait until timeout for condition to be true + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true + * specifying -1 will wait forever + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout) { + return waitForCondition(condition, timeout, 100L); + } + + /** + * Wait until timeout for condition to be true for specified time + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true, + * specifying -1 will wait forever + * @param sleepTime a time to sleep value in milliseconds + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout, long sleepTime) { + long startTime = System.currentTimeMillis(); + while (!(condition.getAsBoolean() || (timeout != -1L + && ((System.currentTimeMillis() - startTime) > timeout)))) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } + return condition.getAsBoolean(); + } + + /** + * Interface same as java.lang.Runnable but with + * method {@code run()} able to throw any Throwable. + */ + public static interface ThrowingRunnable { + void run() throws Throwable; + } + + /** + * Filters out an exception that may be thrown by the given + * test according to the given filter. + * + * @param test - method that is invoked and checked for exception. + * @param filter - function that checks if the thrown exception matches + * criteria given in the filter's implementation. + * @return - exception that matches the filter if it has been thrown or + * {@code null} otherwise. + * @throws Throwable - if test has thrown an exception that does not + * match the filter. + */ + public static Throwable filterException(ThrowingRunnable test, + Function filter) throws Throwable { + try { + test.run(); + } catch (Throwable t) { + if (filter.apply(t)) { + return t; + } else { + throw t; + } + } + return null; + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java new file mode 100644 index 00000000000..c3403f9d1d0 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static jdk.testlibrary.ProcessTools.executeTestJava; +import jdk.testlibrary.CompilerUtils; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng BasicModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib can instantiate the following interfaces + * with customized provider module on boot layer + * + * javax.xml.datatype.DatatypeFactory + * javax.xml.parsers.DocumentBuilderFactory + * javax.xml.parsers.SAXParserFactory + * javax.xml.stream.XMLEventFactory + * javax.xml.stream.XMLInputFactory + * javax.xml.stream.XMLOutputFactory + * javax.xml.transform.TransformerFactory + * javax.xml.validation.SchemaFactory + * javax.xml.xpath.XPathFactory + */ + +@Test +public class BasicModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + private static final Path CLASSES_DIR = Paths.get("classes"); + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("unnamed"), CLASSES_DIR)); + } + + /* + * test the default JAXP implementation + */ + public void testDefault() throws Exception { + int exitValue + = executeTestJava("-cp", CLASSES_DIR.toString(), + "Main") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading one provider module + */ + public void testWithOneProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading both provider modules + */ + public void testWithTwoProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString() + File.pathSeparator + MOD_DIR2.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1", "xmlprovider2") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java new file mode 100644 index 00000000000..45f24001278 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.module.ModuleFinder.empty; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.lang.ClassLoader; +import java.lang.String; +import java.lang.System; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.reflect.Layer; +import java.lang.reflect.Method; +import java.lang.reflect.Module; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import jdk.testlibrary.CompilerUtils; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng LayerModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib works with layer and TCCL + */ + +@Test +public class LayerModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + + /* + * services provided by provider1 + */ + private static final String[] services1 = { "javax.xml.parsers.DocumentBuilderFactory", + "javax.xml.parsers.SAXParserFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + + /* + * services provided by provider2 + */ + private static final String[] services2 = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.stream.XMLEventFactory" }; + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR1.resolve("test"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR2.resolve("test"))); + } + + /* + * layer 1 is created on top of boot layer, layer1 includes module provider1. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the other services are loaded from boot layer + */ + public void testOneLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + ClassLoader cl1 = layer1.findLoader("test"); + + Method m = cl1.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, Layer.boot()); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1 and provider2. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayerWithDuplicate() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1, MOD_DIR2); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java new file mode 100644 index 00000000000..9a1caa4e1f9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module test { + requires java.xml; + exports test; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java new file mode 100644 index 00000000000..6dfaec5cedf --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.Class; +import java.lang.String; +import java.lang.System; +import java.util.Iterator; +import java.util.ServiceLoader; + +public class XMLFactoryHelper { + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + public static Object instantiateXMLService(String serviceName) throws Exception { + ClassLoader backup = Thread.currentThread().getContextClassLoader(); + try { + // set thread context class loader to module class loader + Thread.currentThread().setContextClassLoader(XMLFactoryHelper.class.getClassLoader()); + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } finally { + Thread.currentThread().setContextClassLoader(backup); + } + + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java new file mode 100644 index 00000000000..cb0a37e916b --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.reflect.Layer; +import java.lang.reflect.Module; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +public class Main { + /* + * @param args, the names of provider modules, which have been loaded + */ + public static void main(String[] args) throws Exception { + Module xml = Layer.boot().findModule("java.xml").get(); + + Set allServices = new HashSet<>(Arrays.asList(expectedAllServices)); + if (!allServices.equals(xml.getDescriptor().uses())) + throw new AssertionError("Expect xml module uses: " + allServices + " But actually uses: " + + xml.getDescriptor().uses()); + + long violationCount = Stream.of(args) + .map(xmlProviderName -> Layer.boot().findModule(xmlProviderName).get()) + .mapToLong( + // services provided by the implementation in provider module + provider -> provider.getDescriptor().provides().keySet().stream() + .filter(serviceName -> { + allServices.remove(serviceName); // remove service provided by + // customized module from allServices + return !belongToModule(serviceName, instantiateXMLService(serviceName), provider); + }).count()) + .sum(); + + // the remaining services should be provided by the default implementation + violationCount += allServices.stream() + .filter(serviceName -> !belongToModule(serviceName, instantiateXMLService(serviceName), xml)) + .count(); + + if (violationCount > 0) + throw new AssertionError(violationCount + " services are not provided by expected module"); + } + + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + private static Object instantiateXMLService(String serviceName) { + try { + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } catch (Exception e) { + e.printStackTrace(System.err); + throw new RuntimeException(e); + } + } + + /* + * verify which module provides the xml factory + */ + private static boolean belongToModule(String factoryName, Object factory, Module expected) { + Module actual = factory.getClass().getModule(); + if (!actual.equals(expected)) { + System.err.println("Expect " + factoryName + " is provided by " + expected + + ", but actual implementation " + factory.getClass() + " is provided by " + actual); + return false; + } else { + System.out.println(factory.getClass() + " is provided by " + expected); + return true; + } + } + + /* + * This list equals the declarations in java.xml module-info.java + */ + private static final String[] expectedAllServices = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.parsers.DocumentBuilderFactory", "javax.xml.parsers.SAXParserFactory", + "javax.xml.stream.XMLEventFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java new file mode 100644 index 00000000000..5a5b1b01447 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module xmlprovider1 { + requires java.xml; + + provides javax.xml.parsers.DocumentBuilderFactory with xp1.DocumentBuilderFactoryImpl; + provides javax.xml.parsers.SAXParserFactory with xp1.SAXParserFactoryImpl; + provides javax.xml.stream.XMLInputFactory with xp1.XMLInputFactoryImpl; + provides javax.xml.stream.XMLOutputFactory with xp1.XMLOutputFactoryImpl; + provides javax.xml.transform.TransformerFactory with xp1.TransformerFactoryImpl; + provides javax.xml.validation.SchemaFactory with xp1.SchemaFactoryImpl; + provides javax.xml.xpath.XPathFactory with xp1.XPathFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java new file mode 100644 index 00000000000..7e302b9630c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { + + @Override + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + return null; + } + + @Override + public void setAttribute(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java new file mode 100644 index 00000000000..5d4ce0602f3 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +public class SAXParserFactoryImpl extends SAXParserFactory { + + @Override + public SAXParser newSAXParser() throws ParserConfigurationException, SAXException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException, + SAXNotRecognizedException, SAXNotSupportedException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java new file mode 100644 index 00000000000..ca0cb3be8c7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; + +public class SchemaFactoryImpl extends SchemaFactory { + + @Override + public boolean isSchemaLanguageSupported(String schemaLanguage) { + // must be true, otherwise JAXP library will deny this impl + if (schemaLanguage.equals(W3C_XML_SCHEMA_NS_URI)) + return true; + else + return false; + } + + @Override + public void setErrorHandler(ErrorHandler errorHandler) { + + } + + @Override + public ErrorHandler getErrorHandler() { + return null; + } + + @Override + public void setResourceResolver(LSResourceResolver resourceResolver) { + + } + + @Override + public LSResourceResolver getResourceResolver() { + return null; + } + + @Override + public Schema newSchema(Source[] schemas) throws SAXException { + return null; + } + + @Override + public Schema newSchema() throws SAXException { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java new file mode 100644 index 00000000000..0feabb6b21f --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; + +public class TransformerFactoryImpl extends TransformerFactory { + + @Override + public Transformer newTransformer(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Transformer newTransformer() throws TransformerConfigurationException { + return null; + } + + @Override + public Templates newTemplates(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Source getAssociatedStylesheet(Source source, String media, String title, String charset) + throws TransformerConfigurationException { + return null; + } + + @Override + public void setURIResolver(URIResolver resolver) { + + } + + @Override + public URIResolver getURIResolver() { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws TransformerConfigurationException { + + } + + @Override + public boolean getFeature(String name) { + return false; + } + + @Override + public void setAttribute(String name, Object value) { + + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public void setErrorListener(ErrorListener listener) { + + } + + @Override + public ErrorListener getErrorListener() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java new file mode 100644 index 00000000000..de4f6cbe075 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import java.io.InputStream; +import java.io.Reader; + +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; + +public class XMLInputFactoryImpl extends XMLInputFactory { + + @Override + public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, InputStream stream) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream, String encoding) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLResolver getXMLResolver() { + return null; + } + + @Override + public void setXMLResolver(XMLResolver resolver) { + + } + + @Override + public XMLReporter getXMLReporter() { + return null; + } + + @Override + public void setXMLReporter(XMLReporter reporter) { + + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + + @Override + public void setEventAllocator(XMLEventAllocator allocator) { + + } + + @Override + public XMLEventAllocator getEventAllocator() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java new file mode 100644 index 00000000000..7042ca1af60 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; + +public class XMLOutputFactoryImpl extends XMLOutputFactory { + + @Override + public XMLStreamWriter createXMLStreamWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java new file mode 100644 index 00000000000..bf5aa7aa20e --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathVariableResolver; + +public class XPathFactoryImpl extends XPathFactory { + + @Override + public boolean isObjectModelSupported(String objectModel) { + // must be true, otherwise JAXP library will deny this impl + return true; + } + + @Override + public void setFeature(String name, boolean value) throws XPathFactoryConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws XPathFactoryConfigurationException { + return false; + } + + @Override + public void setXPathVariableResolver(XPathVariableResolver resolver) { + + } + + @Override + public void setXPathFunctionResolver(XPathFunctionResolver resolver) { + + } + + @Override + public XPath newXPath() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java new file mode 100644 index 00000000000..d55645e58e9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module xmlprovider2 { + requires java.xml; + + provides javax.xml.datatype.DatatypeFactory with xp2.DatatypeFactoryImpl; + provides javax.xml.stream.XMLEventFactory with xp2.XMLEventFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java new file mode 100644 index 00000000000..e4a38886dcc --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp2; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; + +public class DatatypeFactoryImpl extends DatatypeFactory { + + @Override + public Duration newDuration(String lexicalRepresentation) { + return null; + } + + @Override + public Duration newDuration(long durationInMilliSeconds) { + return null; + } + + @Override + public Duration newDuration(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, + BigInteger hours, BigInteger minutes, BigDecimal seconds) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar() { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int month, int day, int hour, + int minute, int second, BigDecimal fractionalSecond, int timezone) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java new file mode 100644 index 00000000000..e4e89c8383b --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp2; + +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.Comment; +import javax.xml.stream.events.DTD; +import javax.xml.stream.events.EndDocument; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.EntityDeclaration; +import javax.xml.stream.events.EntityReference; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.ProcessingInstruction; +import javax.xml.stream.events.StartDocument; +import javax.xml.stream.events.StartElement; + +public class XMLEventFactoryImpl extends XMLEventFactory { + + @Override + public void setLocation(Location location) { + + } + + @Override + public Attribute createAttribute(String prefix, String namespaceURI, String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(QName name, String value) { + return null; + } + + @Override + public Namespace createNamespace(String namespaceURI) { + return null; + } + + @Override + public Namespace createNamespace(String prefix, String namespaceUri) { + return null; + } + + @Override + public StartElement createStartElement(QName name, Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces, NamespaceContext context) { + return null; + } + + @Override + public EndElement createEndElement(QName name, Iterator namespaces) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName, + Iterator namespaces) { + return null; + } + + @Override + public Characters createCharacters(String content) { + return null; + } + + @Override + public Characters createCData(String content) { + return null; + } + + @Override + public Characters createSpace(String content) { + return null; + } + + @Override + public Characters createIgnorableSpace(String content) { + return null; + } + + @Override + public StartDocument createStartDocument() { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version, boolean standalone) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding) { + return null; + } + + @Override + public EndDocument createEndDocument() { + return null; + } + + @Override + public EntityReference createEntityReference(String name, EntityDeclaration declaration) { + return null; + } + + @Override + public Comment createComment(String text) { + return null; + } + + @Override + public ProcessingInstruction createProcessingInstruction(String target, String data) { + return null; + } + + @Override + public DTD createDTD(String dtd) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/TEST.properties b/jaxp/test/javax/xml/jaxp/module/TEST.properties new file mode 100644 index 00000000000..85a3ae5f5c7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/TEST.properties @@ -0,0 +1,5 @@ +# Tests that must run in othervm mode +othervm.dirs= . + +# Declare module dependency +modules=java.xml From 1d0549f73ee2a3ea57234c3da05507b8ef22f4b5 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:03 -0700 Subject: [PATCH 094/113] Added tag jdk-9+115 for changeset 4fbd14764fa7 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index e13ddc6f1e0..06edc4a1f53 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -357,3 +357,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 03543a758cd5890f2266e4b9678378a925dde22a jdk-9+112 55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113 1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114 +09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115 From 9fe8b397dd0cbb96e395e8e5a65115ce4a0bf27d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:05 -0700 Subject: [PATCH 095/113] Added tag jdk-9+115 for changeset 5daa5fbad3ce --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index df49fd73654..dd25acb220b 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -357,3 +357,4 @@ b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 780d0620add32bf545471cf65038c9ac6d9c036d jdk-9+112 cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114 +7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115 From 4fff4771e0f3d61201adaba003ac602ba3d66fd6 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:06 -0700 Subject: [PATCH 096/113] Added tag jdk-9+115 for changeset a936b4e01afb --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 472e5185290..11405727ce0 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -517,3 +517,4 @@ c558850fac5750d8ca98a45180121980f57cdd28 jdk-9+111 76582e8dc9e6374e4f99ab797c8d364b6e9449b4 jdk-9+112 c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 +88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115 From 2c681d330ed0750bf357c8ba6afae5accb279f4d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:09 -0700 Subject: [PATCH 097/113] Added tag jdk-9+115 for changeset 04a4a89d81b9 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 99d74713f24..07b1b9985f7 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -357,3 +357,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 36326537f929d20cc5885b93939f90c0efcc4681 jdk-9+112 28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113 147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114 +1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115 From 6e60b5bc3ef83efdc0143436c3131573ea922ca6 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:10 -0700 Subject: [PATCH 098/113] Added tag jdk-9+115 for changeset c0f1d63d6486 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index c0e2ef494a3..7781746dc33 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -360,3 +360,4 @@ fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 21274e7937bae291658d68143aca0e3ee9296db0 jdk-9+112 e980062475c10d21137051045bf95ee229db9b27 jdk-9+113 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 +4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115 From ae0df303d1080640613cfb775148828aff5b03dc Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:17 -0700 Subject: [PATCH 099/113] Added tag jdk-9+115 for changeset e9c85d2b1fcc --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 5d1fa7fb250..78e30d77611 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -348,3 +348,4 @@ cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 c261f8440c5578b34596e6b0419a81aec431a884 jdk-9+112 a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113 ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114 +295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115 From 2ee49b78fe6ac31d4fb992adaad702333d85c2a9 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Fri, 22 Apr 2016 10:46:08 +0200 Subject: [PATCH 100/113] 8154867: PPC64: Better byte behavior Reviewed-by: goetz --- .../src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp | 5 +- hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp | 40 +++++++++++++ hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp | 2 + .../vm/templateInterpreterGenerator_ppc.cpp | 12 +++- .../src/cpu/ppc/vm/templateTable_ppc_64.cpp | 60 +++++++++++++++++-- 5 files changed, 111 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index cba04106f8c..0d1cb4711bd 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -360,7 +360,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -407,7 +407,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark. post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 9c7128da0b4..cedc1e08c1c 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -169,6 +169,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state, Register Rsc case ltos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: lwz(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); @@ -294,6 +295,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -309,6 +311,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -749,6 +752,43 @@ void InterpreterMacroAssembler::merge_frames(Register Rsender_sp, Register retur stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP } +void InterpreterMacroAssembler::narrow(Register result) { + Register ret_type = R11_scratch1; + ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); + lbz(ret_type, in_bytes(ConstMethod::result_type_offset()), R11_scratch1); + + Label notBool, notByte, notChar, done; + + // common case first + cmpwi(CCR0, ret_type, T_INT); + beq(CCR0, done); + + cmpwi(CCR0, ret_type, T_BOOLEAN); + bne(CCR0, notBool); + andi(result, result, 0x1); + b(done); + + bind(notBool); + cmpwi(CCR0, ret_type, T_BYTE); + bne(CCR0, notByte); + extsb(result, result); + b(done); + + bind(notByte); + cmpwi(CCR0, ret_type, T_CHAR); + bne(CCR0, notChar); + andi(result, result, 0xffff); + b(done); + + bind(notChar); + // cmpwi(CCR0, ret_type, T_SHORT); // all that's left + // bne(CCR0, done); + extsh(result, result); + + // Nothing to do for T_INT + bind(done); +} + // Remove activation. // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp index 8a75af011bd..05bd3aa0bdd 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -140,6 +140,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cpool_and_tags(Register Rcpool, Register Rtags); void is_a(Label& L); + void narrow(Register result); + // Java Call Helpers void call_from_interpreter(Register Rtarget_method, Register Rret_addr, Register Rscratch1, Register Rscratch2); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 8979e213acf..3602c646192 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -655,6 +655,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -701,6 +702,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -2092,12 +2094,14 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state // Copied from TemplateTable::_return. // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2157,6 +2161,10 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) { bname = "trace_code_btos {"; tsize = 2; break; + case ztos: + bname = "trace_code_ztos {"; + tsize = 2; + break; case ctos: bname = "trace_code_ctos {"; tsize = 2; diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index c59e7b4b38b..6b8f658ff09 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -170,6 +170,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg switch (new_bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -981,9 +982,21 @@ void TemplateTable::bastore() { Rarray = R12_scratch2, Rscratch = R3_ARG1; __ pop_i(Rindex); + __ pop_ptr(Rarray); // tos: val - // Rarray: array ptr (popped by index_check) - __ index_check(Rarray, Rindex, 0, Rscratch, Rarray); + + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(Rscratch, Rarray); + __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); + int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); + __ testbitdi(CCR0, R0, Rscratch, diffbit); + Label L_skip; + __ bfalse(CCR0, L_skip); + __ andi(R17_tos, R17_tos, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + + __ index_check_without_pop(Rarray, Rindex, 0, Rscratch, Rarray); __ stb(R17_tos, arrayOopDesc::base_offset_in_bytes(T_BYTE), Rarray); } @@ -2108,12 +2121,16 @@ void TemplateTable::_return(TosState state) { __ remove_activation(state, /* throw_monitor_exception */ true); // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2518,6 +2535,21 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ beq(CCR6, Lacquire); // Volatile? __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. + // __ bind(Lztos); (same code as btos) + __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ lbzx(R17_tos, Rclass_or_obj, Roffset); + __ extsb(R17_tos, R17_tos); + __ push(ztos); + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, Rbc, Rscratch); + } + __ beq(CCR6, Lacquire); // Volatile? + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. // __ bind(Lctos); __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2618,6 +2650,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ push_ptr(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ push_i(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_lputfield: __ push_l(); offs+=2*Interpreter::stackElementSize; break; @@ -2658,6 +2691,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ pop_ptr(); break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ pop_i(); break; case Bytecodes::_fast_lputfield: __ pop_l(); break; @@ -2824,6 +2858,21 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. + // __ bind(Lztos); + __ release(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ pop(ztos); + if (!is_static) { pop_and_check_object(Rclass_or_obj); } // Kills R11_scratch1. + __ andi(R17_tos, R17_tos, 0x1); + __ stbx(R17_tos, Rclass_or_obj, Roffset); + if (!is_static) { patch_bytecode(Bytecodes::_fast_zputfield, Rbc, Rscratch, true, byte_no); } + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + __ beq(CR_is_vol, Lvolatile); // Volatile? + } + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. // __ bind(Lctos); __ release(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2949,6 +2998,9 @@ void TemplateTable::fast_storefield(TosState state) { __ stdx(R17_tos, Rclass_or_obj, Roffset); break; + case Bytecodes::_fast_zputfield: + __ andi(R17_tos, R17_tos, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ stbx(R17_tos, Rclass_or_obj, Roffset); break; From f2c59f97ce65dd3c7eb879bfaa085e2ec8799e76 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 22 Apr 2016 10:48:12 +0200 Subject: [PATCH 101/113] 8154326: bash >(...) construct causes race conditions Reviewed-by: tbell, ihse --- make/InitSupport.gmk | 2 +- make/common/MakeBase.gmk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 493591ebbec..cee30522d33 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -331,7 +331,7 @@ else # $(HAS_SPEC)=true BUILD_LOG := $(OUTPUT_ROOT)/build.log BUILD_TRACE_LOG := $(OUTPUT_ROOT)/build-trace-time.log - BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) + BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait # Sanity check the spec file, so it matches this source code define CheckSpecSanity diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 6f1f00b99d5..f159b8fca63 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -706,10 +706,10 @@ endif ExecuteWithLog = \ $(call LogCmdlines, Exececuting: [$(strip $2)]) \ $(call WriteFile, $2, $(strip $1).cmdline) \ - ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ + ( ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ ( exitcode=$(DOLLAR)? && \ $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).log && \ - exit $(DOLLAR)exitcode ) ) + exit $(DOLLAR)exitcode ) ) && wait ) ################################################################################ # Find lib dir for module From 911f4b1664c6b7f6d2c2208c8f3ae052ea170aa7 Mon Sep 17 00:00:00 2001 From: Nadeesh TV Date: Mon, 25 Apr 2016 09:37:43 +0000 Subject: [PATCH 102/113] 8031085: DateTimeFormatter won't parse dates with custom format "yyyyMMddHHmmssSSS" Changed the FractionPrinterParser to subclass of NumberPrinterParser to make it participate in adjacent value parsing Reviewed-by: rriggs, scolebourne --- .../time/format/DateTimeFormatterBuilder.java | 81 ++++++++++++++++--- .../format/TCKDateTimeFormatterBuilder.java | 18 ++++- 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index e8ca3f1e99f..a36d1b5e142 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -667,8 +667,11 @@ public final class DateTimeFormatterBuilder { * No rounding occurs due to the maximum width - digits are simply dropped. *

    * When parsing in strict mode, the number of parsed digits must be between - * the minimum and maximum width. When parsing in lenient mode, the minimum - * width is considered to be zero and the maximum is nine. + * the minimum and maximum width. In strict mode, if the minimum and maximum widths + * are equal and there is no decimal point then the parser will + * participate in adjacent value parsing, see + * {@link appendValue(java.time.temporal.TemporalField, int)}. When parsing in lenient mode, + * the minimum width is considered to be zero and the maximum is nine. *

    * If the value cannot be obtained then an exception will be thrown. * If the value is negative an exception will be thrown. @@ -687,7 +690,12 @@ public final class DateTimeFormatterBuilder { */ public DateTimeFormatterBuilder appendFraction( TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { - appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + if (minWidth == maxWidth && decimalPoint == false) { + // adjacent parsing + appendValue(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } else { + appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } return this; } @@ -2925,11 +2933,8 @@ public final class DateTimeFormatterBuilder { /** * Prints and parses a numeric date-time field with optional padding. */ - static final class FractionPrinterParser implements DateTimePrinterParser { - private final TemporalField field; - private final int minWidth; - private final int maxWidth; - private final boolean decimalPoint; + static final class FractionPrinterParser extends NumberPrinterParser { + private final boolean decimalPoint; /** * Constructor. @@ -2940,6 +2945,7 @@ public final class DateTimeFormatterBuilder { * @param decimalPoint whether to output the localized decimal point symbol */ FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { + this(field, minWidth, maxWidth, decimalPoint, 0); Objects.requireNonNull(field, "field"); if (field.range().isFixed() == false) { throw new IllegalArgumentException("Field must have a fixed set of values: " + field); @@ -2954,12 +2960,61 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " + maxWidth + " < " + minWidth); } - this.field = field; - this.minWidth = minWidth; - this.maxWidth = maxWidth; + } + + /** + * Constructor. + * + * @param field the field to output, not null + * @param minWidth the minimum width to output, from 0 to 9 + * @param maxWidth the maximum width to output, from 0 to 9 + * @param decimalPoint whether to output the localized decimal point symbol + * @param subsequentWidth the subsequentWidth for this instance + */ + FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; } + /** + * Returns a new instance with fixed width flag set. + * + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withFixedWidth() { + if (subsequentWidth == -1) { + return this; + } + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, -1); + } + + /** + * Returns a new instance with an updated subsequent width. + * + * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withSubsequentWidth(int subsequentWidth) { + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, this.subsequentWidth + subsequentWidth); + } + + /** + * For FractionPrinterPrinterParser, the width is fixed if context is sttrict, + * minWidth equal to maxWidth and decimalpoint is absent. + * @param context the context + * @return if the field is fixed width + * @see DateTimeFormatterBuilder#appendValueFraction(java.time.temporal.TemporalField, int, int, boolean) + */ + @Override + boolean isFixedWidth(DateTimeParseContext context) { + if (context.isStrict() && minWidth == maxWidth && decimalPoint == false) { + return true; + } + return false; + } + @Override public boolean format(DateTimePrintContext context, StringBuilder buf) { Long value = context.getValue(field); @@ -2992,8 +3047,8 @@ public final class DateTimeFormatterBuilder { @Override public int parse(DateTimeParseContext context, CharSequence text, int position) { - int effectiveMin = (context.isStrict() ? minWidth : 0); - int effectiveMax = (context.isStrict() ? maxWidth : 9); + int effectiveMin = (context.isStrict() || isFixedWidth(context) ? minWidth : 0); + int effectiveMax = (context.isStrict() || isFixedWidth(context) ? maxWidth : 9); int length = text.length(); if (position == length) { // valid if whole field is optional, invalid if minimum width diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 2fde35b5e2c..14d7e0359d4 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -71,6 +71,7 @@ import static org.testng.Assert.assertEquals; import java.text.ParsePosition; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.YearMonth; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -930,7 +931,7 @@ public class TCKDateTimeFormatterBuilder { @Test public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { - // succeeds because hour/min are fixed width + // succeeds because hour, min and fraction of seconds are fixed width DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); ParsePosition pp = new ParsePosition(0); TemporalAccessor parsed = f.parseUnresolved("1230", pp); @@ -940,6 +941,21 @@ public class TCKDateTimeFormatterBuilder { assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); } + @DataProvider(name="adjacentFractionParseData") + Object[][] data_adjacent_fraction_parse() { + return new Object[][] { + {"20130812214600025", "yyyyMMddHHmmssSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25000000)}, + {"201308122146000256", "yyyyMMddHHmmssSSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25600000)}, + }; + } + + @Test(dataProvider = "adjacentFractionParseData") + public void test_adjacent_fraction(String input, String pattern, LocalDateTime expected) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern); + LocalDateTime actual = LocalDateTime.parse(input, dtf); + assertEquals(actual, expected); + } + @DataProvider(name="lenientOffsetParseData") Object[][] data_lenient_offset_parse() { return new Object[][] { From f4d962e735d90915da9095586b29f2bf671b92e8 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 103/113] 8147426: Missing definition for JIMAGE_NOT_FOUND Reviewed-by: hseigel, alanb --- jdk/src/java.base/share/native/libjimage/jimage.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp index d215e30c2ab..f3371204ec7 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.hpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp @@ -37,11 +37,13 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes +// Resource was not found +#define JIMAGE_NOT_FOUND (0) // The image file is not prefixed with 0xCAFEDADA #define JIMAGE_BAD_MAGIC (-1) // The image file does not have a compatible (translatable) version From 5013b6458071350c568b81cd57bf4ed25b4839ae Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 104/113] 8147634: Need a JImage API that given a JImageLocationRef returns class name Reviewed-by: hseigel --- jdk/make/lib/CoreLibraries.gmk | 2 +- jdk/make/mapfiles/libjimage/mapfile-vers | 1 + .../share/native/libjimage/jimage.cpp | 25 ++++++++++++++++++- .../share/native/libjimage/jimage.hpp | 17 +++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index e4a24e47904..3cb135253ea 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -267,7 +267,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ -export:JIMAGE_PackageToModule \ -export:JIMAGE_FindResource -export:JIMAGE_GetResource \ - -export:JIMAGE_ResourceIterator, \ + -export:JIMAGE_ResourceIterator -export:JIMAGE_ResourcePath, \ LIBS_unix := -ljvm -ldl $(LIBCXX), \ LIBS_solaris := -lc, \ LIBS_macosx := -lc++, \ diff --git a/jdk/make/mapfiles/libjimage/mapfile-vers b/jdk/make/mapfiles/libjimage/mapfile-vers index 48eac21b53a..a4de5f82f3c 100644 --- a/jdk/make/mapfiles/libjimage/mapfile-vers +++ b/jdk/make/mapfiles/libjimage/mapfile-vers @@ -34,6 +34,7 @@ SUNWprivate_1.1 { JIMAGE_FindResource; JIMAGE_GetResource; JIMAGE_ResourceIterator; + JIMAGE_ResourcePath; local: *; }; diff --git a/jdk/src/java.base/share/native/libjimage/jimage.cpp b/jdk/src/java.base/share/native/libjimage/jimage.cpp index 4816a173be9..0c12facbc4d 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.cpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp @@ -207,7 +207,30 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* image, if (!(*visitor)(image, module, "9", parent, base, extension, arg)) { break; } - } } +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max) { + ImageFileReader* imageFile = (ImageFileReader*) image; + + u4 offset = (u4) locationRef; + if (offset >= imageFile->locations_size()) { + return false; + } + + ImageLocation location(imageFile->get_location_offset_data(offset)); + imageFile->location_path(location, path, max); + + return true; +} diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp index f3371204ec7..637f1689e49 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.hpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp @@ -186,3 +186,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + From 80b4b623c7b292ca84e8795f37a0f26f37ad8f13 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 105/113] 8082537: jimage should print usage when started with no args Reviewed-by: alanb --- .../jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 44a6bcc4ce3..105e8f61b44 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -152,6 +152,11 @@ class JImageTask { setLog(new PrintWriter(System.out)); } + if (args.length == 0) { + log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + return EXIT_ABNORMAL; + } + try { List unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { From 58b1ba941edb7bbc991194e2d4b660e0f49964b3 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 106/113] 8153930: Compiler crashed (intermittently) Reviewed-by: redestad, alanb --- .../jdk/internal/jimage/ImageReader.java | 829 ++++++++++-------- .../jdk/internal/jrtfs/JrtFileSystem.java | 12 +- .../jdk/internal/jrtfs/SystemImage.java | 4 +- 3 files changed, 479 insertions(+), 366 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index 41a51b88acf..2c78ea9e5d5 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -25,6 +25,7 @@ package jdk.internal.jimage; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -36,8 +37,11 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; /** @@ -47,80 +51,486 @@ import java.util.function.Consumer; * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -public class ImageReader extends BasicImageReader { +public final class ImageReader implements AutoCloseable { + private SharedImageReader reader; - private static final int SIZE_OF_OFFSET = 4; - - // Map of files opened as LITTLE_ENDIAN - private static final HashMap OPEN_LE_FILES - = new HashMap<>(); - - // Map of files opened as BIG_ENDIAN - private static final HashMap OPEN_BE_FILES - = new HashMap<>(); - - private int openCount; - - // attributes of the .jimage file. jimage file does not contain - // attributes for the individual resources (yet). We use attributes - // of the jimage file itself (creation, modification, access times). - // Iniitalized lazily, see {@link #imageFileAttributes()}. - private BasicFileAttributes imageFileAttributes; - - // directory management implementation - private final HashMap nodes; - private volatile Directory rootDir; - - private Directory packagesDir; - private Directory modulesDir; - - private ImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { - super(imagePath, byteOrder); - this.nodes = new HashMap<>(); + private ImageReader(SharedImageReader reader) { + this.reader = reader; } public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { - HashMap openFiles = getOpenFilesMap(byteOrder); - ImageReader reader; - synchronized (openFiles) { - reader = openFiles.get(imagePath); - if (reader == null) { - reader = new ImageReader(imagePath, byteOrder); - ImageReader existingReader = openFiles.putIfAbsent(imagePath, reader); - assert (existingReader == null); - } - reader.openCount++; - } - return reader; + return SharedImageReader.open(imagePath, byteOrder); } - private static HashMap getOpenFilesMap(ByteOrder byteOrder) { - return (byteOrder == ByteOrder.BIG_ENDIAN) ? OPEN_BE_FILES : OPEN_LE_FILES; - } - - /** - * Opens the given file path as an image file, returning an {@code ImageReader}. - */ public static ImageReader open(Path imagePath) throws IOException { return open(imagePath, ByteOrder.nativeOrder()); } - private boolean canClose() { - HashMap openFiles = getOpenFilesMap(this.getByteOrder()); - synchronized (openFiles) { - if (--this.openCount == 0) { - return openFiles.remove(this.getName(), this); - } - } - return false; - } - @Override public void close() throws IOException { - if (canClose()) { - super.close(); - clearNodes(); - } + if (reader == null) { + throw new IOException("image file already closed"); + } + + reader.close(this); + reader = null; + } + + // directory management interface + public Directory getRootDirectory() throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getRootDirectory(); + } + + public Node findNode(String name) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.findNode(name); + } + + public byte[] getResource(Node node) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(node); + } + + public byte[] getResource(Resource rs) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(rs); + } + + public ImageHeader getHeader() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getHeader(); + } + + public static void releaseByteBuffer(ByteBuffer buffer) { + BasicImageReader.releaseByteBuffer(buffer); + } + + public String getName() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getName() ; + } + + public ByteOrder getByteOrder() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getByteOrder(); + } + + public Path getImagePath() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getImagePath(); + } + + public ImageStringsReader getStrings() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getStrings(); + } + + public ImageLocation findLocation(String mn, String rn) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(mn, rn); + } + + public ImageLocation findLocation(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(name); + } + + public String[] getEntryNames() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getEntryNames(); + } + + public long[] getAttributes(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getAttributes(offset); + } + + public String getString(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getString(offset); + } + + public byte[] getResource(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(name); + } + + public byte[] getResource(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(loc); + } + + public ByteBuffer getResourceBuffer(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceBuffer(loc); + } + + public InputStream getResourceStream(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceStream(loc); + } + + private final static class SharedImageReader extends BasicImageReader { + static final int SIZE_OF_OFFSET = Integer.BYTES; + + static final Map OPEN_FILES = new HashMap<>(); + + // List of openers for this shared image. + final Set openers; + + // attributes of the .jimage file. jimage file does not contain + // attributes for the individual resources (yet). We use attributes + // of the jimage file itself (creation, modification, access times). + // Iniitalized lazily, see {@link #imageFileAttributes()}. + BasicFileAttributes imageFileAttributes; + + // directory management implementation + final HashMap nodes; + volatile Directory rootDir; + + Directory packagesDir; + Directory modulesDir; + + private SharedImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { + super(imagePath, byteOrder); + this.openers = new HashSet<>(); + this.nodes = new HashMap<>(); + } + + public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + synchronized (OPEN_FILES) { + SharedImageReader reader = OPEN_FILES.get(imagePath); + + if (reader == null) { + // Will fail with an IOException if wrong byteOrder. + reader = new SharedImageReader(imagePath, byteOrder); + OPEN_FILES.put(imagePath, reader); + } else if (reader.getByteOrder() != byteOrder) { + throw new IOException("\"" + reader.getName() + "\" is not an image file"); + } + + ImageReader image = new ImageReader(reader); + reader.openers.add(image); + + return image; + } + } + + public void close(ImageReader image) throws IOException { + synchronized (OPEN_FILES) { + if (!openers.remove(image)) { + throw new IOException("image file already closed"); + } + + if (openers.isEmpty()) { + close(); + nodes.clear(); + rootDir = null; + + if (!OPEN_FILES.remove(this.getImagePath(), this)) { + throw new IOException("image file not found in open list"); + } + } + } + } + + void addOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + openers.add(reader); + } + } + + boolean removeOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + return openers.remove(reader); + } + } + + // directory management interface + Directory getRootDirectory() { + return buildRootDirectory(); + } + + /** + * Lazily build a node from a name. + */ + synchronized Node buildNode(String name) { + Node n; + boolean isPackages = name.startsWith("/packages"); + boolean isModules = !isPackages && name.startsWith("/modules"); + + if (!(isModules || isPackages)) { + return null; + } + + ImageLocation loc = findLocation(name); + + if (loc != null) { // A sub tree node + if (isPackages) { + n = handlePackages(name, loc); + } else { // modules sub tree + n = handleModulesSubTree(name, loc); + } + } else { // Asking for a resource? /modules/java.base/java/lang/Object.class + if (isModules) { + n = handleResource(name); + } else { + // Possibly ask for /packages/java.lang/java.base + // although /packages/java.base not created + n = handleModuleLink(name); + } + } + return n; + } + + synchronized Directory buildRootDirectory() { + Directory root = rootDir; // volatile read + if (root != null) { + return root; + } + + root = newDirectory(null, "/"); + root.setIsRootDir(); + + // /packages dir + packagesDir = newDirectory(root, "/packages"); + packagesDir.setIsPackagesDir(); + + // /modules dir + modulesDir = newDirectory(root, "/modules"); + modulesDir.setIsModulesDir(); + + root.setCompleted(true); + return rootDir = root; + } + + /** + * To visit sub tree resources. + */ + interface LocationVisitor { + void visit(ImageLocation loc); + } + + void visitLocation(ImageLocation loc, LocationVisitor visitor) { + byte[] offsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(offsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { + int offset = intBuffer.get(i); + ImageLocation pkgLoc = getLocation(offset); + visitor.visit(pkgLoc); + } + } + + void visitPackageLocation(ImageLocation loc) { + // Retrieve package name + String pkgName = getBaseExt(loc); + // Content is array of offsets in Strings table + byte[] stringsOffsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + // For each module, create a link node. + for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { + // skip empty state, useless. + intBuffer.get(i); + i++; + int offset = intBuffer.get(i); + String moduleName = getString(offset); + Node targetNode = findNode("/modules/" + moduleName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); + } + } + } + + Node handlePackages(String name, ImageLocation loc) { + long size = loc.getUncompressedSize(); + Node n = null; + // Only possiblities are /packages, /packages/package/module + if (name.equals("/packages")) { + visitLocation(loc, (childloc) -> { + findNode(childloc.getFullName()); + }); + packagesDir.setCompleted(true); + n = packagesDir; + } else { + if (size != 0) { // children are offsets to module in StringsTable + String pkgName = getBaseExt(loc); + Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); + visitPackageLocation(loc); + pkgDir.setCompleted(true); + n = pkgDir; + } else { // Link to module + String pkgName = loc.getParent(); + String modName = getBaseExt(loc); + Node targetNode = findNode("/modules/" + modName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); + n = linkNode; + } + } + } + return n; + } + + // Asking for /packages/package/module although + // /packages// not yet created, need to create it + // prior to return the link to module node. + Node handleModuleLink(String name) { + // eg: unresolved /packages/package/module + // Build /packages/package node + Node ret = null; + String radical = "/packages/"; + String path = name; + if (path.startsWith(radical)) { + int start = radical.length(); + int pkgEnd = path.indexOf('/', start); + if (pkgEnd != -1) { + String pkg = path.substring(start, pkgEnd); + String pkgPath = radical + pkg; + Node n = findNode(pkgPath); + // If not found means that this is a symbolic link such as: + // /packages/java.util/java.base/java/util/Vector.class + // and will be done by a retry of the filesystem + for (Node child : n.getChildren()) { + if (child.name.equals(name)) { + ret = child; + break; + } + } + } + } + return ret; + } + + Node handleModulesSubTree(String name, ImageLocation loc) { + Node n; + assert (name.equals(loc.getFullName())); + Directory dir = makeDirectories(name); + visitLocation(loc, (childloc) -> { + String path = childloc.getFullName(); + if (path.startsWith("/modules")) { // a package + makeDirectories(path); + } else { // a resource + makeDirectories(childloc.buildName(true, true, false)); + newResource(dir, childloc); + } + }); + dir.setCompleted(true); + n = dir; + return n; + } + + Node handleResource(String name) { + Node n = null; + String locationPath = name.substring("/modules".length()); + ImageLocation resourceLoc = findLocation(locationPath); + if (resourceLoc != null) { + Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); + Resource res = newResource(dir, resourceLoc); + n = res; + } + return n; + } + + String getBaseExt(ImageLocation loc) { + String base = loc.getBase(); + String ext = loc.getExtension(); + if (ext != null && !ext.isEmpty()) { + base = base + "." + ext; + } + return base; + } + + synchronized Node findNode(String name) { + buildRootDirectory(); + Node n = nodes.get(name); + if (n == null || !n.isCompleted()) { + n = buildNode(name); + } + return n; + } + + /** + * Returns the file attributes of the image file. + */ + BasicFileAttributes imageFileAttributes() { + BasicFileAttributes attrs = imageFileAttributes; + if (attrs == null) { + try { + Path file = getImagePath(); + attrs = Files.readAttributes(file, BasicFileAttributes.class); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + imageFileAttributes = attrs; + } + return attrs; + } + + Directory newDirectory(Directory parent, String name) { + Directory dir = Directory.create(parent, name, imageFileAttributes()); + nodes.put(dir.getName(), dir); + return dir; + } + + Resource newResource(Directory parent, ImageLocation loc) { + Resource res = Resource.create(parent, loc, imageFileAttributes()); + nodes.put(res.getName(), res); + return res; + } + + LinkNode newLinkNode(Directory dir, String name, Node link) { + LinkNode linkNode = LinkNode.create(dir, name, link); + nodes.put(linkNode.getName(), linkNode); + return linkNode; + } + + Directory makeDirectories(String parent) { + Directory last = rootDir; + for (int offset = parent.indexOf('/', 1); + offset != -1; + offset = parent.indexOf('/', offset + 1)) { + String dir = parent.substring(0, offset); + last = makeDirectory(dir, last); + } + return makeDirectory(parent, last); + + } + + Directory makeDirectory(String dir, Directory last) { + Directory nextDir = (Directory) nodes.get(dir); + if (nextDir == null) { + nextDir = newDirectory(last, dir); + } + return nextDir; + } + + byte[] getResource(Node node) throws IOException { + if (node.isResource()) { + return super.getResource(node.getLocation()); + } + throw new IOException("Not a resource: " + node); + } + + byte[] getResource(Resource rs) throws IOException { + return super.getResource(rs.getLocation()); + } } // jimage file does not store directory structure. We build nodes @@ -389,7 +799,7 @@ public class ImageReader extends BasicImageReader { @Override public Node resolveLink(boolean recursive) { - return recursive && (link instanceof LinkNode)? ((LinkNode)link).resolveLink(true) : link; + return (recursive && link instanceof LinkNode) ? ((LinkNode)link).resolveLink(true) : link; } @Override @@ -397,297 +807,4 @@ public class ImageReader extends BasicImageReader { return true; } } - - // directory management interface - public Directory getRootDirectory() { - return buildRootDirectory(); - } - - /** - * To visit sub tree resources. - */ - interface LocationVisitor { - - void visit(ImageLocation loc); - } - - /** - * Lazily build a node from a name. - */ - private Node buildNode(String name) { - Node n; - boolean isPackages = name.startsWith("/packages"); - boolean isModules = !isPackages && name.startsWith("/modules"); - - if (!(isModules || isPackages)) { - return null; - } - - ImageLocation loc = findLocation(name); - - if (loc != null) { // A sub tree node - if (isPackages) { - n = handlePackages(name, loc); - } else { // modules sub tree - n = handleModulesSubTree(name, loc); - } - } else { // Asking for a resource? /modules/java.base/java/lang/Object.class - if (isModules) { - n = handleResource(name); - } else { - // Possibly ask for /packages/java.lang/java.base - // although /packages/java.base not created - n = handleModuleLink(name); - } - } - return n; - } - - private void visitLocation(ImageLocation loc, LocationVisitor visitor) { - byte[] offsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(offsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { - int offset = intBuffer.get(i); - ImageLocation pkgLoc = getLocation(offset); - visitor.visit(pkgLoc); - } - } - - private void visitPackageLocation(ImageLocation loc) { - // Retrieve package name - String pkgName = getBaseExt(loc); - // Content is array of offsets in Strings table - byte[] stringsOffsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - // For each module, create a link node. - for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { - // skip empty state, useless. - intBuffer.get(i); - i++; - int offset = intBuffer.get(i); - String moduleName = getString(offset); - Node targetNode = findNode("/modules/" + moduleName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); - } - } - } - - private Node handlePackages(String name, ImageLocation loc) { - long size = loc.getUncompressedSize(); - Node n = null; - // Only possiblities are /packages, /packages/package/module - if (name.equals("/packages")) { - visitLocation(loc, (childloc) -> { - findNode(childloc.getFullName()); - }); - packagesDir.setCompleted(true); - n = packagesDir; - } else { - if (size != 0) { // children are offsets to module in StringsTable - String pkgName = getBaseExt(loc); - Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); - visitPackageLocation(loc); - pkgDir.setCompleted(true); - n = pkgDir; - } else { // Link to module - String pkgName = loc.getParent(); - String modName = getBaseExt(loc); - Node targetNode = findNode("/modules/" + modName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); - n = linkNode; - } - } - } - return n; - } - - // Asking for /packages/package/module although - // /packages// not yet created, need to create it - // prior to return the link to module node. - private Node handleModuleLink(String name) { - // eg: unresolved /packages/package/module - // Build /packages/package node - Node ret = null; - String radical = "/packages/"; - String path = name; - if (path.startsWith(radical)) { - int start = radical.length(); - int pkgEnd = path.indexOf('/', start); - if (pkgEnd != -1) { - String pkg = path.substring(start, pkgEnd); - String pkgPath = radical + pkg; - Node n = findNode(pkgPath); - // If not found means that this is a symbolic link such as: - // /packages/java.util/java.base/java/util/Vector.class - // and will be done by a retry of the filesystem - for (Node child : n.getChildren()) { - if (child.name.equals(name)) { - ret = child; - break; - } - } - } - } - return ret; - } - - private Node handleModulesSubTree(String name, ImageLocation loc) { - Node n; - assert (name.equals(loc.getFullName())); - Directory dir = makeDirectories(name); - visitLocation(loc, (childloc) -> { - String path = childloc.getFullName(); - if (path.startsWith("/modules")) { // a package - makeDirectories(path); - } else { // a resource - makeDirectories(childloc.buildName(true, true, false)); - newResource(dir, childloc); - } - }); - dir.setCompleted(true); - n = dir; - return n; - } - - private Node handleResource(String name) { - Node n = null; - String locationPath = name.substring("/modules".length()); - ImageLocation resourceLoc = findLocation(locationPath); - if (resourceLoc != null) { - Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); - Resource res = newResource(dir, resourceLoc); - n = res; - } - return n; - } - - private String getBaseExt(ImageLocation loc) { - String base = loc.getBase(); - String ext = loc.getExtension(); - if (ext != null && !ext.isEmpty()) { - base = base + "." + ext; - } - return base; - } - - public synchronized Node findNode(String name) { - buildRootDirectory(); - Node n = nodes.get(name); - if (n == null || !n.isCompleted()) { - n = buildNode(name); - } - return n; - } - - private synchronized void clearNodes() { - nodes.clear(); - rootDir = null; - } - - /** - * Returns the file attributes of the image file. - */ - private BasicFileAttributes imageFileAttributes() { - BasicFileAttributes attrs = imageFileAttributes; - if (attrs == null) { - try { - Path file = getImagePath(); - attrs = Files.readAttributes(file, BasicFileAttributes.class); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - imageFileAttributes = attrs; - } - return attrs; - } - - private Directory buildRootDirectory() { - Directory root = rootDir; // volatile read - if (root != null) { - return root; - } - - synchronized (this) { - root = rootDir; - if (root != null) { - return root; - } - - // FIXME no time information per resource in jimage file (yet?) - // we use file attributes of jimage itself. - // root directory - root = newDirectory(null, "/"); - root.setIsRootDir(); - - // /packages dir - packagesDir = newDirectory(root, "/packages"); - packagesDir.setIsPackagesDir(); - - // /modules dir - modulesDir = newDirectory(root, "/modules"); - modulesDir.setIsModulesDir(); - - root.setCompleted(true); - return rootDir = root; - } - } - - private Directory newDirectory(Directory parent, String name) { - Directory dir = Directory.create(parent, name, imageFileAttributes()); - nodes.put(dir.getName(), dir); - return dir; - } - - private Resource newResource(Directory parent, ImageLocation loc) { - Resource res = Resource.create(parent, loc, imageFileAttributes()); - nodes.put(res.getName(), res); - return res; - } - - private LinkNode newLinkNode(Directory dir, String name, Node link) { - LinkNode linkNode = LinkNode.create(dir, name, link); - nodes.put(linkNode.getName(), linkNode); - return linkNode; - } - - private Directory makeDirectories(String parent) { - Directory last = rootDir; - for (int offset = parent.indexOf('/', 1); - offset != -1; - offset = parent.indexOf('/', offset + 1)) { - String dir = parent.substring(0, offset); - last = makeDirectory(dir, last); - } - return makeDirectory(parent, last); - - } - - private Directory makeDirectory(String dir, Directory last) { - Directory nextDir = (Directory) nodes.get(dir); - if (nextDir == null) { - nextDir = newDirectory(last, dir); - } - return nextDir; - } - - public byte[] getResource(Node node) throws IOException { - if (node.isResource()) { - return super.getResource(node.getLocation()); - } - throw new IOException("Not a resource: " + node); - } - - public byte[] getResource(Resource rs) throws IOException { - return super.getResource(rs.getLocation()); - } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java index d5984095e99..5f0433b9d3b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java @@ -299,13 +299,9 @@ class JrtFileSystem extends FileSystem { } // clean up this file system - called from finalize and close - void cleanup() throws IOException { - if (!isOpen) { - return; - } - synchronized (this) { + synchronized void cleanup() throws IOException { + if (isOpen) { isOpen = false; - // close image reader and null out image.close(); image = null; } @@ -461,8 +457,8 @@ class JrtFileSystem extends FileSystem { private Node lookup(String path) { try { return image.findNode(path); - } catch (RuntimeException re) { - throw new InvalidPathException(path, re.toString()); + } catch (RuntimeException | IOException ex) { + throw new InvalidPathException(path, ex.toString()); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java index 7b155feba88..2da0d6ed452 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java @@ -49,7 +49,7 @@ import jdk.internal.jimage.ImageReader.Node; */ abstract class SystemImage { - abstract Node findNode(String path); + abstract Node findNode(String path) throws IOException; abstract byte[] getResource(Node node) throws IOException; abstract void close() throws IOException; @@ -60,7 +60,7 @@ abstract class SystemImage { image.getRootDirectory(); return new SystemImage() { @Override - Node findNode(String path) { + Node findNode(String path) throws IOException { return image.findNode(path); } @Override From c20a95b52d5e32ad7fb9cde3e755f271f76cef9c Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 107/113] 8154090: Remove support for jimage recreate Reviewed-by: alanb --- .../jdk/tools/jimage/ExtractedImage.java | 78 ------------------- .../classes/jdk/tools/jimage/JImageTask.java | 43 ++-------- .../tools/jimage/resources/jimage.properties | 23 ++---- jdk/test/tools/jimage/JImageTest.java | 49 ------------ jdk/test/tools/jimage/JImageToolTest.java | 4 - jdk/test/tools/lib/tests/JImageGenerator.java | 4 - 6 files changed, 12 insertions(+), 189 deletions(-) delete mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java deleted file mode 100644 index 7090f768eb0..00000000000 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 jdk.tools.jimage; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Consumer; -import jdk.tools.jlink.internal.ImageFileCreator; -import jdk.tools.jlink.internal.Archive; -import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.DirArchive; -/** - * - * Support for extracted image. - */ -public final class ExtractedImage { - - private Set archives = new HashSet<>(); - private final ImagePluginStack plugins; - - ExtractedImage(Path dirPath, ImagePluginStack plugins, PrintWriter log, - boolean verbose) throws IOException { - if (!Files.isDirectory(dirPath)) { - throw new IOException("Not a directory"); - } - Consumer cons = (String t) -> { - if (verbose) { - log.println(t); - } - }; - this.plugins = plugins; - Files.walk(dirPath, 1).forEach((p) -> { - if (!dirPath.equals(p)) { - if (Files.isDirectory(p)) { - Archive a = new DirArchive(p, cons); - archives.add(a); - } - } - }); - archives = Collections.unmodifiableSet(archives); - } - - void recreateJImage(Path path) throws IOException { - ImageFileCreator.recreateJimage(path, archives, plugins); - } - - private static String getPathName(Path path) { - return path.toString().replace(File.separatorChar, '/'); - } -} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 105e8f61b44..26acec228bb 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -32,7 +32,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.file.Files; -import java.nio.file.Path; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; import java.util.LinkedList; @@ -44,8 +43,6 @@ import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION; import static jdk.internal.jimage.ImageHeader.MINOR_VERSION; import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.ImageResourcesTree; -import jdk.tools.jlink.internal.ImagePluginConfiguration; -import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.TaskHelper; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE; @@ -97,7 +94,6 @@ class JImageTask { EXTRACT, INFO, LIST, - RECREATE, SET, VERIFY }; @@ -160,18 +156,20 @@ class JImageTask { try { List unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { - options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + try { + options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + } catch (IllegalArgumentException ex) { + throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0)); + } for(int i = 1; i < unhandled.size(); i++) { options.jimages.add(new File(unhandled.get(i))); } + } else { + throw taskHelper.newBadArgs("err.not.a.task", ""); } if (options.help) { optionsHelper.showHelp(PROGNAME); } - if(optionsHelper.listPlugins()) { - optionsHelper.listPlugins(true); - return EXIT_OK; - } if (options.version || options.fullVersion) { taskHelper.showVersion(options.fullVersion); } @@ -191,30 +189,6 @@ class JImageTask { } } - private void recreate() throws Exception, BadArgs { - File directory = new File(options.directory); - if (!directory.isDirectory()) { - throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath()); - } - Path dirPath = directory.toPath(); - if (options.jimages.isEmpty()) { - throw taskHelper.newBadArgs("err.jimage.not.specified"); - } else if (options.jimages.size() != 1) { - throw taskHelper.newBadArgs("err.only.one.jimage"); - } - - Path jimage = options.jimages.get(0).toPath(); - - if (jimage.toFile().createNewFile()) { - ImagePluginStack pc = ImagePluginConfiguration.parseConfiguration(taskHelper. - getPluginsConfig(null, false)); - ExtractedImage img = new ExtractedImage(dirPath, pc, log, options.verbose); - img.recreateJImage(jimage); - } else { - throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName()); - } - } - private void title(File file, BasicImageReader reader) { log.println("jimage: " + file.getName()); } @@ -379,9 +353,6 @@ class JImageTask { case LIST: iterate(this::listTitle, this::list); break; - case RECREATE: - recreate(); - break; case SET: iterate(this::set, null); break; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 857d52b005a..99d2d4706d5 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -1,30 +1,25 @@ main.usage.summary=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ use --help for a list of possible options main.usage=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ \n\ \ extract - Extract all jimage entries into separate files into the directory\n\ \ specified by --dir= (default='.')\n\ \ info - Prints information specified in the jimage header.\n\ \ list - Prints the names of all the entries in the jimage. When used with\n\ \ --verbose will also print entry attributes ex. size and offset.\n\ -\ recreate - Reconstructs a jimage from an extracted directory (--dir)\n\ \ set - sets the value of specific jimage header entries\n\ \ verify - Reports errors on any .class entries that don't verify as classes.\n\ \n\ Possible options include: -main.extended.help=\ -jimage recreate is extensible by the main of plugins. Following plugins have been discovered \ -thanks to ServiceLoader and can be used when re-creating a jimage. - error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract/recreate +\ --dir Target directory for extract main.opt.flags=\ \ --flags=value Set the jimage flags to value @@ -38,14 +33,8 @@ main.opt.verbose=\ main.opt.version=\ \ --version Version information -main.opt.configuration=\ -\ --configuration Path to properties file containing defaults\ -\ options for recreate - main.command.files=\ \ @ Read options from file - -err.cannot.create.dir=cannot create directory: {0} err.cannot.read.file=cannot read file: {0} err.cannot.update.file=cannot update file: {0} err.file.not.found=cannot find file: {0} @@ -53,12 +42,10 @@ err.file.error=cannot access file: {0} err.flags.not.int=--flags value not integer: {0} err.internal.error=internal error: {0} {1} {2} err.invalid.arg.for.option=invalid argument for option: {0} -err.invalid.task=task must be extract|recreate|info|list|verify: {0} -err.jimage.already.exists=jimage already exists: {0} -err.jimage.not.specified=no jimage specified +err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} -err.only.one.jimage=only one jimage should be specified +err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} diff --git a/jdk/test/tools/jimage/JImageTest.java b/jdk/test/tools/jimage/JImageTest.java index be1e784c070..fa2c08b08dd 100644 --- a/jdk/test/tools/jimage/JImageTest.java +++ b/jdk/test/tools/jimage/JImageTest.java @@ -110,54 +110,5 @@ public class JImageTest { .dir(helper.createNewExtractedDir("modules")) .image(image.resolve("lib").resolve("modules")) .extract().assertSuccess(); - - Path recreatedImage = JImageGenerator.getJImageTask() - .dir(extractedDir) - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage, bootClasses, Collections.emptyList()); - - // Check replacing the boot image by recreated one - Path destFile = image.resolve("lib").resolve("modules"); - Files.copy(recreatedImage, destFile, REPLACE_EXISTING); - JImageValidator validator = new JImageValidator(module, Collections.emptyList(), - image.toFile(), Collections.emptyList(), Collections.emptyList()); - validator.validate(); - - Path recreatedImage2 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress").option("2") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage2, bootClasses, Collections.emptyList()); - - Path recreatedImage3 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--strip-debug") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage3, bootClasses, Collections.emptyList()); - - Path recreatedImage4 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - List unexpectedPaths = new ArrayList<>(); - unexpectedPaths.add(".jcov"); - unexpectedPaths.add("/META-INF/"); - JImageValidator.validate(recreatedImage4, bootClasses, unexpectedPaths); - - Path recreatedImage5 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress") - .option("2") - .option("--strip-debug") - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage5, bootClasses, unexpectedPaths); } } diff --git a/jdk/test/tools/jimage/JImageToolTest.java b/jdk/test/tools/jimage/JImageToolTest.java index 18f22f12fb1..48195c4c1da 100644 --- a/jdk/test/tools/jimage/JImageToolTest.java +++ b/jdk/test/tools/jimage/JImageToolTest.java @@ -63,11 +63,7 @@ public class JImageToolTest { String jimage = jimagePath.toAbsolutePath().toString(); String bootimage = modulesimagePath.toAbsolutePath().toString(); String extractDir = Paths.get(".", "extract").toAbsolutePath().toString(); - String recreateImage = Paths.get(".", "recreate").toAbsolutePath().toString(); - String relativeRecreateImage = Paths.get(".", "recreate2").toString(); jimage("extract", "--dir", extractDir, bootimage); - jimage("recreate", "--dir", extractDir, recreateImage); - jimage("recreate", "--dir", extractDir, relativeRecreateImage); System.out.println("Test successful"); } else { System.out.println("Test skipped, not an images build"); diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index 77366aafb13..c75164b69cc 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -553,10 +553,6 @@ public class JImageGenerator { public Result extract() { return cmd("extract", dir); } - - public Result recreate() { - return cmd("recreate", image); - } } public static class JLinkTask { From d83717b035492c9ec6ca3a1092ba721a4c492e25 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 108/113] 8069079: jimage extract / list to organize classes by modules Reviewed-by: alanb, mchung --- .../classes/jdk/tools/jimage/JImageTask.java | 86 +++++++++++++------ .../tools/jimage/resources/jimage.properties | 1 + 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 26acec228bb..b8a2d58c7fc 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -189,25 +189,19 @@ class JImageTask { } } - private void title(File file, BasicImageReader reader) { - log.println("jimage: " + file.getName()); - } - private void listTitle(File file, BasicImageReader reader) { - title(file, reader); - - if (options.verbose) { - log.print(pad("Offset", OFFSET_WIDTH + 1)); - log.print(pad("Size", SIZE_WIDTH + 1)); - log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1)); - log.println(" Entry"); - } + log.println("jimage: " + file); } private interface JImageAction { public void apply(File file, BasicImageReader reader) throws IOException, BadArgs; } + private interface ModuleAction { + public void apply(BasicImageReader reader, + String oldModule, String newModule) throws IOException, BadArgs; + } + private interface ResourceAction { public void apply(BasicImageReader reader, String name, ImageLocation location) throws IOException, BadArgs; @@ -233,23 +227,32 @@ class JImageTask { } } - private static final int NUMBER_WIDTH = 12; - private static final int OFFSET_WIDTH = NUMBER_WIDTH; - private static final int SIZE_WIDTH = NUMBER_WIDTH; - private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH; + private static final int OFFSET_WIDTH = 12; + private static final int SIZE_WIDTH = 10; + private static final int COMPRESSEDSIZE_WIDTH = 10; - private void print(String entry, ImageLocation location) { + private String trimModule(String name) { + int offset = name.indexOf('/', 1); + + if (offset != -1 && offset + 1 < name.length()) { + return name.substring(offset + 1); + } + + return name; + } + + private void print(String name, ImageLocation location) { log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " "); log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " "); log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " "); - log.println(entry); + log.println(trimModule(name)); } - private void print(BasicImageReader reader, String entry) { + private void print(BasicImageReader reader, String name) { if (options.verbose) { - print(entry, reader.findLocation(entry)); + print(name, reader.findLocation(name)); } else { - log.println(entry); + log.println(" " + trimModule(name)); } } @@ -268,6 +271,18 @@ class JImageTask { log.println(" Index Size: " + header.getIndexSize()); } + private void listModule(BasicImageReader reader, String oldModule, String newModule) { + log.println(); + log.println("Module: " + newModule); + + if (options.verbose) { + log.print(pad("Offset", OFFSET_WIDTH) + " "); + log.print(pad("Size", SIZE_WIDTH) + " "); + log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH) + " "); + log.println("Entry"); + } + } + private void list(BasicImageReader reader, String name, ImageLocation location) { print(reader, name); } @@ -317,7 +332,12 @@ class JImageTask { } private void iterate(JImageAction jimageAction, + ModuleAction moduleAction, ResourceAction resourceAction) throws IOException, BadArgs { + if (options.jimages.isEmpty()) { + throw taskHelper.newBadArgs("err.no.jimage"); + } + for (File file : options.jimages) { if (!file.exists() || !file.isFile()) { throw taskHelper.newBadArgs("err.not.a.jimage", file.getName()); @@ -330,9 +350,23 @@ class JImageTask { if (resourceAction != null) { String[] entryNames = reader.getEntryNames(); + String oldModule = ""; for (String name : entryNames) { if (!ImageResourcesTree.isTreeInfoResource(name)) { + if (moduleAction != null) { + int offset = name.indexOf('/', 1); + + String newModule = offset != -1 ? + name.substring(1, offset) : + ""; + + if (!oldModule.equals(newModule)) { + moduleAction.apply(reader, oldModule, newModule); + oldModule = newModule; + } + } + ImageLocation location = reader.findLocation(name); resourceAction.apply(reader, name, location); } @@ -345,19 +379,19 @@ class JImageTask { private boolean run() throws Exception, BadArgs { switch (options.task) { case EXTRACT: - iterate(null, this::extract); + iterate(null, null, this::extract); break; case INFO: - iterate(this::info, null); + iterate(this::info, null, null); break; case LIST: - iterate(this::listTitle, this::list); + iterate(this::listTitle, this::listModule, this::list); break; case SET: - iterate(this::set, null); + iterate(this::set, null, null); break; case VERIFY: - iterate(this::title, this::verify); + iterate(this::listTitle, null, this::verify); break; default: throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 99d2d4706d5..ef94fd376c6 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -46,6 +46,7 @@ err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} +err.no.jimage=no jimage provided err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} From 7057b40f4859efe2af4fcb48b9c9636ce8d6682e Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:56 -0300 Subject: [PATCH 109/113] 8154179: BasicImageReader activating ImageBufferCache when not used Reviewed-by: redestad --- .../share/classes/jdk/internal/jimage/BasicImageReader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java index 4c70a9b1547..9b21fb6c1be 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java @@ -183,7 +183,9 @@ public class BasicImageReader implements AutoCloseable { } public static void releaseByteBuffer(ByteBuffer buffer) { - ImageBufferCache.releaseBuffer(buffer); + if (!MAP_ALL) { + ImageBufferCache.releaseBuffer(buffer); + } } public String getName() { From c95df8b9fe59a9af82f316853dc9fee0dd9deab7 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:59:07 -0300 Subject: [PATCH 110/113] 8147426: Missing definition for JIMAGE_NOT_FOUND Reviewed-by: hseigel, alanb --- hotspot/src/share/vm/classfile/jimage.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp index e538ac805f8..480d01bc149 100644 --- a/hotspot/src/share/vm/classfile/jimage.hpp +++ b/hotspot/src/share/vm/classfile/jimage.hpp @@ -30,7 +30,7 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes @@ -113,7 +113,8 @@ typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* p * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); */ extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage, const char* module_name, const char* version, const char* name, @@ -134,7 +135,8 @@ typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); * char* buffer = new char[size]; * (*JImageGetResource)(image, location, buffer, size); */ @@ -154,7 +156,8 @@ typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef locati * required. All strings are utf-8, zero byte terminated.file. * * Ex. - * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) { + * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, + * const char* package, const char* name, const char* extension, void* arg) { * if (strcmp(extension, “class”) == 0) { * char path[JIMAGE_MAX_PATH]; * Thread* THREAD = Thread::current(); From ce076f3ab97f97e0a6e2027deb666a4b9409e1c6 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:59:43 -0300 Subject: [PATCH 111/113] 8147634: Need a JImage API that given a JImageLocationRef returns class name Reviewed-by: hseigel --- hotspot/src/share/vm/classfile/classLoader.cpp | 15 +++++++++------ hotspot/src/share/vm/classfile/jimage.hpp | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index a8a86765970..19b0f460a9d 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -98,12 +98,13 @@ static Crc32_t Crc32 = NULL; // Entry points for jimage.dll for loading jimage file entries -static JImageOpen_t JImageOpen = NULL; -static JImageClose_t JImageClose = NULL; -static JImagePackageToModule_t JImagePackageToModule = NULL; -static JImageFindResource_t JImageFindResource = NULL; -static JImageGetResource_t JImageGetResource = NULL; -static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImageOpen_t JImageOpen = NULL; +static JImageClose_t JImageClose = NULL; +static JImagePackageToModule_t JImagePackageToModule = NULL; +static JImageFindResource_t JImageFindResource = NULL; +static JImageGetResource_t JImageGetResource = NULL; +static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImage_ResourcePath_t JImageResourcePath = NULL; // Globals @@ -925,6 +926,8 @@ void ClassLoader::load_jimage_library() { guarantee(JImageGetResource != NULL, "function JIMAGE_GetResource not found"); JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, os::dll_lookup(handle, "JIMAGE_ResourceIterator")); guarantee(JImageResourceIterator != NULL, "function JIMAGE_ResourceIterator not found"); + JImageResourcePath = CAST_TO_FN_PTR(JImage_ResourcePath_t, os::dll_lookup(handle, "JIMAGE_ResourcePath")); + guarantee(JImageResourcePath != NULL, "function JIMAGE_ResourcePath not found"); } jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp index 480d01bc149..f34ba6efde9 100644 --- a/hotspot/src/share/vm/classfile/jimage.hpp +++ b/hotspot/src/share/vm/classfile/jimage.hpp @@ -179,3 +179,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + From f49817d6cd8f90f86c7dc4c7ab3f7f058a91ddd0 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Mon, 25 Apr 2016 08:50:16 -0700 Subject: [PATCH 112/113] 8154485: JShell: infrastructure for multi-Snippet class wrappers Reviewed-by: jlahoda --- .../internal/jshell/remote/RemoteAgent.java | 7 +- .../internal/jshell/remote/RemoteCodes.java | 10 +- .../jshell/tool/resources/l10n.properties | 2 +- .../classes/jdk/jshell/ClassTracker.java | 13 ++- .../jdk/jshell/DeclarationSnippet.java | 2 +- .../share/classes/jdk/jshell/Diag.java | 9 +- .../share/classes/jdk/jshell/DiagList.java | 5 +- .../share/classes/jdk/jshell/Eval.java | 78 +++++++-------- .../classes/jdk/jshell/ExecutionControl.java | 9 +- .../share/classes/jdk/jshell/JShell.java | 5 +- .../jdk/jshell/OuterImportSnippetWrap.java | 61 ++++++++++++ .../jdk/jshell/OuterSnippetsClassWrap.java | 95 ++++++++++++++++++ .../share/classes/jdk/jshell/OuterWrap.java | 77 +++++---------- .../classes/jdk/jshell/OuterWrapMap.java | 98 +++++++++++++++++++ .../share/classes/jdk/jshell/Snippet.java | 10 +- .../share/classes/jdk/jshell/SnippetMaps.java | 31 +++--- .../jdk/jshell/SourceCodeAnalysisImpl.java | 19 ++-- .../share/classes/jdk/jshell/TaskFactory.java | 59 +++-------- .../classes/jdk/jshell/TreeDissector.java | 34 ++++--- .../share/classes/jdk/jshell/Unit.java | 70 ++++++++----- .../share/classes/jdk/jshell/Util.java | 8 +- .../share/classes/jdk/jshell/Wrap.java | 51 +++++++++- langtools/test/jdk/jshell/ClassesTest.java | 9 +- langtools/test/jdk/jshell/DropTest.java | 13 ++- langtools/test/jdk/jshell/KullaTesting.java | 2 +- langtools/test/jdk/jshell/MethodsTest.java | 29 +++++- langtools/test/jdk/jshell/ReplaceTest.java | 24 ++--- .../jdk/jshell/SnippetStatusListenerTest.java | 2 +- langtools/test/jdk/jshell/SnippetTest.java | 3 +- langtools/test/jdk/jshell/VariablesTest.java | 4 +- 30 files changed, 573 insertions(+), 266 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java index f7d8e4a186d..83d6419f86a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java @@ -262,9 +262,14 @@ class RemoteAgent { } } + /** + * Expunge internal info from string + * @param s string to process + * @return string the display, JShell package and wrapper class names removed + */ static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java index edb33f0bd38..e8deae7e73c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java @@ -47,8 +47,12 @@ public class RemoteCodes { public static final int RESULT_CORRALLED = 103; public static final int RESULT_KILLED = 104; + // String constants + public static final String REPL_PACKAGE = "REPL"; + public static final String REPL_CLASS_PREFIX = "$JShell$"; public static final String DOIT_METHOD_NAME = "do_it$"; - public static final String replClass = "\\$REPL(?\\d+)[A-Z]*"; - public static final Pattern prefixPattern = Pattern.compile("(REPL\\.)?" + replClass + "[\\$\\.]?"); - + public static final Pattern PREFIX_PATTERN = Pattern.compile( + "(" + REPL_PACKAGE + "\\.)?" + + "(?" + Pattern.quote(REPL_CLASS_PREFIX) + + "\\w+" + ")" + "[\\$\\.]?"); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 34ef112a527..b70c6de2ac0 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -512,7 +512,7 @@ startup.feedback = \ /set format verbose errorpre '| ' \n\ /set format verbose errorpost '%n' \n\ \n\ -/set format verbose errorline '{pre} {err}' \n\ +/set format verbose errorline '{post}{pre} {err}' \n\ \n\ /set format verbose action 'created' added-primary \n\ /set format verbose action 'modified' modified-primary \n\ diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java index 206aa94b86a..51af9abbc93 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java @@ -27,6 +27,7 @@ package jdk.jshell; import java.util.Arrays; import java.util.HashMap; +import java.util.Objects; import com.sun.jdi.ReferenceType; /** @@ -82,6 +83,17 @@ class ClassTracker { } return rt; } + + @Override + public boolean equals(Object o) { + return o instanceof ClassInfo && + ((ClassInfo) o).className.equals(className); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.className); + } } ClassInfo classInfo(String className, byte[] bytes) { @@ -93,5 +105,4 @@ class ClassTracker { ClassInfo get(String className) { return map.get(className); } - } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java index 8fc60cb749d..3902fbae3bb 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java @@ -84,6 +84,6 @@ public abstract class DeclarationSnippet extends PersistentSnippet { @Override String importLine(JShell state) { - return "import static " + state.maps.classFullName(this) + "." + name() + ";\n"; + return "import static " + classFullName() + "." + name() + ";\n"; } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java index 9a5c7538143..396396dec2a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java @@ -100,10 +100,12 @@ public abstract class Diag { // *** Internal support *** /** - * Internal: If this is from a compile, extract the compilation Unit. + * Internal: If this is from a compile/analyze wrapped in an outer class, extract the snippet. * Otherwise null. */ - abstract Unit unitOrNull(); + Snippet snippetOrNull() { + return null; + } /** * This is an unreachable-statement error @@ -124,6 +126,7 @@ public abstract class Diag { */ boolean isResolutionError() { //TODO: try javac RESOLVE_ERROR flag - return getCode().startsWith("compiler.err.cant.resolve"); + return getCode().startsWith("compiler.err.cant.resolve") + || getCode().equals("compiler.err.cant.apply.symbol"); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java index b0546fe5e12..7007a5f7f1a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java @@ -106,7 +106,10 @@ final class DiagList extends ArrayList { DiagList ofUnit(Unit u) { return this.stream() - .filter(d -> d.unitOrNull() == u) + .filter(d -> { + Snippet snn = d.snippetOrNull(); + return snn == u.snippet(); + }) .collect(Collectors.toCollection(() -> new DiagList())); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 7e0e4b35392..961eafbf0c0 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.jshell; import java.util.ArrayList; @@ -50,7 +49,6 @@ import java.io.StringWriter; import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; -import com.sun.tools.javac.util.Context; import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; @@ -68,7 +66,7 @@ import static java.util.stream.Collectors.toSet; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; import static jdk.jshell.Util.*; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -339,18 +337,8 @@ class Eval { return declare(snip); } - private OuterWrap wrapInClass(String className, Set except, String userSource, Wrap guts, Collection plus) { - String imports = state.maps.packageAndImportsExcept(except, plus); - return OuterWrap.wrapInClass(state.maps.packageName(), className, imports, userSource, guts); - } - - OuterWrap wrapInClass(Snippet snip, Set except, Wrap guts, Collection plus) { - return wrapInClass(snip.className(), except, snip.source(), guts, plus); - } - private AnalyzeTask trialCompile(Wrap guts) { - OuterWrap outer = wrapInClass(REPL_DOESNOTMATTER_CLASS_NAME, - Collections.emptySet(), "", guts, null); + OuterWrap outer = state.outerMap.wrapInTrialClass(guts); return state.taskFactory.new AnalyzeTask(outer); } @@ -468,7 +456,7 @@ class Eval { if (si.status().isDefined) { if (si.isExecutable()) { try { - value = state.executionControl().commandInvoke(state.maps.classFullName(si)); + value = state.executionControl().commandInvoke(si.classFullName()); value = si.subKind().hasValue() ? expunge(value) : ""; @@ -504,37 +492,54 @@ class Eval { return events(c, outs, value, exception); } + private boolean interestingEvent(SnippetEvent e) { + return e.isSignatureChange() + || e.causeSnippet() == null + || e.status() != e.previousStatus() + || e.exception() != null; + } + private List events(Unit c, Collection outs, String value, Exception exception) { List events = new ArrayList<>(); events.add(c.event(value, exception)); events.addAll(outs.stream() .filter(u -> u != c) .map(u -> u.event(null, null)) + .filter(this::interestingEvent) .collect(Collectors.toList())); events.addAll(outs.stream() .flatMap(u -> u.secondaryEvents().stream()) + .filter(this::interestingEvent) .collect(Collectors.toList())); //System.err.printf("Events: %s\n", events); return events; } + private Set outerWrapSet(Collection units) { + return units.stream() + .map(u -> u.snippet().outerWrap()) + .collect(toSet()); + } + private Set compileAndLoad(Set ins) { if (ins.isEmpty()) { return ins; } Set replaced = new LinkedHashSet<>(); + // Loop until dependencies and errors are stable while (true) { state.debug(DBG_GEN, "compileAndLoad %s\n", ins); - ins.stream().forEach(u -> u.initialize(ins)); - AnalyzeTask at = state.taskFactory.new AnalyzeTask(ins); + ins.stream().forEach(u -> u.initialize()); + ins.stream().forEach(u -> u.setWrap(ins, ins)); + AnalyzeTask at = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setDiagnostics(at)); // corral any Snippets that need it AnalyzeTask cat; if (ins.stream().anyMatch(u -> u.corralIfNeeded(ins))) { // if any were corralled, re-analyze everything - cat = state.taskFactory.new AnalyzeTask(ins); + cat = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setCorralledDiagnostics(cat)); } else { cat = at; @@ -556,7 +561,7 @@ class Eval { legit.stream().forEach(u -> u.setWrap(ins, legit)); // generate class files for those capable - CompileTask ct = state.taskFactory.new CompileTask(legit); + CompileTask ct = state.taskFactory.new CompileTask(outerWrapSet(legit)); if (!ct.compile()) { // oy! compile failed because of recursive new unresolved if (legit.stream() @@ -572,8 +577,8 @@ class Eval { // load all new classes load(legit.stream() - .flatMap(u -> u.classesToLoad(ct.classInfoList(u))) - .collect(toList())); + .flatMap(u -> u.classesToLoad(ct.classInfoList(u.snippet().outerWrap()))) + .collect(toSet())); // attempt to redefine the remaining classes List toReplace = legit.stream() .filter(u -> !u.doRedefines()) @@ -607,7 +612,7 @@ class Eval { } } - private void load(List cil) { + private void load(Set cil) { if (!cil.isEmpty()) { state.executionControl().commandLoad(cil); } @@ -625,20 +630,14 @@ class Eval { StackTraceElement[] elems = new StackTraceElement[last + 1]; for (int i = 0; i <= last; ++i) { StackTraceElement r = raw[i]; - String rawKlass = r.getClassName(); - Matcher matcher = prefixPattern.matcher(rawKlass); - String num; - if (matcher.find() && (num = matcher.group("num")) != null) { - int end = matcher.end(); - if (rawKlass.charAt(end - 1) == '$') { - --end; - } - int id = Integer.parseInt(num); - Snippet si = state.maps.getSnippet(id); - String klass = expunge(rawKlass); + OuterSnippetsClassWrap outer = state.outerMap.getOuter(r.getClassName()); + if (outer != null) { + String klass = expunge(r.getClassName()); String method = r.getMethodName().equals(DOIT_METHOD_NAME) ? "" : r.getMethodName(); - String file = "#" + id; - int line = si.outerWrap().wrapLineToSnippetLine(r.getLineNumber() - 1) + 1; + int wln = r.getLineNumber() - 1; + int line = outer.wrapLineToSnippetLine(wln) + 1; + Snippet sn = outer.wrapLineToSnippet(wln); + String file = "#" + sn.id(); elems[i] = new StackTraceElement(klass, method, file, line); } else if (r.getFileName().equals("")) { elems[i] = new StackTraceElement(r.getClassName(), r.getMethodName(), null, r.getLineNumber()); @@ -654,7 +653,7 @@ class Eval { } private boolean isWrap(StackTraceElement ste) { - return prefixPattern.matcher(ste.getClassName()).find(); + return PREFIX_PATTERN.matcher(ste.getClassName()).find(); } private DiagList modifierDiagnostics(ModifiersTree modtree, @@ -714,11 +713,6 @@ class Eval { public String getMessage(Locale locale) { return message; } - - @Override - Unit unitOrNull() { - return null; - } } List list = new ArrayList<>(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index abaa5cbd5d5..f69ec57e797 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -36,6 +36,7 @@ import java.net.ServerSocket; import java.net.Socket; import com.sun.jdi.*; import java.io.EOFException; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -94,7 +95,7 @@ class ExecutionControl { } - boolean commandLoad(List cil) { + boolean commandLoad(Collection cil) { try { out.writeInt(CMD_LOAD); out.writeInt(cil.size()); @@ -122,7 +123,7 @@ class ExecutionControl { String result = in.readUTF(); return result; } - } catch (IOException | ClassNotFoundException ex) { + } catch (IOException | RuntimeException ex) { if (!env.connection().isRunning()) { env.shutdown(); } else { @@ -204,7 +205,7 @@ class ExecutionControl { } } - private boolean readAndReportExecutionResult() throws IOException, ClassNotFoundException, EvalException, UnresolvedReferenceException { + private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException { int ok = in.readInt(); switch (ok) { case RESULT_SUCCESS: @@ -224,7 +225,7 @@ class ExecutionControl { case RESULT_CORRALLED: { int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); - Snippet si = maps.getSnippet(id); + Snippet si = maps.getSnippetDeadOrAlive(id); throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index b261e5e67be..0cb2d05c7af 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -77,6 +77,7 @@ public class JShell implements AutoCloseable { final SnippetMaps maps; final KeyMap keyMap; + final OuterWrapMap outerMap; final TaskFactory taskFactory; final InputStream in; final PrintStream out; @@ -106,8 +107,8 @@ public class JShell implements AutoCloseable { this.idGenerator = b.idGenerator; this.maps = new SnippetMaps(this); - maps.setPackageName("REPL"); this.keyMap = new KeyMap(this); + this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); this.classTracker = new ClassTracker(this); @@ -563,7 +564,7 @@ public class JShell implements AutoCloseable { throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } - String value = executionControl().commandVarValue(maps.classFullName(snippet), snippet.name()); + String value = executionControl().commandVarValue(snippet.classFullName(), snippet.name()); return expunge(value); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java new file mode 100644 index 00000000000..8e336544943 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 jdk.jshell; + +import java.util.IdentityHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterImportSnippetWrap extends OuterWrap { + + private final Snippet snippet; + + OuterImportSnippetWrap(Wrap wrap, Snippet snippet) { + super(wrap); + this.snippet = snippet; + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + return snippet; + } + }; + } + + @Override + public String toString() { + return "OISW(" + w + ")"; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java new file mode 100644 index 00000000000..5a58ade38cc --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 jdk.jshell; + +import java.util.LinkedHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import jdk.jshell.Wrap.CompoundWrap; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterSnippetsClassWrap extends OuterWrap { + + private final String className; + private final LinkedHashMap wrapToSnippet; + + OuterSnippetsClassWrap(String className, CompoundWrap w, List snippets, List wraps) { + super(w); + assert snippets == null || snippets.size() == wraps.size(); + this.className = className; + wrapToSnippet = new LinkedHashMap<>(); + for (int i = 0; i < snippets.size(); ++i) { + wrapToSnippet.put(wraps.get(i), snippets.get(i)); + } + } + + public Snippet wrapLineToSnippet(int wline) { + Wrap wrap = ((CompoundWrap)w).wrapLineToWrap(wline); + return wrapToSnippet.get(wrap); + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + Wrap wrap = ((CompoundWrap) w).wrapIndexToWrap(diag.getPosition()); + Snippet sn = wrapToSnippet.get(wrap); + if (sn != null) { + return sn; + } else { + return super.snippetOrNull(); + } + } + }; + } + + int ordinal(Snippet sn) { + int i = 0; + for (Snippet si : wrapToSnippet.values()) { + if (si == sn) { + return i; + } + ++i; + } + return -1; + } + + @Override + public String className() { + return className; + } + + @Override + public String toString() { + return "OSCW(" + className + ":" + w + ")"; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java index b44a7015020..f61d8b487d4 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015-2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,47 +25,23 @@ package jdk.jshell; -import jdk.jshell.Wrap.CompoundWrap; -import static jdk.jshell.Util.*; import java.util.Locale; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; -import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; +import jdk.internal.jshell.remote.RemoteCodes; +import static jdk.jshell.Util.*; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * * @author Robert Field */ -final class OuterWrap implements GeneralWrap { +class OuterWrap implements GeneralWrap { - private final String packageName; - private final String className; - private final String userSource; - private final GeneralWrap w; - private final Wrap guts; + protected final Wrap w; - public static OuterWrap wrapInClass(String packageName, String className, - String imports, String userSource, Wrap guts) { - GeneralWrap kw = new CompoundWrap( - imports - + "class " + className + " {\n", - guts, - "}\n"); - return new OuterWrap(packageName, className, userSource, kw, guts); - } - - public static OuterWrap wrapImport(String userSource, Wrap guts) { - return new OuterWrap("", "", userSource, guts, guts); - } - - private OuterWrap(String packageName, String className, String userSource, - GeneralWrap w, Wrap guts) { - this.packageName = packageName; - this.className = className; - this.userSource = userSource; - this.w = w; - this.guts = guts; + OuterWrap(Wrap wrap) { + this.w = wrap; } @Override @@ -114,19 +90,28 @@ final class OuterWrap implements GeneralWrap { } public String className() { - return className; + return REPL_DOESNOTMATTER_CLASS_NAME; } public String classFullName() { - return packageName + "." + className; + return REPL_PACKAGE + "." + className(); } - public String getUserSource() { - return userSource; + @Override + public int hashCode() { + return className().hashCode(); } - Wrap guts() { - return guts; + @Override + public boolean equals(Object o) { + return (o instanceof OuterWrap) + ? className().equals(((OuterWrap) o).className()) + : false; + } + + @Override + public String toString() { + return "OW(" + w + ")"; } Diag wrapDiag(Diagnostic d) { @@ -135,7 +120,7 @@ final class OuterWrap implements GeneralWrap { class WrappedDiagnostic extends Diag { - private final Diagnostic diag; + final Diagnostic diag; WrappedDiagnostic(Diagnostic diag) { this.diag = diag; @@ -171,18 +156,6 @@ final class OuterWrap implements GeneralWrap { return expunge(diag.getMessage(locale)); } - @Override - Unit unitOrNull() { - JavaFileObject fo = diag.getSource(); - if (fo instanceof SourceMemoryJavaFileObject) { - SourceMemoryJavaFileObject sfo = (SourceMemoryJavaFileObject) fo; - if (sfo.getOrigin() instanceof Unit) { - return (Unit) sfo.getOrigin(); - } - } - return null; - } - @Override boolean isResolutionError() { if (!super.isResolutionError()) { @@ -190,7 +163,7 @@ final class OuterWrap implements GeneralWrap { } for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) { if (line.trim().startsWith("location:")) { - if (!line.contains(REPL_CLASS_PREFIX)) { + if (!line.contains(RemoteCodes.REPL_CLASS_PREFIX)) { // Resolution error must occur within a REPL class or it is not resolvable return false; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java new file mode 100644 index 00000000000..1576ebe7725 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 jdk.jshell; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.stream.Collectors; +import jdk.jshell.Wrap.CompoundWrap; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; +import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; +import static jdk.jshell.Util.asLetters; + +/** + * + * @author Robert Field + */ +public class OuterWrapMap { + + private final JShell state; + private final Map classOuters = new HashMap<>(); + + OuterWrapMap(JShell state) { + this.state = state; + } + + OuterSnippetsClassWrap getOuter(String className) { + Matcher matcher = PREFIX_PATTERN.matcher(className); + String cn; + if (matcher.find() && (cn = matcher.group("class")) != null) { + return classOuters.get(cn); + } + return null; + } + + private CompoundWrap wrappedInClass(String className, String imports, List wraps) { + List elems = new ArrayList<>(wraps.size() + 2); + elems.add(imports + + "class " + className + " {\n"); + elems.addAll(wraps); + elems.add("}\n"); + return new CompoundWrap(elems.toArray()); + } + + OuterWrap wrapInClass(Set except, Collection plus, + List snippets, List wraps) { + String imports = state.maps.packageAndImportsExcept(except, plus); + // className is unique to the set of snippets and their version (seq) + String className = REPL_CLASS_PREFIX + snippets.stream() + .sorted((sn1, sn2) -> sn1.key().index() - sn2.key().index()) + .map(sn -> "" + sn.key().index() + asLetters(sn.sequenceNumber())) + .collect(Collectors.joining("_")); + CompoundWrap w = wrappedInClass(className, imports, wraps); + OuterSnippetsClassWrap now = new OuterSnippetsClassWrap(className, w, snippets, wraps); + classOuters.put(className, now); + return now; + } + + OuterWrap wrapInTrialClass(Wrap wrap) { + String imports = state.maps.packageAndImportsExcept(null, null); + CompoundWrap w = wrappedInClass(REPL_DOESNOTMATTER_CLASS_NAME, imports, + Collections.singletonList(wrap)); + return new OuterWrap(w); + } + + OuterWrap wrapImport(Wrap guts, Snippet sn) { + return new OuterImportSnippetWrap(guts, sn); + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java index 5f5489b6a78..6669cf1803d 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java @@ -28,8 +28,6 @@ package jdk.jshell; import java.util.Collection; import java.util.Collections; import java.util.List; -import static jdk.jshell.Util.REPL_CLASS_PREFIX; -import static jdk.jshell.Util.asLetters; /** * A Snippet represents a snippet of Java source code as passed to @@ -503,7 +501,6 @@ public abstract class Snippet { private final SubKind subkind; private int seq; - private String className; private String id; private OuterWrap outer; private Status status; @@ -615,7 +612,6 @@ public abstract class Snippet { final void setSequenceNumber(int seq) { this.seq = seq; - this.className = REPL_CLASS_PREFIX + key().index() + asLetters(seq); } void setOuterWrap(OuterWrap outer) { @@ -653,7 +649,11 @@ public abstract class Snippet { } String className() { - return className; + return outer.className(); + } + + String classFullName() { + return outer.classFullName(); } /** diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index 149a90e05c3..9d0a48505d8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -38,8 +38,9 @@ import java.util.regex.Matcher; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * Maintain relationships between the significant entities: Snippets, @@ -48,7 +49,6 @@ import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; */ final class SnippetMaps { - private String packageName; private final List keyIndexToSnippet = new ArrayList<>(); private final Set snippets = new LinkedHashSet<>(); private final Map> dependencies = new HashMap<>(); @@ -81,6 +81,13 @@ final class SnippetMaps { } Snippet getSnippet(int ki) { + Snippet sn = getSnippetDeadOrAlive(ki); + return (sn != null && !sn.status().isActive) + ? null + : sn; + } + + Snippet getSnippetDeadOrAlive(int ki) { if (ki >= keyIndexToSnippet.size()) { return null; } @@ -91,21 +98,9 @@ final class SnippetMaps { return new ArrayList<>(snippets); } - void setPackageName(String n) { - packageName = n; - } - - String packageName() { - return packageName; - } - - String classFullName(Snippet sn) { - return packageName + "." + sn.className(); - } - String packageAndImportsExcept(Set except, Collection plus) { StringBuilder sb = new StringBuilder(); - sb.append("package ").append(packageName()).append(";\n"); + sb.append("package ").append(REPL_PACKAGE).append(";\n"); for (Snippet si : keyIndexToSnippet) { if (si != null && si.status().isDefined && (except == null || !except.contains(si.key()))) { sb.append(si.importLine(state)); @@ -137,7 +132,7 @@ final class SnippetMaps { } List deps = new ArrayList<>(); for (Integer dss : depset) { - Snippet dep = getSnippet(dss); + Snippet dep = getSnippetDeadOrAlive(dss); if (dep != null) { deps.add(dep); state.debug(DBG_DEP, "Found dependency %s -> %s\n", snip.name(), dep.name()); @@ -161,7 +156,7 @@ final class SnippetMaps { } String fullClassNameAndPackageToClass(String full, String pkg) { - Matcher mat = prefixPattern.matcher(full); + Matcher mat = PREFIX_PATTERN.matcher(full); if (mat.lookingAt()) { return full.substring(mat.end()); } @@ -195,6 +190,6 @@ final class SnippetMaps { private Stream importSnippets() { return state.keyMap.importKeys() .map(key -> (ImportSnippet)getSnippet(key)) - .filter(sn -> state.status(sn).isDefined); + .filter(sn -> sn != null && state.status(sn).isDefined); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 45f9661d0bb..ca6b08612b9 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -211,11 +211,6 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { throw new InternalError(); } - private OuterWrap wrapInClass(Wrap guts) { - String imports = proc.maps.packageAndImportsExcept(null, null); - return OuterWrap.wrapInClass(proc.maps.packageName(), REPL_DOESNOTMATTER_CLASS_NAME, imports, "", guts); - } - private Tree.Kind guessKind(String code) { ParseTask pt = proc.taskFactory.new ParseTask(code); List units = pt.units(); @@ -258,13 +253,13 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { OuterWrap codeWrap; switch (guessKind(code)) { case IMPORT: - codeWrap = OuterWrap.wrapImport(null, Wrap.simpleWrap(code + "any.any")); + codeWrap = proc.outerMap.wrapImport(Wrap.simpleWrap(code + "any.any"), null); break; case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } String requiredPrefix = identifier; @@ -946,7 +941,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { if (guessKind(code) == Kind.IMPORT) return null; - OuterWrap codeWrap = wrapInClass(Wrap.methodWrap(code)); + OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); SourcePositions sp = at.trees().getSourcePositions(); CompilationUnitTree topLevel = at.firstCuTree(); @@ -1064,7 +1059,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { case INTERFACE: case ANNOTATION_TYPE: case VARIABLE: return null; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); @@ -1104,10 +1099,10 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { case IMPORT: return new QualifiedNames(Collections.emptyList(), -1, true, false); case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index 8ad7862c6b4..ce34f5f16a6 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,48 +148,22 @@ class TaskFactory { public String getMessage(Locale locale) { return expunge(d.getMessage(locale)); } - - @Override - Unit unitOrNull() { - return null; - } }; } } private class WrapSourceHandler implements SourceHandler { - final OuterWrap wrap; - - WrapSourceHandler(OuterWrap wrap) { - this.wrap = wrap; - } - @Override public JavaFileObject sourceToFileObject(MemoryFileManager fm, OuterWrap w) { return fm.createSourceFileObject(w, w.classFullName(), w.wrapped()); } - @Override - public Diag diag(Diagnostic d) { - return wrap.wrapDiag(d); - } - } - - private class UnitSourceHandler implements SourceHandler { - - @Override - public JavaFileObject sourceToFileObject(MemoryFileManager fm, Unit u) { - return fm.createSourceFileObject(u, - state.maps.classFullName(u.snippet()), - u.snippet().outerWrap().wrapped()); - } - @Override public Diag diag(Diagnostic d) { SourceMemoryJavaFileObject smjfo = (SourceMemoryJavaFileObject) d.getSource(); - Unit u = (Unit) smjfo.getOrigin(); - return u.snippet().outerWrap().wrapDiag(d); + OuterWrap w = (OuterWrap) smjfo.getOrigin(); + return w.wrapDiag(d); } } @@ -242,13 +216,12 @@ class TaskFactory { private final Iterable cuts; AnalyzeTask(final OuterWrap wrap) { - this(Stream.of(wrap), - new WrapSourceHandler(wrap), - "-XDshouldStopPolicy=FLOW", "-proc:none"); + this(Collections.singletonList(wrap)); } - AnalyzeTask(final Collection units) { - this(units.stream(), new UnitSourceHandler(), + AnalyzeTask(final Collection wraps) { + this(wraps.stream(), + new WrapSourceHandler(), "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -287,10 +260,10 @@ class TaskFactory { */ class CompileTask extends BaseTask { - private final Map> classObjs = new HashMap<>(); + private final Map> classObjs = new HashMap<>(); - CompileTask(Collection units) { - super(units.stream(), new UnitSourceHandler(), + CompileTask(final Collection wraps) { + super(wraps.stream(), new WrapSourceHandler(), "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -302,8 +275,8 @@ class TaskFactory { } - List classInfoList(Unit u) { - List l = classObjs.get(u); + List classInfoList(OuterWrap w) { + List l = classObjs.get(w); if (l == null) return Collections.emptyList(); return l.stream() .map(fo -> state.classTracker.classInfo(fo.getName(), fo.getBytes())) @@ -315,11 +288,11 @@ class TaskFactory { //debug("listenForNewClassFile %s loc=%s kind=%s\n", className, location, kind); if (location == CLASS_OUTPUT) { state.debug(DBG_GEN, "Compiler generating class %s\n", className); - Unit u = ((sibling instanceof SourceMemoryJavaFileObject) - && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof Unit)) - ? (Unit) ((SourceMemoryJavaFileObject) sibling).getOrigin() + OuterWrap w = ((sibling instanceof SourceMemoryJavaFileObject) + && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof OuterWrap)) + ? (OuterWrap) ((SourceMemoryJavaFileObject) sibling).getOrigin() : null; - classObjs.compute(u, (k, v) -> (v == null)? new ArrayList<>() : v) + classObjs.compute(w, (k, v) -> (v == null)? new ArrayList<>() : v) .add(jfo); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java index f59d10b0d3a..c9fd4cedc59 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java @@ -162,18 +162,28 @@ class TreeDissector { return new Range(start, end); } - Tree firstClassMember() { - if (targetClass != null) { - //TODO: missing classes - for (Tree mem : targetClass.getMembers()) { - if (mem.getKind() == Tree.Kind.VARIABLE) { - return mem; - } - if (mem.getKind() == Tree.Kind.METHOD) { - MethodTree mt = (MethodTree) mem; - if (!isDoIt(mt.getName()) && !mt.getName().toString().equals("")) { + MethodTree method(MethodSnippet msn) { + if (targetClass == null) { + return null; + } + OuterWrap ow = msn.outerWrap(); + if (!(ow instanceof OuterSnippetsClassWrap)) { + return null; + } + int ordinal = ((OuterSnippetsClassWrap) ow).ordinal(msn); + if (ordinal < 0) { + return null; + } + int count = 0; + String name = msn.name(); + for (Tree mem : targetClass.getMembers()) { + if (mem.getKind() == Tree.Kind.METHOD) { + MethodTree mt = (MethodTree) mem; + if (mt.getName().toString().equals(name)) { + if (count == ordinal) { return mt; } + ++count; } } } @@ -244,8 +254,8 @@ class TreeDissector { return ei; } - String typeOfMethod() { - Tree unitTree = firstClassMember(); + String typeOfMethod(MethodSnippet msn) { + Tree unitTree = method(msn); if (unitTree instanceof JCMethodDecl) { JCMethodDecl mtree = (JCMethodDecl) unitTree; Type mt = types().erasure(mtree.type); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java index 538f34f5a24..e5892470440 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ final class Unit { private final DiagList generatedDiagnostics; private int seq; - private int seqInitial; + private String classNameInitial; private Wrap activeGuts; private Status status; private Status prevStatus; @@ -95,7 +95,7 @@ final class Unit { this.generatedDiagnostics = generatedDiagnostics; this.seq = isNew? 0 : siOld.sequenceNumber(); - this.seqInitial = seq; + this.classNameInitial = isNew? "" : siOld.className(); this.prevStatus = (isNew || isDependency) ? si.status() : siOld.status(); @@ -136,28 +136,50 @@ final class Unit { return isDependency; } - boolean isNew() { - return isNew; - } - - void initialize(Collection working) { + void initialize() { isAttemptingCorral = false; dependenciesNeeded = false; toRedefine = null; // assure NPE if classToLoad not called activeGuts = si.guts(); markOldDeclarationOverwritten(); - setWrap(working, working); } - void setWrap(Collection except, Collection plus) { - si.setOuterWrap(isImport() - ? OuterWrap.wrapImport(si.source(), activeGuts) - : state.eval.wrapInClass(si, - except.stream().map(u -> u.snippet().key()).collect(toSet()), - activeGuts, - plus.stream().map(u -> u.snippet()) - .filter(sn -> sn != si) - .collect(toList()))); + // Set the outer wrap of our Snippet + void setWrap(Collection exceptUnit, Collection plusUnfiltered) { + if (isImport()) { + si.setOuterWrap(state.outerMap.wrapImport(activeGuts, si)); + } else { + // Collect Units for be wrapped together. Just this except for overloaded methods + List units; + if (snippet().kind() == Kind.METHOD) { + String name = ((MethodSnippet) snippet()).name(); + units = plusUnfiltered.stream() + .filter(u -> u.snippet().kind() == Kind.METHOD && + ((MethodSnippet) u.snippet()).name().equals(name)) + .collect(toList()); + } else { + units = Collections.singletonList(this); + } + // Keys to exclude from imports + Set except = exceptUnit.stream() + .map(u -> u.snippet().key()) + .collect(toSet()); + // Snippets to add to imports + Collection plus = plusUnfiltered.stream() + .filter(u -> !units.contains(u)) + .map(u -> u.snippet()) + .collect(toList()); + // Snippets to wrap in an outer + List snippets = units.stream() + .map(u -> u.snippet()) + .collect(toList()); + // Snippet wraps to wrap in an outer + List wraps = units.stream() + .map(u -> u.activeGuts) + .collect(toList()); + // Set the outer wrap for this snippet + si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps)); + } } void setDiagnostics(AnalyzeTask ct) { @@ -302,11 +324,13 @@ final class Unit { private boolean sigChanged() { return (status.isDefined != prevStatus.isDefined) - || (seq != seqInitial && status.isDefined) + || (status.isDefined && !si.className().equals(classNameInitial)) || signatureChanged; } Stream effectedDependents() { + //System.err.printf("effectedDependents sigChanged=%b dependenciesNeeded=%b status=%s\n", + // sigChanged(), dependenciesNeeded, status); return sigChanged() || dependenciesNeeded || status == RECOVERABLE_NOT_DEFINED ? dependents() : Stream.empty(); @@ -361,7 +385,7 @@ final class Unit { if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent); // Defined methods can overwrite methods of other (equivalent) snippets - if (si.kind() == Kind.METHOD && status.isDefined) { + if (isNew && si.kind() == Kind.METHOD && status.isDefined) { MethodSnippet msi = (MethodSnippet)si; String oqpt = msi.qualifiedParameterTypes(); String nqpt = computeQualifiedParameterTypes(at, msi); @@ -405,7 +429,7 @@ final class Unit { } private String computeQualifiedParameterTypes(AnalyzeTask at, MethodSnippet msi) { - String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(); + String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(msi); String signature = expunge(rawSig); int paren = signature.lastIndexOf(')'); @@ -425,7 +449,9 @@ final class Unit { } List secondaryEvents() { - return secondaryEvents; + return secondaryEvents==null + ? Collections.emptyList() + : secondaryEvents; } @Override diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java index 8cc42150790..553e6c97fb3 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java @@ -30,7 +30,8 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.lang.model.element.Name; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; /** * Assorted shared utilities. @@ -38,8 +39,7 @@ import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; */ class Util { - static final String REPL_CLASS_PREFIX = "$REPL"; - static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"00DOESNOTMATTER"; + static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"DOESNOTMATTER"; static final Locale PARSED_LOCALE = Locale.ROOT; @@ -53,7 +53,7 @@ class Util { static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index 3dd39750cf2..873a0d1cce8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -25,6 +25,8 @@ package jdk.jshell; +import java.util.Arrays; +import static java.util.stream.Collectors.joining; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -237,6 +239,27 @@ abstract class Wrap implements GeneralWrap { return 0; } + Wrap wrapIndexToWrap(long wi) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += s.length(); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int len = w.wrapped().length(); + if ((wi - before) <= len) { + //System.err.printf("Defer to wrap %s - wi: %d. before; %d -- %s >>> %s\n", + // w, wi, before, w.debugPos(wi - before), w.wrapped()); + return w; + } + before += len; + } + } + return w; + } + @Override public int wrapIndexToSnippetIndex(int wi) { int before = 0; @@ -286,6 +309,25 @@ abstract class Wrap implements GeneralWrap { return 0; } + Wrap wrapLineToWrap(int wline) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += countLines(s); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int lns = countLines(w.wrapped()); + if ((wline - before) < lns) { + return w; + } + before += lns; + } + } + return w; + } + @Override public int wrapLineToSnippetLine(int wline) { int before = 0; @@ -315,7 +357,10 @@ abstract class Wrap implements GeneralWrap { return snlineLast; } - + @Override + public String toString() { + return "CompoundWrap(" + Arrays.stream(os).map(u -> u.toString()).collect(joining(",")) + ")"; + } } private static class RangeWrap extends Wrap { @@ -404,6 +449,10 @@ abstract class Wrap implements GeneralWrap { return lastSnline; } + @Override + public String toString() { + return "RangeWrap(" + range + ")"; + } } private static class NoWrap extends RangeWrap { diff --git a/langtools/test/jdk/jshell/ClassesTest.java b/langtools/test/jdk/jshell/ClassesTest.java index 058714fe438..a0848f12f1c 100644 --- a/langtools/test/jdk/jshell/ClassesTest.java +++ b/langtools/test/jdk/jshell/ClassesTest.java @@ -47,6 +47,7 @@ import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; import static jdk.jshell.Snippet.Status.OVERWRITTEN; +import static jdk.jshell.Snippet.Status.NONEXISTENT; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -83,7 +84,7 @@ public class ClassesTest extends KullaTesting { TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + ste(c1, NONEXISTENT, RECOVERABLE_DEFINED, true, null))); assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); @@ -176,6 +177,7 @@ public class ClassesTest extends KullaTesting { assertActiveKeys(); } + //8154496: test3 update: sig change should false public void classesRedeclaration3() { Snippet a = classKey(assertEval("class A { }")); assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); @@ -190,7 +192,7 @@ public class ClassesTest extends KullaTesting { ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(test1, VALID, VALID, true, MAIN_SNIPPET), ste(test2, VALID, VALID, true, MAIN_SNIPPET), - ste(test3, VALID, VALID, false, MAIN_SNIPPET), + ste(test3, VALID, VALID, true, MAIN_SNIPPET), ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A")); assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test")); @@ -201,8 +203,7 @@ public class ClassesTest extends KullaTesting { Snippet b = classKey(assertEval("class B extends A { }", added(RECOVERABLE_NOT_DEFINED))); Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, - added(RECOVERABLE_NOT_DEFINED), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET))); + added(REJECTED))); /*** assertDeclareFail("class A extends B { }", "****", added(REJECTED), diff --git a/langtools/test/jdk/jshell/DropTest.java b/langtools/test/jdk/jshell/DropTest.java index 04e9fb2a4e5..d00003f4b98 100644 --- a/langtools/test/jdk/jshell/DropTest.java +++ b/langtools/test/jdk/jshell/DropTest.java @@ -57,10 +57,10 @@ public class DropTest extends KullaTesting { assertActiveKeys(); method = methodKey(assertEval("int mu() { return x * 4; }", - ste(MAIN_SNIPPET, DROPPED, RECOVERABLE_DEFINED, true, null), + added(RECOVERABLE_DEFINED), ste(clazz, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); assertEval("int x = 10;", "10", - ste(MAIN_SNIPPET, DROPPED, VALID, true, null), + added(VALID), ste(method, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)); PersistentSnippet c0 = varKey(assertEval("C c0 = new C();")); assertEval("c0.v();", "\"#40\""); @@ -189,12 +189,11 @@ public class DropTest extends KullaTesting { assertDrop(c, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null), - ste(d, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, c)); + ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); assertEval("interface A {}", null, null, - DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(a, DROPPED, VALID, true, null), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET)); + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + added(VALID)); assertClasses(); assertActiveKeys(); } diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index 0ea4a622499..7c4224a27db 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -651,7 +651,7 @@ public class KullaTesting { DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates); SnippetEvent e = events.get(0); List diagnostics = getState().diagnostics(e.snippet()); - assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); + if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); return e.snippet(); } diff --git a/langtools/test/jdk/jshell/MethodsTest.java b/langtools/test/jdk/jshell/MethodsTest.java index a5ffcd383ba..6d0c3f4b4f9 100644 --- a/langtools/test/jdk/jshell/MethodsTest.java +++ b/langtools/test/jdk/jshell/MethodsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ public class MethodsTest extends KullaTesting { MethodSnippet m1 = (MethodSnippet) assertDeclareFail("void f() { return g(); }", "compiler.err.prob.found.req"); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); MethodSnippet m2 = methodKey(assertEval("int f() { return g(); }", - ste(m1, REJECTED, RECOVERABLE_DEFINED, true, null))); + added(RECOVERABLE_DEFINED))); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); assertMethodDeclSnippet(m2, "f", "()int", RECOVERABLE_DEFINED, 1, 0); } @@ -115,6 +115,26 @@ public class MethodsTest extends KullaTesting { assertActiveKeys(); } + /*** + public void methodOverloadDependent() { + assertEval("String m(String s) { return s + s; }"); + assertEval("String m(double d) { return m(\"#\" + d); }"); + assertEval("String m(int x) { return m(2.25 * x); }"); + assertEval("String m() { return m(3); }"); + assertMethods( + method("(String)String", "m"), + method("(double)String", "m"), + method("(int)String", "m"), + method("()String", "m") + ); + assertEval("m();", "\"#6.75#6.75\""); + assertEval("m(2);", "\"#4.5#4.5\""); + assertEval("m(3.14);", "\"#3.14#3.14\""); + assertEval("m(\"hi\");", "\"hihi\""); + assertActiveKeys(); + } + ***/ + public void methodsRedeclaration1() { Snippet x = methodKey(assertEval("int x() { return 10; }")); Snippet y = methodKey(assertEval("String y() { return \"\"; }")); @@ -149,8 +169,7 @@ public class MethodsTest extends KullaTesting { assertEval("double b() { return 3.14159; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertMethods(method("()int", "a"), method("()double", "b"), method("()double", "c")); assertEval("c();", "3.14159"); assertActiveKeys(); @@ -202,7 +221,7 @@ public class MethodsTest extends KullaTesting { assertActiveKeys(); assertDeclareFail("int f() {}", "compiler.err.missing.ret.stmt", - ste(MAIN_SNIPPET, REJECTED, REJECTED, false, null)); + added(REJECTED)); assertNumberOfActiveMethods(0); assertActiveKeys(); diff --git a/langtools/test/jdk/jshell/ReplaceTest.java b/langtools/test/jdk/jshell/ReplaceTest.java index 60807c09601..b631c4958c9 100644 --- a/langtools/test/jdk/jshell/ReplaceTest.java +++ b/langtools/test/jdk/jshell/ReplaceTest.java @@ -97,8 +97,7 @@ public class ReplaceTest extends KullaTesting { assertEval("mu() == 0.0;", "true"); assertEval("double x = 2.5;", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(musn, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection meths = getState().methods(); assertEquals(meths.size(), 1); assertTrue(musn == meths.iterator().next(), "Identity must not change"); @@ -115,8 +114,7 @@ public class ReplaceTest extends KullaTesting { assertEval("d();", "1060.0"); assertEval("int a() { return 5; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(b, VALID, VALID, false, MAIN_SNIPPET)); + ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("d();", "1150.0"); assertActiveKeys(); } @@ -127,8 +125,7 @@ public class ReplaceTest extends KullaTesting { assertEval("m();", "7"); assertEval("class C { int x = 99; int f() { return x; } }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(m, VALID, VALID, false, MAIN_SNIPPET)); + ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("m();", "99"); assertActiveKeys(); } @@ -140,8 +137,7 @@ public class ReplaceTest extends KullaTesting { assertEval("new A().a == 0.0;", "true"); assertEval("double x = 2.5;", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection classes = getState().types(); assertEquals(classes.size(), 1); assertTrue(c == classes.iterator().next(), "Identity must not change"); @@ -157,8 +153,7 @@ public class ReplaceTest extends KullaTesting { assertEval("new A().a == 0.0;", "true"); assertEval("double x() { return 2.5; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("x();", "2.5"); Collection classes = getState().types(); assertEquals(classes.size(), 1); @@ -875,18 +870,15 @@ public class ReplaceTest extends KullaTesting { MethodSnippet k1 = methodKey(assertEval(ms1, added(VALID))); VarSnippet xd = varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k1, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); MethodSnippet k2 = methodKey(assertEval(ms2, ste(MAIN_SNIPPET, VALID, VALID, true, null), //TODO: technically, should be false ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); VarSnippet xi2 = varKey(assertEval(xsi, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); } } diff --git a/langtools/test/jdk/jshell/SnippetStatusListenerTest.java b/langtools/test/jdk/jshell/SnippetStatusListenerTest.java index 715b350a617..14ea0b956a7 100644 --- a/langtools/test/jdk/jshell/SnippetStatusListenerTest.java +++ b/langtools/test/jdk/jshell/SnippetStatusListenerTest.java @@ -65,7 +65,7 @@ public class SnippetStatusListenerTest extends KullaTesting { getState().unsubscribe(subscription1); assertDrop(f, DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, ste(f, REJECTED, DROPPED, false, null)); - assertEval("void f() { }", ste(MAIN_SNIPPET, DROPPED, VALID, true, null)); + assertEval("void f() { }", added(VALID)); assertEvalException("throw new RuntimeException();"); assertEquals(listener1.getEvents(), events1, "Checking that unsubscribed listener does not get events"); diff --git a/langtools/test/jdk/jshell/SnippetTest.java b/langtools/test/jdk/jshell/SnippetTest.java index e3176c0b6c8..f9518ba0aee 100644 --- a/langtools/test/jdk/jshell/SnippetTest.java +++ b/langtools/test/jdk/jshell/SnippetTest.java @@ -142,8 +142,7 @@ public class SnippetTest extends KullaTesting { assertActiveKeys(); assertEval("double f() { return 0.0; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(g, VALID, VALID, false, MAIN_SNIPPET)); + ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertKeys(method("()void", "g"), clazz(KullaTesting.ClassType.INTERFACE, "A"), method("()double", "f")); assertActiveKeys(); diff --git a/langtools/test/jdk/jshell/VariablesTest.java b/langtools/test/jdk/jshell/VariablesTest.java index 3a374a0b52c..35eda77cdcc 100644 --- a/langtools/test/jdk/jshell/VariablesTest.java +++ b/langtools/test/jdk/jshell/VariablesTest.java @@ -83,7 +83,7 @@ public class VariablesTest extends KullaTesting { public void testVarValue2() { VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); badVarValue(v1); - VarSnippet v2 = varKey(assertEval("int a = 0;", ste(v1, REJECTED, VALID, true, null))); + VarSnippet v2 = varKey(assertEval("int a = 0;", added(VALID))); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); badVarValue(v2); } @@ -111,7 +111,7 @@ public class VariablesTest extends KullaTesting { VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); assertVariableDeclSnippet(v1, "a", "int", REJECTED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 1); VarSnippet v2 = varKey(assertEval("int a = 0;", - ste(v1, REJECTED, VALID, true, null))); + added(VALID))); assertVariableDeclSnippet(v2, "a", "int", VALID, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); assertVariableDeclSnippet(v2, "a", "int", DROPPED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0); From 3a647e6b88a3c4fb200b5ddafebfb2c6b52eb571 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:36:12 +0200 Subject: [PATCH 113/113] Added tag jdk-9+115 for changeset 8d78fb40648d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0eced0f9e0d..3aec595d887 100644 --- a/.hgtags +++ b/.hgtags @@ -357,3 +357,4 @@ a6614ff7bf09da74be1d0ef3d9755090d244697a jdk-9+111 7359994942f8d8e723b584d66a3a92c2e9e95e5c jdk-9+112 6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 +8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115