# HG changeset patch # User amurillo # Date 1397776147 25200 # Node ID b6a2ba7d3ea7259a76c8ff1ec22fac9094494c1c # Parent 70dc2c030c69470a5d9099b7f54e4cfef89276fd# Parent cfde111a2f2035399d094432d68173e41dfa0f7e Merge diff -r 70dc2c030c69 -r b6a2ba7d3ea7 make/hotspot_version --- a/make/hotspot_version Wed Apr 16 12:32:23 2014 -0700 +++ b/make/hotspot_version Thu Apr 17 16:09:07 2014 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=20 -HS_BUILD_NUMBER=10 +HS_BUILD_NUMBER=11 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 70dc2c030c69 -r b6a2ba7d3ea7 make/jprt.properties --- a/make/jprt.properties Wed Apr 16 12:32:23 2014 -0700 +++ b/make/jprt.properties Thu Apr 17 16:09:07 2014 -0700 @@ -77,11 +77,6 @@ jprt.my.linux.ppcv2.jdk7u8=${jprt.my.linux.ppcv2.jdk7} jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}} -jprt.my.linux.ppcsflt.jdk8u20=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.jdk7u8=${jprt.my.linux.ppcsflt.jdk7} -jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}} - jprt.my.linux.armvfpsflt.jdk8u20=linux_armvfpsflt_2.6 jprt.my.linux.armvfpsflt=${jprt.my.linux.armvfpsflt.${jprt.tools.default.release}} @@ -135,7 +130,6 @@ ${jprt.my.linux.i586}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppc}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppcv2}-{productEmb|fastdebugEmb}, \ - ${jprt.my.linux.ppcsflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armvfpsflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armvfphflt}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.armsflt}-{productEmb|fastdebugEmb} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/cpu/sparc/vm/assembler_sparc.hpp --- a/src/cpu/sparc/vm/assembler_sparc.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -630,11 +630,20 @@ } protected: + // Insert a nop if the previous is cbcond + void insert_nop_after_cbcond() { + if (UseCBCond && cbcond_before()) { + nop(); + } + } // Delay slot helpers // cti is called when emitting control-transfer instruction, // BEFORE doing the emitting. // Only effective when assertion-checking is enabled. void cti() { + // A cbcond instruction immediately followed by a CTI + // instruction introduces pipeline stalls, we need to avoid that. + no_cbcond_before(); #ifdef CHECK_DELAY assert_not_delayed("cti should not be in delay slot"); #endif @@ -658,7 +667,6 @@ void no_cbcond_before() { assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond"); } - public: bool use_cbcond(Label& L) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/cpu/sparc/vm/assembler_sparc.inline.hpp --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -54,33 +54,33 @@ inline void Assembler::add(Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); } +inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } +inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { insert_nop_after_cbcond(); bpr( c, a, p, s1, target(L)); } -inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::fb( Condition c, bool a, Label& L ) { fb(c, a, target(L)); } +inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } +inline void Assembler::fb( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); fb(c, a, target(L)); } -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { fbp(c, a, cc, p, target(L)); } +inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } +inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); fbp(c, a, cc, p, target(L)); } -inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::br( Condition c, bool a, Label& L ) { br(c, a, target(L)); } +inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } +inline void Assembler::br( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); br(c, a, target(L)); } -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { bp(c, a, cc, p, target(L)); } +inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } +inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); bp(c, a, cc, p, target(L)); } // compare and branch inline void Assembler::cbcond(Condition c, CC cc, Register s1, Register s2, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | rs2(s2)); } inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | immed(true) | simm(simm5, 5)); } -inline void Assembler::call( address d, relocInfo::relocType rt ) { cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } -inline void Assembler::call( Label& L, relocInfo::relocType rt ) { call( target(L), rt); } +inline void Assembler::call( address d, relocInfo::relocType rt ) { insert_nop_after_cbcond(); cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } +inline void Assembler::call( Label& L, relocInfo::relocType rt ) { insert_nop_after_cbcond(); call( target(L), rt); } inline void Assembler::flush( Register s1, Register s2) { emit_int32( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); } inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::jmpl( Register s1, Register s2, Register d ) { cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } -inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } +inline void Assembler::jmpl( Register s1, Register s2, Register d ) { insert_nop_after_cbcond(); cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } +inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { insert_nop_after_cbcond(); cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp --- a/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -233,6 +233,7 @@ } inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); br(c, a, p, target(L)); } @@ -248,6 +249,7 @@ } inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); brx(c, a, p, target(L)); } @@ -269,6 +271,7 @@ } inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { + insert_nop_after_cbcond(); fb(c, a, p, target(L)); } @@ -318,6 +321,7 @@ } inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { + insert_nop_after_cbcond(); MacroAssembler::call( target(L), rt); } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Wed Apr 16 12:32:23 2014 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Thu Apr 17 16:09:07 2014 -0700 @@ -1268,7 +1268,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { Compile* C = ra_->C; - if( do_polling() && ra_->C->is_method_compilation() ) { + if(do_polling() && ra_->C->is_method_compilation()) { st->print("SETHI #PollAddr,L0\t! Load Polling address\n\t"); #ifdef _LP64 st->print("LDX [L0],G0\t!Poll for Safepointing\n\t"); @@ -1277,8 +1277,12 @@ #endif } - if( do_polling() ) + if(do_polling()) { + if (UseCBCond && !ra_->C->is_method_compilation()) { + st->print("NOP\n\t"); + } st->print("RET\n\t"); + } st->print("RESTORE"); } @@ -1291,15 +1295,20 @@ __ verify_thread(); // If this does safepoint polling, then do it here - if( do_polling() && ra_->C->is_method_compilation() ) { + if(do_polling() && ra_->C->is_method_compilation()) { AddressLiteral polling_page(os::get_polling_page()); __ sethi(polling_page, L0); __ relocate(relocInfo::poll_return_type); - __ ld_ptr( L0, 0, G0 ); + __ ld_ptr(L0, 0, G0); } // If this is a return, then stuff the restore in the delay slot - if( do_polling() ) { + if(do_polling()) { + if (UseCBCond && !ra_->C->is_method_compilation()) { + // Insert extra padding for the case when the epilogue is preceded by + // a cbcond jump, which can't be followed by a CTI instruction + __ nop(); + } __ ret(); __ delayed()->restore(); } else { @@ -3330,7 +3339,18 @@ //----------Instruction Attributes--------------------------------------------- ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute ins_attrib ins_size(32); // Required size attribute (in bits) -ins_attrib ins_avoid_back_to_back(0); // instruction should not be generated back to back + +// avoid_back_to_back attribute is an expression that must return +// one of the following values defined in MachNode: +// AVOID_NONE - instruction can be placed anywhere +// AVOID_BEFORE - instruction cannot be placed after an +// instruction with MachNode::AVOID_AFTER +// AVOID_AFTER - the next instruction cannot be the one +// with MachNode::AVOID_BEFORE +// AVOID_BEFORE_AND_AFTER - BEFORE and AFTER attributes at +// the same time +ins_attrib ins_avoid_back_to_back(MachNode::AVOID_NONE); + ins_attrib ins_short_branch(0); // Required flag: is this instruction a // non-matching short branch variant of some // long branch? @@ -6630,6 +6650,7 @@ ins_encode %{ __ encode_heap_oop($src$$Register, $dst$$Register); %} + ins_avoid_back_to_back(Universe::narrow_oop_base() == NULL ? AVOID_NONE : AVOID_BEFORE); ins_pipe(ialu_reg); %} @@ -9199,6 +9220,7 @@ __ ba(*L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br); %} @@ -9217,7 +9239,7 @@ __ ba_short(*L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9231,6 +9253,7 @@ format %{ "BP$cmp $icc,$labl" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9242,6 +9265,7 @@ format %{ "BP$cmp $icc,$labl" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9260,6 +9284,7 @@ __ bp( (Assembler::Condition)($cmp$$cmpcode), false, Assembler::ptr_cc, predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9278,6 +9303,7 @@ __ fbp( (Assembler::Condition)($cmp$$cmpcode), false, (Assembler::CC)($fcc$$reg), predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_fcc); %} @@ -9290,6 +9316,7 @@ format %{ "BP$cmp $icc,$labl\t! Loop end" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9302,6 +9329,7 @@ format %{ "BP$cmp $icc,$labl\t! Loop end" %} // Prim = bits 24-22, Secnd = bits 31-30 ins_encode( enc_bp( labl, cmp, icc ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9552,7 +9580,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9570,7 +9598,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9588,7 +9616,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9606,7 +9634,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9624,7 +9652,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9642,7 +9670,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9665,7 +9693,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9687,7 +9715,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, G0, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9705,7 +9733,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9723,7 +9751,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, G0, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9742,7 +9770,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_reg); %} @@ -9760,7 +9788,7 @@ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L); %} ins_short_branch(1); - ins_avoid_back_to_back(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); ins_pipe(cbcond_reg_imm); %} @@ -9777,6 +9805,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9789,6 +9818,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9801,6 +9831,7 @@ ins_cost(BRANCH_COST); format %{ "BR$cmp $op1,$labl" %} ins_encode( enc_bpr( labl, cmp, op1 ) ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_reg); %} @@ -9841,6 +9872,7 @@ __ bp( (Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); __ delayed()->nop(); %} + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(br_cc); %} @@ -9968,6 +10000,7 @@ ins_cost(CALL_COST); format %{ "CALL,static ; NOP ==> " %} ins_encode( Java_Static_Call( meth ), call_epilog ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10004,6 +10037,7 @@ format %{ "CALL,runtime" %} ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10016,6 +10050,7 @@ ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10028,6 +10063,7 @@ ins_encode( Java_To_Runtime( meth ), call_epilog, adjust_long_from_native_call ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(simple_call); %} @@ -10041,6 +10077,7 @@ ins_cost(CALL_COST); format %{ "Jmp $jump_target ; NOP \t! $method_oop holds method oop" %} ins_encode(form_jmpl(jump_target)); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10072,6 +10109,7 @@ // opcode(Assembler::jmpl_op3, Assembler::arith_op); // The hack duplicates the exception oop into G3, so that CreateEx can use it there. // ins_encode( form3_rs1_simm13_rd( jump_target, 0x00, R_G0 ), move_return_pc_to_o1() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10102,6 +10140,7 @@ // use the following format syntax format %{ "Jmp rethrow_stub" %} ins_encode(enc_rethrow); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(tail_call); %} @@ -10130,6 +10169,7 @@ ins_cost(DEFAULT_COST*10); format %{ "CALL PartialSubtypeCheck\n\tNOP" %} ins_encode( enc_PartialSubtypeCheck() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(partial_subtype_check_pipe); %} @@ -10139,6 +10179,7 @@ ins_cost(DEFAULT_COST*10); format %{ "CALL PartialSubtypeCheck\n\tNOP\t# (sets condition codes)" %} ins_encode( enc_PartialSubtypeCheck() ); + ins_avoid_back_to_back(AVOID_BEFORE); ins_pipe(partial_subtype_check_pipe); %} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/adlc/output_h.cpp --- a/src/share/vm/adlc/output_h.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/adlc/output_h.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1613,21 +1613,20 @@ // Each instruction attribute results in a virtual call of same name. // The ins_cost is not handled here. Attribute *attr = instr->_attribs; - bool avoid_back_to_back = false; + Attribute *avoid_back_to_back_attr = NULL; while (attr != NULL) { - if (strcmp (attr->_ident, "ins_cost") != 0 && + if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) { + fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val); + } else if (strcmp (attr->_ident, "ins_cost") != 0 && strncmp(attr->_ident, "ins_field_", 10) != 0 && // Must match function in node.hpp: return type bool, no prefix "ins_". strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") != 0 && strcmp (attr->_ident, "ins_short_branch") != 0) { fprintf(fp, " virtual int %s() const { return %s; }\n", attr->_ident, attr->_val); } - // Check value for ins_avoid_back_to_back, and if it is true (1), set the flag - if (!strcmp(attr->_ident, "ins_avoid_back_to_back") != 0 && attr->int_val(*this) != 0) - avoid_back_to_back = true; - if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) - fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val); - + if (strcmp(attr->_ident, "ins_avoid_back_to_back") == 0) { + avoid_back_to_back_attr = attr; + } attr = (Attribute *)attr->_next; } @@ -1799,11 +1798,11 @@ } // flag: if this instruction should not be generated back to back. - if ( avoid_back_to_back ) { - if ( node_flags_set ) { - fprintf(fp," | Flag_avoid_back_to_back"); + if (avoid_back_to_back_attr != NULL) { + if (node_flags_set) { + fprintf(fp," | (%s)", avoid_back_to_back_attr->_val); } else { - fprintf(fp,"init_flags(Flag_avoid_back_to_back"); + fprintf(fp,"init_flags((%s)", avoid_back_to_back_attr->_val); node_flags_set = true; } } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -3751,18 +3751,24 @@ Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), - "Unsupported major.minor version %u.%u", + "Unsupported class file version %u.%u, " + "this version of the Java Runtime only recognizes class file versions up to %u.%u", major_version, - minor_version); + minor_version, + JAVA_MAX_SUPPORTED_VERSION, + JAVA_MAX_SUPPORTED_MINOR_VERSION); } else { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), - "%s : Unsupported major.minor version %u.%u", + "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), " + "this version of the Java Runtime only recognizes class file versions up to %u.%u", name->as_C_string(), major_version, - minor_version); + minor_version, + JAVA_MAX_SUPPORTED_VERSION, + JAVA_MAX_SUPPORTED_MINOR_VERSION); } return nullHandle; } @@ -4175,8 +4181,12 @@ clear_class_metadata(); - // deallocate the klass if already created. - MetadataFactory::free_metadata(_loader_data, _klass); + // deallocate the klass if already created. Don't directly deallocate, but add + // to the deallocate list so that the klass is removed from the CLD::_klasses list + // at a safepoint. + if (_klass != NULL) { + _loader_data->add_to_deallocate_list(_klass); + } _klass = NULL; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/defaultMethods.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -390,20 +390,6 @@ Symbol* get_exception_message() { return _exception_message; } Symbol* get_exception_name() { return _exception_name; } - // Return true if the specified klass has a static method that matches - // the name and signature of the target method. - bool has_matching_static(InstanceKlass* root) { - if (_members.length() > 0) { - Pair entry = _members.at(0); - Method* impl = root->find_method(entry.first->name(), - entry.first->signature()); - if ((impl != NULL) && impl->is_static()) { - return true; - } - } - return false; - } - // Either sets the target or the exception error message void determine_target(InstanceKlass* root, TRAPS) { if (has_target() || throws_exception()) { @@ -433,21 +419,19 @@ // If the root klass has a static method with matching name and signature // then do not generate an overpass method because it will hide the // static method during resolution. - if (!has_matching_static(root)) { - if (qualified_methods.length() == 0) { - _exception_message = generate_no_defaults_message(CHECK); - } else { - assert(root != NULL, "Null root class"); - _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); - } - _exception_name = vmSymbols::java_lang_AbstractMethodError(); + if (qualified_methods.length() == 0) { + _exception_message = generate_no_defaults_message(CHECK); + } else { + assert(root != NULL, "Null root class"); + _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); } + _exception_name = vmSymbols::java_lang_AbstractMethodError(); // If only one qualified method is default, select that } else if (num_defaults == 1) { _selected_target = qualified_methods.at(default_index); - } else if (num_defaults > 1 && !has_matching_static(root)) { + } else if (num_defaults > 1) { _exception_message = generate_conflicts_message(&qualified_methods,CHECK); _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); if (TraceDefaultMethods) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -482,8 +482,8 @@ } } -static void initialize_static_field(fieldDescriptor* fd, TRAPS) { - Handle mirror (THREAD, fd->field_holder()->java_mirror()); + +static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) { assert(mirror.not_null() && fd->is_static(), "just checking"); if (fd->has_initial_value()) { BasicType t = fd->field_type(); @@ -550,21 +550,45 @@ create_mirror(k, Handle(NULL), CHECK); } -oop java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) { +void java_lang_Class::initialize_mirror_fields(KlassHandle k, + Handle mirror, + Handle protection_domain, + TRAPS) { + // Allocate a simple java object for a lock. + // This needs to be a java object because during class initialization + // it can be held across a java call. + typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK); + set_init_lock(mirror(), r); + + // Set protection domain also + set_protection_domain(mirror(), protection_domain()); + + // Initialize static fields + InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK); +} + +void java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) { assert(k->java_mirror() == NULL, "should only assign mirror once"); // Use this moment of initialization to cache modifier_flags also, // to support Class.getModifiers(). Instance classes recalculate // the cached flags after the class file is parsed, but before the // class is put into the system dictionary. - int computed_modifiers = k->compute_modifier_flags(CHECK_0); + int computed_modifiers = k->compute_modifier_flags(CHECK); k->set_modifier_flags(computed_modifiers); // Class_klass has to be loaded because it is used to allocate // the mirror. if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) - Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); + Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK); + + // Setup indirection from mirror->klass + if (!k.is_null()) { + java_lang_Class::set_klass(mirror(), k()); + } InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); + assert(oop_size(mirror()) == mk->instance_size(k), "should have been set"); + java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); // It might also have a component mirror. This mirror must already exist. @@ -577,29 +601,32 @@ assert(k->oop_is_objArray(), "Must be"); Klass* element_klass = ObjArrayKlass::cast(k())->element_klass(); assert(element_klass != NULL, "Must have an element klass"); - comp_mirror = element_klass->java_mirror(); + comp_mirror = element_klass->java_mirror(); } assert(comp_mirror.not_null(), "must have a mirror"); - // Two-way link between the array klass and its component mirror: + // Two-way link between the array klass and its component mirror: ArrayKlass::cast(k())->set_component_mirror(comp_mirror()); set_array_klass(comp_mirror(), k()); } else { assert(k->oop_is_instance(), "Must be"); - // Allocate a simple java object for a lock. - // This needs to be a java object because during class initialization - // it can be held across a java call. - typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_NULL); - set_init_lock(mirror(), r); - - // Set protection domain also - set_protection_domain(mirror(), protection_domain()); - - // Initialize static fields - InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL); + initialize_mirror_fields(k, mirror, protection_domain, THREAD); + if (HAS_PENDING_EXCEPTION) { + // If any of the fields throws an exception like OOM remove the klass field + // from the mirror so GC doesn't follow it after the klass has been deallocated. + // This mirror looks like a primitive type, which logically it is because it + // it represents no class. + java_lang_Class::set_klass(mirror(), NULL); + return; + } } - return mirror(); + + // Setup indirection from klass->mirror last + // after any exceptions can happen during allocations. + if (!k.is_null()) { + k->set_java_mirror(mirror()); + } } else { if (fixup_mirror_list() == NULL) { GrowableArray* list = @@ -607,12 +634,10 @@ set_fixup_mirror_list(list); } fixup_mirror_list()->push(k()); - return NULL; } } - int java_lang_Class::oop_size(oop java_class) { assert(_oop_size_offset != 0, "must be set"); return java_class->int_field(_oop_size_offset); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -246,11 +246,12 @@ static void set_init_lock(oop java_class, oop init_lock); static void set_protection_domain(oop java_class, oop protection_domain); + static void initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS); public: static void compute_offsets(); // Instance creation - static oop create_mirror(KlassHandle k, Handle protection_domain, TRAPS); + static void create_mirror(KlassHandle k, Handle protection_domain, TRAPS); static void fixup_mirror(KlassHandle k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); // Conversion diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -826,47 +826,6 @@ } } // load_instance_class loop - if (HAS_PENDING_EXCEPTION) { - // An exception, such as OOM could have happened at various places inside - // load_instance_class. We might have partially initialized a shared class - // and need to clean it up. - if (class_loader.is_null()) { - // In some cases k may be null. Let's find the shared class again. - instanceKlassHandle ik(THREAD, find_shared_class(name)); - if (ik.not_null()) { - if (ik->class_loader_data() == NULL) { - // We didn't go as far as Klass::restore_unshareable_info(), - // so nothing to clean up. - } else { - Klass *kk; - { - MutexLocker mu(SystemDictionary_lock, THREAD); - kk = find_class(d_index, d_hash, name, ik->class_loader_data()); - } - if (kk != NULL) { - // No clean up is needed if the shared class has been entered - // into system dictionary, as load_shared_class() won't be called - // again. - } else { - // This must be done outside of the SystemDictionary_lock to - // avoid deadlock. - // - // Note that Klass::restore_unshareable_info (called via - // load_instance_class above) is also called outside - // of SystemDictionary_lock. Other threads are blocked from - // loading this class because they are waiting on the - // SystemDictionary_lock until this thread removes - // the placeholder below. - // - // This need to be re-thought when parallel-capable non-boot - // classloaders are supported by CDS (today they're not). - clean_up_shared_class(ik, class_loader, THREAD); - } - } - } - } - } - if (load_instance_added == true) { // clean up placeholder entries for LOAD_INSTANCE success or error // This brackets the SystemDictionary updates for both defining @@ -1272,19 +1231,6 @@ return ik; } -void SystemDictionary::clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS) { - // Updating methods must be done under a lock so multiple - // threads don't update these in parallel - // Shared classes are all currently loaded by the bootstrap - // classloader, so this will never cause a deadlock on - // a custom class loader lock. - { - Handle lockObject = compute_loader_lock_object(class_loader, THREAD); - check_loader_lock_contention(lockObject, THREAD); - ObjectLocker ol(lockObject, THREAD, true); - ik->remove_unshareable_info(); - } -} instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -617,7 +617,6 @@ Handle class_loader, TRAPS); static instanceKlassHandle load_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS); - static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS); static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/verificationType.hpp --- a/src/share/vm/classfile/verificationType.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/verificationType.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -299,7 +299,7 @@ int dimensions() const { assert(is_array(), "Must be an array"); int index = 0; - while (name()->byte_at(index++) == '['); + while (name()->byte_at(index) == '[') index++; return index; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/classfile/verifier.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -1943,7 +1943,7 @@ InstanceKlass* target_instance = InstanceKlass::cast(target_class); fieldDescriptor fd; if (is_method) { - Method* m = target_instance->uncached_lookup_method(field_name, field_sig); + Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::normal); if (m != NULL && m->is_protected()) { if (!this_class->is_same_class_package(m->method_holder())) { return true; @@ -2280,7 +2280,8 @@ ref_class_type.name(), CHECK_VERIFY(this)); Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method( vmSymbols::object_initializer_name(), - cp->signature_ref_at(bcs->get_index_u2())); + cp->signature_ref_at(bcs->get_index_u2()), + Klass::normal); instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/code/debugInfo.hpp --- a/src/share/vm/code/debugInfo.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/code/debugInfo.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -273,8 +273,8 @@ } Method* read_method() { Method* o = (Method*)(code()->metadata_at(read_int())); - assert(o == NULL || - o->is_metaspace_object(), "meta data only"); + // is_metadata() is a faster check than is_metaspace_object() + assert(o == NULL || o->is_metadata(), "meta data only"); return o; } ScopeValue* read_object_value(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1288,7 +1288,7 @@ print_heap_before_gc(); trace_heap_before_gc(gc_tracer); - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); verify_region_sets_optional(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1204,7 +1204,7 @@ (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; if (full) { - _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes(); + _metaspace_used_bytes_before_gc = MetaspaceAux::used_bytes(); } } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -184,7 +184,7 @@ size_t prev_used = heap->used(); // Capture metadata size before collection for sizing. - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); // For PrintGCDetails size_t old_gen_prev_used = old_gen->used_in_bytes(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -927,7 +927,7 @@ _heap_used = heap->used(); _young_gen_used = heap->young_gen()->used_in_bytes(); _old_gen_used = heap->old_gen()->used_in_bytes(); - _metadata_used = MetaspaceAux::allocated_used_bytes(); + _metadata_used = MetaspaceAux::used_bytes(); }; size_t heap_used() const { return _heap_used; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/shared/gcHeapSummary.hpp --- a/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -62,16 +62,16 @@ }; class MetaspaceSizes : public StackObj { - size_t _capacity; + size_t _committed; size_t _used; size_t _reserved; public: - MetaspaceSizes() : _capacity(0), _used(0), _reserved(0) {} - MetaspaceSizes(size_t capacity, size_t used, size_t reserved) : - _capacity(capacity), _used(used), _reserved(reserved) {} + MetaspaceSizes() : _committed(0), _used(0), _reserved(0) {} + MetaspaceSizes(size_t committed, size_t used, size_t reserved) : + _committed(committed), _used(used), _reserved(reserved) {} - size_t capacity() const { return _capacity; } + size_t committed() const { return _committed; } size_t used() const { return _used; } size_t reserved() const { return _reserved; } }; diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -258,7 +258,7 @@ static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) { TraceStructMetaspaceSizes meta_sizes; - meta_sizes.set_capacity(sizes.capacity()); + meta_sizes.set_committed(sizes.committed()); meta_sizes.set_used(sizes.used()); meta_sizes.set_reserved(sizes.reserved()); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -103,6 +103,15 @@ assert(((_gc_cause != GCCause::_no_gc) && (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); + // To be able to handle a GC the VM initialization needs to be completed. + if (!is_init_completed()) { + vm_exit_during_initialization( + err_msg("GC triggered before VM initialization completed. Try increasing " + "NewSize, current value " UINTX_FORMAT "%s.", + byte_size_in_proper_unit(NewSize), + proper_unit_for_byte_size(NewSize))); + } + acquire_pending_list_lock(); // If the GC count has changed someone beat us to the collection // Get the Heap_lock after the pending_list_lock. diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -85,16 +85,16 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { const MetaspaceSizes meta_space( - MetaspaceAux::allocated_capacity_bytes(), - MetaspaceAux::allocated_used_bytes(), + MetaspaceAux::committed_bytes(), + MetaspaceAux::used_bytes(), MetaspaceAux::reserved_bytes()); const MetaspaceSizes data_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType), + MetaspaceAux::committed_bytes(Metaspace::NonClassType), + MetaspaceAux::used_bytes(Metaspace::NonClassType), MetaspaceAux::reserved_bytes(Metaspace::NonClassType)); const MetaspaceSizes class_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), + MetaspaceAux::committed_bytes(Metaspace::ClassType), + MetaspaceAux::used_bytes(Metaspace::ClassType), MetaspaceAux::reserved_bytes(Metaspace::ClassType)); const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary = @@ -582,36 +582,6 @@ } } -oop CollectedHeap::Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS) { - debug_only(check_for_valid_allocation_state()); - assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); - assert(size >= 0, "int won't convert to size_t"); - HeapWord* obj; - assert(ScavengeRootsInCode > 0, "must be"); - obj = common_mem_allocate_init(real_klass, size, CHECK_NULL); - post_allocation_setup_common(klass, obj); - assert(Universe::is_bootstrapping() || - !((oop)obj)->is_array(), "must not be an array"); - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); - oop mirror = (oop)obj; - - java_lang_Class::set_oop_size(mirror, size); - - // Setup indirections - if (!real_klass.is_null()) { - java_lang_Class::set_klass(mirror, real_klass()); - real_klass->set_java_mirror(mirror); - } - - InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); - assert(size == mk->instance_size(real_klass), "should have been set"); - - // notify jvmti and dtrace - post_allocation_notify(klass, (oop)obj); - - return mirror; -} - /////////////// Unit tests /////////////// #ifndef PRODUCT diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -151,7 +151,7 @@ inline static void post_allocation_setup_no_klass_install(KlassHandle klass, HeapWord* objPtr); - inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj); + inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj, int size); inline static void post_allocation_setup_array(KlassHandle klass, HeapWord* obj, int length); @@ -312,9 +312,6 @@ // May be overridden to set additional parallelism. virtual void set_par_threads(uint t) { _n_par_threads = t; }; - // Allocate and initialize instances of Class - static oop Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS); - // General obj/array allocation facilities. inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/gc_interface/collectedHeap.inline.hpp --- a/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -70,7 +70,7 @@ } // Support for jvmti and dtrace -inline void post_allocation_notify(KlassHandle klass, oop obj) { +inline void post_allocation_notify(KlassHandle klass, oop obj, int size) { // support low memory notifications (no-op if not enabled) LowMemoryDetector::detect_low_memory_for_collected_pools(); @@ -80,18 +80,19 @@ if (DTraceAllocProbes) { // support for Dtrace object alloc event (no-op most of the time) if (klass() != NULL && klass()->name() != NULL) { - SharedRuntime::dtrace_object_alloc(obj); + SharedRuntime::dtrace_object_alloc(obj, size); } } } void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, - HeapWord* obj) { + HeapWord* obj, + int size) { post_allocation_setup_common(klass, obj); assert(Universe::is_bootstrapping() || !((oop)obj)->is_array(), "must not be an array"); // notify jvmti and dtrace - post_allocation_notify(klass, (oop)obj); + post_allocation_notify(klass, (oop)obj, size); } void CollectedHeap::post_allocation_setup_array(KlassHandle klass, @@ -103,9 +104,10 @@ assert(length >= 0, "length should be non-negative"); ((arrayOop)obj)->set_length(length); post_allocation_setup_common(klass, obj); - assert(((oop)obj)->is_array(), "must be an array"); + oop new_obj = (oop)obj; + assert(new_obj->is_array(), "must be an array"); // notify jvmti and dtrace (must be after length is set for dtrace) - post_allocation_notify(klass, (oop)obj); + post_allocation_notify(klass, new_obj, new_obj->size()); } HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) { @@ -199,7 +201,7 @@ assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); - post_allocation_setup_obj(klass, obj); + post_allocation_setup_obj(klass, obj, size); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); return (oop)obj; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -243,7 +243,8 @@ // Look up method in klasses, including static methods // Then look up local default methods void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature); + // Ignore overpasses so statics can be found during resolution + Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, @@ -256,6 +257,12 @@ result_oop = NULL; } + // Before considering default methods, check for an overpass in the + // current class if a method has not been found. + if (result_oop == NULL) { + result_oop = InstanceKlass::cast(klass())->find_method(name, signature); + } + if (result_oop == NULL) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { @@ -276,11 +283,11 @@ // returns first instance method // Looks up method in classes, then looks up local default methods void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature); + Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::normal); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) { KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super()); - result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature)); + result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); } if (result.is_null()) { @@ -302,7 +309,7 @@ // First check in default method array if (!resolved_method->is_abstract() && (InstanceKlass::cast(klass())->default_methods() != NULL)) { - int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature); + int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false); if (index >= 0 ) { vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); } @@ -322,7 +329,7 @@ // Specify 'true' in order to skip default methods when searching the // interfaces. Function lookup_method_in_klasses() already looked for // the method in the default methods table. - result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, true)); + result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults)); } void LinkResolver::lookup_polymorphic_method(methodHandle& result, diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/gcLocker.cpp --- a/src/share/vm/memory/gcLocker.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/gcLocker.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -28,7 +28,6 @@ #include "memory/sharedHeap.hpp" volatile jint GC_locker::_jni_lock_count = 0; -volatile jint GC_locker::_lock_count = 0; volatile bool GC_locker::_needs_gc = false; volatile bool GC_locker::_doing_gc = false; @@ -102,7 +101,7 @@ // We check that at least one thread is in a critical region before // blocking because blocked threads are woken up by a thread exiting // a JNI critical region. - while ((needs_gc() && is_jni_active()) || _doing_gc) { + while (is_active_and_needs_gc() || _doing_gc) { JNICritical_lock->wait(); } thread->enter_critical(); @@ -116,27 +115,20 @@ _jni_lock_count--; decrement_debug_jni_lock_count(); thread->exit_critical(); - if (needs_gc() && !is_jni_active()) { + if (needs_gc() && !is_active_internal()) { // We're the last thread out. Cause a GC to occur. - // GC will also check is_active, so this check is not - // strictly needed. It's added here to make it clear that - // the GC will NOT be performed if any other caller - // of GC_locker::lock() still needs GC locked. - if (!is_active_internal()) { - _doing_gc = true; - { - // Must give up the lock while at a safepoint - MutexUnlocker munlock(JNICritical_lock); - if (PrintJNIGCStalls && PrintGCDetails) { - ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", - gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); - } - Universe::heap()->collect(GCCause::_gc_locker); + _doing_gc = true; + { + // Must give up the lock while at a safepoint + MutexUnlocker munlock(JNICritical_lock); + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", + gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); } - _doing_gc = false; + Universe::heap()->collect(GCCause::_gc_locker); } - + _doing_gc = false; _needs_gc = false; JNICritical_lock->notify_all(); } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/gcLocker.hpp --- a/src/share/vm/memory/gcLocker.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/gcLocker.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -54,8 +54,6 @@ // safepointing and decremented during the slow path of GC_locker // unlocking. static volatile jint _jni_lock_count; // number of jni active instances. - - static volatile jint _lock_count; // number of other active instances static volatile bool _needs_gc; // heap is filling, we need a GC // note: bool is typedef'd as jint static volatile bool _doing_gc; // unlock_critical() is doing a GC @@ -66,12 +64,6 @@ static volatile jint _debug_jni_lock_count; #endif - // Accessors - static bool is_jni_active() { - assert(_needs_gc, "only valid when _needs_gc is set"); - return _jni_lock_count > 0; - } - // At a safepoint, visit all threads and count the number of active // critical sections. This is used to ensure that all active // critical sections are exited before a new one is started. @@ -82,7 +74,7 @@ static bool is_active_internal() { verify_critical_count(); - return _lock_count > 0 || _jni_lock_count > 0; + return _jni_lock_count > 0; } public: @@ -132,10 +124,6 @@ // not a stable predicate. static void stall_until_clear(); - // Non-structured GC locking: currently needed for JNI. Use with care! - static void lock(); - static void unlock(); - // The following two methods are used for JNI critical regions. // If we find that we failed to perform a GC because the GC_locker // was active, arrange for one as soon as possible by allowing diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/gcLocker.inline.hpp --- a/src/share/vm/memory/gcLocker.inline.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/gcLocker.inline.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -27,22 +27,6 @@ #include "memory/gcLocker.hpp" -inline void GC_locker::lock() { - // cast away volatile - Atomic::inc(&_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count++; }) - assert(Universe::heap() == NULL || - !Universe::heap()->is_gc_active(), "locking failed"); -} - -inline void GC_locker::unlock() { - // cast away volatile - Atomic::dec(&_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count--; }) -} - inline void GC_locker::lock_critical(JavaThread* thread) { if (!thread->in_critical()) { if (needs_gc()) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/genCollectedHeap.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -374,7 +374,7 @@ ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); - const size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + const size_t metadata_prev_used = MetaspaceAux::used_bytes(); print_heap_before_gc(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/metaspace.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1447,7 +1447,7 @@ uint current_shrink_factor = _shrink_factor; _shrink_factor = 0; - const size_t used_after_gc = MetaspaceAux::allocated_capacity_bytes(); + const size_t used_after_gc = MetaspaceAux::capacity_bytes(); const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC(); const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0; @@ -2537,8 +2537,8 @@ // MetaspaceAux -size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0}; -size_t MetaspaceAux::_allocated_used_words[] = {0, 0}; +size_t MetaspaceAux::_capacity_words[] = {0, 0}; +size_t MetaspaceAux::_used_words[] = {0, 0}; size_t MetaspaceAux::free_bytes(Metaspace::MetadataType mdtype) { VirtualSpaceList* list = Metaspace::get_space_list(mdtype); @@ -2551,38 +2551,38 @@ void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); - assert(words <= allocated_capacity_words(mdtype), + assert(words <= capacity_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_capacity_words(mdtype))); - _allocated_capacity_words[mdtype] -= words; + " is greater than _capacity_words[%u] " SIZE_FORMAT, + words, mdtype, capacity_words(mdtype))); + _capacity_words[mdtype] -= words; } void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); // Needs to be atomic - _allocated_capacity_words[mdtype] += words; + _capacity_words[mdtype] += words; } void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) { - assert(words <= allocated_used_words(mdtype), + assert(words <= used_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_used_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_used_words(mdtype))); + " is greater than _used_words[%u] " SIZE_FORMAT, + words, mdtype, used_words(mdtype))); // For CMS deallocation of the Metaspaces occurs during the // sweep which is a concurrent phase. Protection by the expand_lock() // is not enough since allocation is on a per Metaspace basis // and protected by the Metaspace lock. jlong minus_words = (jlong) - (jlong) words; - Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(minus_words, &_used_words[mdtype]); } void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) { - // _allocated_used_words tracks allocations for + // _used_words tracks allocations for // each piece of metadata. Those allocations are // generally done concurrently by different application // threads so must be done atomically. - Atomic::add_ptr(words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(words, &_used_words[mdtype]); } size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) { @@ -2629,16 +2629,16 @@ size_t MetaspaceAux::capacity_bytes_slow() { #ifdef PRODUCT - // Use allocated_capacity_bytes() in PRODUCT instead of this function. + // Use capacity_bytes() in PRODUCT instead of this function. guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT"); #endif size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType); size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType); - assert(allocated_capacity_bytes() == class_capacity + non_class_capacity, - err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT + assert(capacity_bytes() == class_capacity + non_class_capacity, + err_msg("bad accounting: capacity_bytes() " SIZE_FORMAT " class_capacity + non_class_capacity " SIZE_FORMAT " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT, - allocated_capacity_bytes(), class_capacity + non_class_capacity, + capacity_bytes(), class_capacity + non_class_capacity, class_capacity, non_class_capacity)); return class_capacity + non_class_capacity; @@ -2698,14 +2698,14 @@ "->" SIZE_FORMAT "(" SIZE_FORMAT ")", prev_metadata_used, - allocated_used_bytes(), + used_bytes(), reserved_bytes()); } else { gclog_or_tty->print(" " SIZE_FORMAT "K" "->" SIZE_FORMAT "K" "(" SIZE_FORMAT "K)", prev_metadata_used/K, - allocated_used_bytes()/K, + used_bytes()/K, reserved_bytes()/K); } @@ -2721,8 +2721,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes()/K, - allocated_capacity_bytes()/K, + used_bytes()/K, + capacity_bytes()/K, committed_bytes()/K, reserved_bytes()/K); @@ -2733,8 +2733,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes(ct)/K, - allocated_capacity_bytes(ct)/K, + used_bytes(ct)/K, + capacity_bytes(ct)/K, committed_bytes(ct)/K, reserved_bytes(ct)/K); } @@ -2836,42 +2836,42 @@ void MetaspaceAux::verify_capacity() { #ifdef ASSERT - size_t running_sum_capacity_bytes = allocated_capacity_bytes(); + size_t running_sum_capacity_bytes = capacity_bytes(); // For purposes of the running sum of capacity, verify against capacity size_t capacity_in_use_bytes = capacity_bytes_slow(); assert(running_sum_capacity_bytes == capacity_in_use_bytes, - err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT + err_msg("capacity_words() * BytesPerWord " SIZE_FORMAT " capacity_bytes_slow()" SIZE_FORMAT, running_sum_capacity_bytes, capacity_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t capacity_in_use_bytes = capacity_bytes_slow(i); - assert(allocated_capacity_bytes(i) == capacity_in_use_bytes, - err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT + assert(capacity_bytes(i) == capacity_in_use_bytes, + err_msg("capacity_bytes(%u) " SIZE_FORMAT " capacity_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_capacity_bytes(i), i, capacity_in_use_bytes)); + i, capacity_bytes(i), i, capacity_in_use_bytes)); } #endif } void MetaspaceAux::verify_used() { #ifdef ASSERT - size_t running_sum_used_bytes = allocated_used_bytes(); + size_t running_sum_used_bytes = used_bytes(); // For purposes of the running sum of used, verify against used size_t used_in_use_bytes = used_bytes_slow(); - assert(allocated_used_bytes() == used_in_use_bytes, - err_msg("allocated_used_bytes() " SIZE_FORMAT + assert(used_bytes() == used_in_use_bytes, + err_msg("used_bytes() " SIZE_FORMAT " used_bytes_slow()" SIZE_FORMAT, - allocated_used_bytes(), used_in_use_bytes)); + used_bytes(), used_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t used_in_use_bytes = used_bytes_slow(i); - assert(allocated_used_bytes(i) == used_in_use_bytes, - err_msg("allocated_used_bytes(%u) " SIZE_FORMAT + assert(used_bytes(i) == used_in_use_bytes, + err_msg("used_bytes(%u) " SIZE_FORMAT " used_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_used_bytes(i), i, used_in_use_bytes)); + i, used_bytes(i), i, used_in_use_bytes)); } #endif } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/metaspace.hpp --- a/src/share/vm/memory/metaspace.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/metaspace.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -280,11 +280,11 @@ // allocated to a Metaspace. This is used instead of // iterating over all the classloaders. One for each // type of Metadata - static size_t _allocated_capacity_words[Metaspace:: MetadataTypeCount]; - // Running sum of space in all Metachunks that have + static size_t _capacity_words[Metaspace:: MetadataTypeCount]; + // Running sum of space in all Metachunks that // are being used for metadata. One for each // type of Metadata. - static size_t _allocated_used_words[Metaspace:: MetadataTypeCount]; + static size_t _used_words[Metaspace:: MetadataTypeCount]; public: // Decrement and increment _allocated_capacity_words @@ -308,32 +308,32 @@ static size_t free_chunks_total_bytes(); static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); - static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) { - return _allocated_capacity_words[mdtype]; + static size_t capacity_words(Metaspace::MetadataType mdtype) { + return _capacity_words[mdtype]; } - static size_t allocated_capacity_words() { - return allocated_capacity_words(Metaspace::NonClassType) + - allocated_capacity_words(Metaspace::ClassType); + static size_t capacity_words() { + return capacity_words(Metaspace::NonClassType) + + capacity_words(Metaspace::ClassType); } - static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) { - return allocated_capacity_words(mdtype) * BytesPerWord; + static size_t capacity_bytes(Metaspace::MetadataType mdtype) { + return capacity_words(mdtype) * BytesPerWord; } - static size_t allocated_capacity_bytes() { - return allocated_capacity_words() * BytesPerWord; + static size_t capacity_bytes() { + return capacity_words() * BytesPerWord; } - static size_t allocated_used_words(Metaspace::MetadataType mdtype) { - return _allocated_used_words[mdtype]; + static size_t used_words(Metaspace::MetadataType mdtype) { + return _used_words[mdtype]; } - static size_t allocated_used_words() { - return allocated_used_words(Metaspace::NonClassType) + - allocated_used_words(Metaspace::ClassType); + static size_t used_words() { + return used_words(Metaspace::NonClassType) + + used_words(Metaspace::ClassType); } - static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) { - return allocated_used_words(mdtype) * BytesPerWord; + static size_t used_bytes(Metaspace::MetadataType mdtype) { + return used_words(mdtype) * BytesPerWord; } - static size_t allocated_used_bytes() { - return allocated_used_words() * BytesPerWord; + static size_t used_bytes() { + return used_words() * BytesPerWord; } static size_t free_bytes(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/metaspaceCounters.cpp --- a/src/share/vm/memory/metaspaceCounters.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/metaspaceCounters.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -66,7 +66,7 @@ MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL; size_t MetaspaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspaceCounters::capacity() { @@ -98,7 +98,7 @@ MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL; size_t CompressedClassSpaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } size_t CompressedClassSpaceCounters::capacity() { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/metaspaceShared.cpp --- a/src/share/vm/memory/metaspaceShared.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/metaspaceShared.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -645,9 +645,6 @@ TraceTime timer("Dump Shared Spaces", TraceStartupTime); ResourceMark rm; - // Lock out GC - is it necessary? I don't think we care. - No_GC_Verifier no_gc; - // Preload classes to be shared. // Should use some os:: method rather than fopen() here. aB. // Construct the path to the class list (in jre/lib) diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/memory/universe.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -632,7 +632,6 @@ guarantee(sizeof(oop) % sizeof(HeapWord) == 0, "oop size is not not a multiple of HeapWord size"); TraceTime timer("Genesis", TraceStartupTime); - GC_locker::lock(); // do not allow gc during bootstrapping JavaClasses::compute_hard_coded_offsets(); jint status = Universe::initialize_heap(); @@ -1164,8 +1163,6 @@ MemoryService::add_metaspace_memory_pools(); - GC_locker::unlock(); // allow gc after bootstrapping - MemoryService::set_universe_heap(Universe::_collectedHeap); return true; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/arrayKlass.cpp --- a/src/share/vm/oops/arrayKlass.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/arrayKlass.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -64,10 +64,10 @@ return NULL; } -Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); - return super()->uncached_lookup_method(name, signature); + return super()->uncached_lookup_method(name, signature, mode); } ArrayKlass::ArrayKlass(Symbol* name) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/arrayKlass.hpp --- a/src/share/vm/oops/arrayKlass.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/arrayKlass.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -86,7 +86,7 @@ objArrayOop allocate_arrayArray(int n, int length, TRAPS); // Lookup operations - Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // Casting from Klass* static ArrayKlass* cast(Klass* k) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/constantPool.cpp --- a/src/share/vm/oops/constantPool.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/constantPool.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -144,6 +144,10 @@ // CDS support. Create a new resolved_references array. void ConstantPool::restore_unshareable_info(TRAPS) { + // Only create the new resolved references array and lock if it hasn't been + // attempted before + if (resolved_references() != NULL) return; + // restore the C++ vtable from the shared archive restore_vtable(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1329,17 +1329,18 @@ } -void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS) { +void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) { instanceKlassHandle h_this(THREAD, this); - do_local_static_fields_impl(h_this, f, CHECK); + do_local_static_fields_impl(h_this, f, mirror, CHECK); } -void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) { - for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) { +void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, + void f(fieldDescriptor* fd, Handle mirror, TRAPS), Handle mirror, TRAPS) { + for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { fieldDescriptor& fd = fs.field_descriptor(); - f(&fd, CHECK); + f(&fd, mirror, CHECK); } } } @@ -1428,7 +1429,11 @@ // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { - return InstanceKlass::find_method(methods(), name, signature); + return find_method_impl(name, signature, false); +} + +Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const { + return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass); } // find_instance_method looks up the name/signature in the local methods array @@ -1445,40 +1450,49 @@ // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array* methods, Symbol* name, Symbol* signature) { - int hit = find_method_index(methods, name, signature); + return InstanceKlass::find_method_impl(methods, name, signature, false); +} + +Method* InstanceKlass::find_method_impl( + Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { + int hit = find_method_index(methods, name, signature, skipping_overpass); return hit >= 0 ? methods->at(hit): NULL; } // Used directly for default_methods to find the index into the // default_vtable_indices, and indirectly by find_method // find_method_index looks in the local methods array to return the index -// of the matching name/signature +// of the matching name/signature. If, overpass methods are being ignored, +// the search continues to find a potential non-overpass match. This capability +// is important during method resolution to prefer a static method, for example, +// over an overpass method. int InstanceKlass::find_method_index( - Array* methods, Symbol* name, Symbol* signature) { + Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass) { int hit = binary_search(methods, name); if (hit != -1) { Method* m = methods->at(hit); // Do linear search to find matching signature. First, quick check - // for common case - if (m->signature() == signature) return hit; + // for common case, ignoring overpasses if requested. + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit; + // search downwards through overloaded methods int i; for (i = hit - 1; i >= 0; --i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return i; + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; } // search upwards for (i = hit + 1; i < methods->length(); ++i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (m->signature() == signature) return i; + if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i; } // not found #ifdef ASSERT - int index = linear_search(methods, name, signature); + int index = skipping_overpass ? -1 : linear_search(methods, name, signature); assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif } @@ -1504,16 +1518,16 @@ // uncached_lookup_method searches both the local class methods array and all // superclasses methods arrays, skipping any overpass methods in superclasses. -Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { + MethodLookupMode lookup_mode = mode; Klass* klass = const_cast(this); - bool dont_ignore_overpasses = true; // For the class being searched, find its overpasses. while (klass != NULL) { - Method* method = InstanceKlass::cast(klass)->find_method(name, signature); - if ((method != NULL) && (dont_ignore_overpasses || !method->is_overpass())) { + Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, (lookup_mode == skip_overpass)); + if (method != NULL) { return method; } klass = InstanceKlass::cast(klass)->super(); - dont_ignore_overpasses = false; // Ignore overpass methods in all superclasses. + lookup_mode = skip_overpass; // Always ignore overpass methods in superclasses } return NULL; } @@ -1528,7 +1542,7 @@ } // Look up interfaces if (m == NULL) { - m = lookup_method_in_all_interfaces(name, signature, false); + m = lookup_method_in_all_interfaces(name, signature, normal); } return m; } @@ -1538,7 +1552,7 @@ // They should only be found in the initial InterfaceMethodRef Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, - bool skip_default_methods) const { + MethodLookupMode mode) const { Array* all_ifs = transitive_interfaces(); int num_ifs = all_ifs->length(); InstanceKlass *ik = NULL; @@ -1546,7 +1560,7 @@ ik = InstanceKlass::cast(all_ifs->at(i)); Method* m = ik->lookup_method(name, signature); if (m != NULL && m->is_public() && !m->is_static() && - (!skip_default_methods || !m->is_default_method())) { + ((mode != skip_defaults) || !m->is_default_method())) { return m; } } @@ -2280,9 +2294,7 @@ int num_methods = methods->length(); for (int index2 = 0; index2 < num_methods; ++index2) { methodHandle m(THREAD, methods->at(index2)); - m()->link_method(m, CHECK); - // restore method's vtable by calling a virtual function - m->restore_vtable(); + m->restore_unshareable_info(CHECK); } if (JvmtiExport::has_redefined_a_class()) { // Reinitialize vtable because RedefineClasses may have changed some diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -518,14 +518,14 @@ static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); // find a local method index in default_methods (returns -1 if not found) - static int find_method_index(Array* methods, Symbol* name, Symbol* signature); + static int find_method_index(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); // lookup operation (returns NULL if not found) - Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // lookup a method in all the interfaces that this class implements // (returns NULL if not found) - Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, bool skip_default_methods) const; + Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, MethodLookupMode mode) const; // lookup a method in local defaults then in all interfaces // (returns NULL if not found) @@ -830,7 +830,7 @@ // Iterators void do_local_static_fields(FieldClosure* cl); void do_nonstatic_fields(FieldClosure* cl); // including inherited fields - void do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS); + void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS); void methods_do(void f(Method* method)); void array_klasses_do(void f(Klass* k)); @@ -1038,7 +1038,7 @@ static void set_initialization_state_and_notify_impl (instanceKlassHandle this_oop, ClassState state, TRAPS); static void call_class_initializer_impl (instanceKlassHandle this_oop, TRAPS); static Klass* array_klass_impl (instanceKlassHandle this_oop, bool or_null, int n, TRAPS); - static void do_local_static_fields_impl (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS); + static void do_local_static_fields_impl (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS); /* jni_id_for_impl for jfieldID only */ static JNIid* jni_id_for_impl (instanceKlassHandle this_oop, int offset); @@ -1048,6 +1048,10 @@ // Returns the array class with this class as element type Klass* array_klass_impl(bool or_null, TRAPS); + // find a local method (returns NULL if not found) + Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const; + static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, bool skipping_overpass); + // Free CHeap allocated fields. void release_C_heap_structures(); public: diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/instanceMirrorKlass.cpp --- a/src/share/vm/oops/instanceMirrorKlass.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/instanceMirrorKlass.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -367,7 +367,12 @@ // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, this); - instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL); + instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); + + // Since mirrors can be variable sized because of the static fields, store + // the size in the mirror itself. + java_lang_Class::set_oop_size(i, size); + return i; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/klass.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -129,7 +129,7 @@ } -Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const { +Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { #ifdef ASSERT tty->print_cr("Error: uncached_lookup_method called on a klass oop." " Likely error: reflection method does not correctly" @@ -483,12 +483,8 @@ } void Klass::remove_unshareable_info() { - if (!DumpSharedSpaces) { - // Clean up after OOM during class loading - if (class_loader_data() != NULL) { - class_loader_data()->remove_class(this); - } - } + assert (DumpSharedSpaces, "only called for DumpSharedSpaces"); + set_subklass(NULL); set_next_sibling(NULL); // Clear the java mirror @@ -500,17 +496,26 @@ } void Klass::restore_unshareable_info(TRAPS) { - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - // Restore class_loader_data to the null class loader data - set_class_loader_data(loader_data); + // If an exception happened during CDS restore, some of these fields may already be + // set. We leave the class on the CLD list, even if incomplete so that we don't + // modify the CLD list outside a safepoint. + if (class_loader_data() == NULL) { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + // Restore class_loader_data to the null class loader data + set_class_loader_data(loader_data); - // Add to null class loader list first before creating the mirror - // (same order as class file parsing) - loader_data->add_class(this); + // Add to null class loader list first before creating the mirror + // (same order as class file parsing) + loader_data->add_class(this); + } // Recreate the class mirror. The protection_domain is always null for // boot loader, for now. - java_lang_Class::create_mirror(this, Handle(NULL), CHECK); + // Only recreate it if not present. A previous attempt to restore may have + // gotten an OOM later but keep the mirror if it was created. + if (java_mirror() == NULL) { + java_lang_Class::create_mirror(this, Handle(NULL), CHECK); + } } Klass* Klass::array_klass_or_null(int rank) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/klass.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -182,6 +182,8 @@ void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); public: + enum MethodLookupMode { normal, skip_overpass, skip_defaults }; + bool is_klass() const volatile { return true; } // super @@ -421,10 +423,10 @@ virtual void initialize(TRAPS); // lookup operation for MethodLookupCache friend class MethodLookupCache; - virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature) const; + virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const { - return uncached_lookup_method(name, signature); + return uncached_lookup_method(name, signature, normal); } // array class with specific rank diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/klassVtable.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -622,7 +622,7 @@ // this check for all access permissions. InstanceKlass *sk = InstanceKlass::cast(super); if (sk->has_miranda_methods()) { - if (sk->lookup_method_in_all_interfaces(name, signature, false) != NULL) { + if (sk->lookup_method_in_all_interfaces(name, signature, Klass::normal) != NULL) { return false; // found a matching miranda; we do not need a new entry } } @@ -698,7 +698,7 @@ && mo->method_holder() != NULL && mo->method_holder()->super() != NULL) { - mo = mo->method_holder()->super()->uncached_lookup_method(name, signature); + mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::normal); } if (mo == NULL || mo->access_flags().is_private() ) { // super class hierarchy does not implement it or protection is different @@ -743,7 +743,7 @@ if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all? InstanceKlass *sk = InstanceKlass::cast(super); // check if it is a duplicate of a super's miranda - if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), false) == NULL) { + if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::normal) == NULL) { new_mirandas->append(im); } if (all_mirandas != NULL) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/metadata.hpp --- a/src/share/vm/oops/metadata.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/metadata.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -42,6 +42,7 @@ // Rehashing support for tables containing pointers to this unsigned int new_hash(juint seed) { ShouldNotReachHere(); return 0; } + virtual bool is_metadata() const volatile { return true; } virtual bool is_klass() const volatile { return false; } virtual bool is_method() const volatile { return false; } virtual bool is_methodData() const volatile { return false; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/method.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -905,6 +905,19 @@ return adapter->get_c2i_entry(); } +void Method::restore_unshareable_info(TRAPS) { + // Since restore_unshareable_info can be called more than once for a method, don't + // redo any work. If this field is restored, there is nothing to do. + if (_from_compiled_entry == NULL) { + // restore method's vtable by calling a virtual function + restore_vtable(); + + methodHandle mh(THREAD, this); + link_method(mh, CHECK); + } +} + + // The verified_code_entry() must be called when a invoke is resolved // on this method. diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/oops/method.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -156,6 +156,8 @@ void restore_vtable() { guarantee(is_method(), "vtable restored by this call"); } bool is_method() const volatile { return true; } + void restore_unshareable_info(TRAPS); + // accessors for instance variables ConstMethod* constMethod() const { return _constMethod; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/loopTransform.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1147,6 +1147,7 @@ // Now force out all loop-invariant dominating tests. The optimizer // finds some, but we _know_ they are all useless. peeled_dom_test_elim(loop,old_new); + loop->record_for_igvn(); } //------------------------------is_invariant----------------------------- diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/loopnode.cpp --- a/src/share/vm/opto/loopnode.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/loopnode.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -3171,17 +3171,16 @@ bool had_error = false; #ifdef ASSERT if (early != C->root()) { - // Make sure that there's a dominance path from use to LCA - Node* d = use; - while (d != LCA) { - d = idom(d); + // Make sure that there's a dominance path from LCA to early + Node* d = LCA; + while (d != early) { if (d == C->root()) { - tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx); - n->dump(); - use->dump(); + dump_bad_graph("Bad graph detected in compute_lca_of_uses", n, early, LCA); + tty->print_cr("*** Use %d isn't dominated by def %d ***", use->_idx, n->_idx); had_error = true; break; } + d = idom(d); } } #endif @@ -3434,6 +3433,13 @@ _igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops. } +#ifdef ASSERT + if (_verify_only && !n->is_CFG()) { + // Check def-use domination. + compute_lca_of_uses(n, get_ctrl(n), true /* verify */); + } +#endif + // CFG and pinned nodes already handled if( n->in(0) ) { if( n->in(0)->is_top() ) return; // Dead? diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/loopopts.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -2698,6 +2698,7 @@ // Inhibit more partial peeling on this loop new_head_clone->set_partial_peel_loop(); C->set_major_progress(); + loop->record_for_igvn(); #if !defined(PRODUCT) if (TracePartialPeeling) { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/machnode.hpp --- a/src/share/vm/opto/machnode.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/machnode.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -210,7 +210,14 @@ bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; } // Avoid back to back some instructions on some CPUs. - bool avoid_back_to_back() const { return (flags() & Flag_avoid_back_to_back) != 0; } + enum AvoidBackToBackFlag { AVOID_NONE = 0, + AVOID_BEFORE = Flag_avoid_back_to_back_before, + AVOID_AFTER = Flag_avoid_back_to_back_after, + AVOID_BEFORE_AND_AFTER = AVOID_BEFORE | AVOID_AFTER }; + + bool avoid_back_to_back(AvoidBackToBackFlag flag_value) const { + return (flags() & flag_value) == flag_value; + } // instruction implemented with a call bool has_call() const { return (flags() & Flag_has_call) != 0; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/node.hpp --- a/src/share/vm/opto/node.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/node.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -645,17 +645,18 @@ // Flags are sorted by usage frequency. enum NodeFlags { - Flag_is_Copy = 0x01, // should be first bit to avoid shift - Flag_rematerialize = Flag_is_Copy << 1, + Flag_is_Copy = 0x01, // should be first bit to avoid shift + Flag_rematerialize = Flag_is_Copy << 1, Flag_needs_anti_dependence_check = Flag_rematerialize << 1, - Flag_is_macro = Flag_needs_anti_dependence_check << 1, - Flag_is_Con = Flag_is_macro << 1, - Flag_is_cisc_alternate = Flag_is_Con << 1, - Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, - Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, - Flag_avoid_back_to_back = Flag_may_be_short_branch << 1, - Flag_has_call = Flag_avoid_back_to_back << 1, - Flag_is_expensive = Flag_has_call << 1, + Flag_is_macro = Flag_needs_anti_dependence_check << 1, + Flag_is_Con = Flag_is_macro << 1, + Flag_is_cisc_alternate = Flag_is_Con << 1, + Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, + Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, + Flag_avoid_back_to_back_before = Flag_may_be_short_branch << 1, + Flag_avoid_back_to_back_after = Flag_avoid_back_to_back_before << 1, + Flag_has_call = Flag_avoid_back_to_back_after << 1, + Flag_is_expensive = Flag_has_call << 1, _max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination }; diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/opto/output.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -411,7 +411,7 @@ blk_size += nop_size; } } - if (mach->avoid_back_to_back()) { + if (mach->avoid_back_to_back(MachNode::AVOID_BEFORE)) { // Nop is inserted between "avoid back to back" instructions. // ScheduleAndBundle() can rearrange nodes in a block, // check for all offsets inside this block. @@ -439,7 +439,7 @@ last_call_adr = blk_starts[i]+blk_size; } // Remember end of avoid_back_to_back offset - if (nj->is_Mach() && nj->as_Mach()->avoid_back_to_back()) { + if (nj->is_Mach() && nj->as_Mach()->avoid_back_to_back(MachNode::AVOID_AFTER)) { last_avoid_back_to_back_adr = blk_starts[i]+blk_size; } } @@ -525,11 +525,11 @@ int new_size = replacement->size(_regalloc); int diff = br_size - new_size; assert(diff >= (int)nop_size, "short_branch size should be smaller"); - // Conservatively take into accound padding between + // Conservatively take into account padding between // avoid_back_to_back branches. Previous branch could be // converted into avoid_back_to_back branch during next // rounds. - if (needs_padding && replacement->avoid_back_to_back()) { + if (needs_padding && replacement->avoid_back_to_back(MachNode::AVOID_BEFORE)) { jmp_offset[i] += nop_size; diff -= nop_size; } @@ -548,7 +548,7 @@ } } // (mach->may_be_short_branch()) if (mach != NULL && (mach->may_be_short_branch() || - mach->avoid_back_to_back())) { + mach->avoid_back_to_back(MachNode::AVOID_AFTER))) { last_may_be_short_branch_adr = blk_starts[i] + jmp_offset[i] + jmp_size[i]; } blk_starts[i+1] -= adjust_block_start; @@ -1313,7 +1313,7 @@ if (is_sfn && !is_mcall && padding == 0 && current_offset == last_call_offset) { padding = nop_size; } - if (padding == 0 && mach->avoid_back_to_back() && + if (padding == 0 && mach->avoid_back_to_back(MachNode::AVOID_BEFORE) && current_offset == last_avoid_back_to_back_offset) { // Avoid back to back some instructions. padding = nop_size; @@ -1407,7 +1407,7 @@ int new_size = replacement->size(_regalloc); assert((br_size - new_size) >= (int)nop_size, "short_branch size should be smaller"); // Insert padding between avoid_back_to_back branches. - if (needs_padding && replacement->avoid_back_to_back()) { + if (needs_padding && replacement->avoid_back_to_back(MachNode::AVOID_BEFORE)) { MachNode *nop = new (this) MachNopNode(); block->insert_node(nop, j++); _cfg->map_node_to_block(nop, block); @@ -1515,7 +1515,7 @@ last_call_offset = current_offset; } - if (n->is_Mach() && n->as_Mach()->avoid_back_to_back()) { + if (n->is_Mach() && n->as_Mach()->avoid_back_to_back(MachNode::AVOID_AFTER)) { // Avoid back to back some instructions. last_avoid_back_to_back_offset = current_offset; } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/prims/jvm.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1217,7 +1217,8 @@ // get run() method Method* m_oop = object->klass()->uncached_lookup_method( vmSymbols::run_method_name(), - vmSymbols::void_object_signature()); + vmSymbols::void_object_signature(), + Klass::normal); methodHandle m (THREAD, m_oop); if (m.is_null() || !m->is_method() || !m()->is_public() || m()->is_static()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method"); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -408,7 +408,7 @@ // Find method and invoke standard lookup methodHandle method (THREAD, - klass->uncached_lookup_method(m_name, s_name)); + klass->uncached_lookup_method(m_name, s_name, Klass::normal)); address result = lookup(method, in_base_library, CATCH); assert(in_base_library, "must be in basic library"); guarantee(result != NULL, "must be non NULL"); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/prims/whitebox.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -438,6 +438,30 @@ return (mh->queued_for_compilation() || nm != NULL); WB_END +class VM_WhiteBoxOperation : public VM_Operation { + public: + VM_WhiteBoxOperation() { } + VMOp_Type type() const { return VMOp_WhiteBoxOperation; } + bool allow_nested_vm_operations() const { return true; } +}; + +class AlwaysFalseClosure : public BoolObjectClosure { + public: + bool do_object_b(oop p) { return false; } +}; + +static AlwaysFalseClosure always_false; + +class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation { + public: + VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { } + void doit() { + _mdo->clean_method_data(&always_false); + } + private: + MethodData* _mdo; +}; + WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION(env); @@ -453,6 +477,8 @@ for (int i = 0; i < arg_count; i++) { mdo->set_arg_modified(i, 0); } + VM_WhiteBoxCleanMethodData op(mdo); + VMThread::execute(&op); } mh->clear_not_c1_compilable(); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -960,14 +960,13 @@ * it gets turned into a tail-call on sparc, which runs into dtrace bug * 6254741. Once that is fixed we can remove the dummy return value. */ -int SharedRuntime::dtrace_object_alloc(oopDesc* o) { - return dtrace_object_alloc_base(Thread::current(), o); +int SharedRuntime::dtrace_object_alloc(oopDesc* o, int size) { + return dtrace_object_alloc_base(Thread::current(), o, size); } -int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o) { +int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o, int size) { assert(DTraceAllocProbes, "wrong call"); Klass* klass = o->klass(); - int size = o->size(); Symbol* name = klass->name(); #ifndef USDT2 HS_DTRACE_PROBE4(hotspot, object__alloc, get_java_tid(thread), diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/sharedRuntime.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -261,8 +261,8 @@ static void register_finalizer(JavaThread* thread, oopDesc* obj); // dtrace notifications - static int dtrace_object_alloc(oopDesc* o); - static int dtrace_object_alloc_base(Thread* thread, oopDesc* o); + static int dtrace_object_alloc(oopDesc* o, int size); + static int dtrace_object_alloc_base(Thread* thread, oopDesc* o, int size); static int dtrace_method_entry(JavaThread* thread, Method* m); static int dtrace_method_exit(JavaThread* thread, Method* m); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/thread.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -239,7 +239,6 @@ debug_only(_allow_allocation_count = 0;) NOT_PRODUCT(_allow_safepoint_count = 0;) NOT_PRODUCT(_skip_gcalot = false;) - CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; set_allocated_bytes(0); _vm_operation_started_count = 0; diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/thread.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -249,9 +249,6 @@ // Used by SkipGCALot class. NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot? - // Record when GC is locked out via the GC_locker mechanism - CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;) - friend class No_Alloc_Verifier; friend class No_Safepoint_Verifier; friend class Pause_No_Safepoint_Verifier; @@ -397,7 +394,6 @@ void clear_unhandled_oops() { if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops(); } - bool is_gc_locked_out() { return _gc_locked_out_count > 0; } #endif // CHECK_UNHANDLED_OOPS #ifndef PRODUCT diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/unhandledOops.cpp --- a/src/share/vm/runtime/unhandledOops.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/unhandledOops.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -113,9 +113,7 @@ void UnhandledOops::clear_unhandled_oops() { assert (CheckUnhandledOops, "should only be called with checking option"); - if (_thread->is_gc_locked_out()) { - return; - } + for (int k = 0; k < _oop_list->length(); k++) { UnhandledOopEntry entry = _oop_list->at(k); // If an entry is on the unhandled oop list but isn't on the stack diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/runtime/vm_operations.hpp --- a/src/share/vm/runtime/vm_operations.hpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/runtime/vm_operations.hpp Thu Apr 17 16:09:07 2014 -0700 @@ -95,6 +95,7 @@ template(Exit) \ template(LinuxDllLoad) \ template(RotateGCLog) \ + template(WhiteBoxOperation) \ class VM_Operation: public CHeapObj { public: diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/services/memoryPool.cpp --- a/src/share/vm/services/memoryPool.cpp Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/services/memoryPool.cpp Thu Apr 17 16:09:07 2014 -0700 @@ -268,7 +268,7 @@ } size_t MetaspacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspacePool::calculate_max_size() const { @@ -280,7 +280,7 @@ MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { } size_t CompressedKlassSpacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } MemoryUsage CompressedKlassSpacePool::get_memory_usage() { diff -r 70dc2c030c69 -r b6a2ba7d3ea7 src/share/vm/trace/trace.xml --- a/src/share/vm/trace/trace.xml Wed Apr 16 12:32:23 2014 -0700 +++ b/src/share/vm/trace/trace.xml Thu Apr 17 16:09:07 2014 -0700 @@ -185,7 +185,7 @@ - + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/TEST.groups --- a/test/TEST.groups Wed Apr 16 12:32:23 2014 -0700 +++ b/test/TEST.groups Thu Apr 17 16:09:07 2014 -0700 @@ -135,7 +135,8 @@ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/tiered/NonTieredLevelsTest.java \ - compiler/tiered/TieredLevelsTest.java + compiler/tiered/TieredLevelsTest.java \ + compiler/intrinsics/bmi/verifycode # Compact 2 adds full VM tests compact2 = \ diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/AddnTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build AddnTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestI + */ + +import java.lang.reflect.Method; + +public class AddnTestI extends BmiIntrinsicBase.BmiTestCase { + + protected AddnTestI(Method method) { + super(method); + // from intel manual VEX.NDS.LZ.0F38.W0 F2 /r, example c4e260f2c2 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF2}; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(AddnTestI::new, TestAndnI.AndnIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(AddnTestI::new, TestAndnI.AndnICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/AddnTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build AddnTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestL + */ + +import java.lang.reflect.Method; + +public class AddnTestL extends AddnTestI { + + protected AddnTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(AddnTestL::new, TestAndnL.AndnLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(AddnTestL::new, TestAndnL.AndnLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsiTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestI + */ + +import java.lang.reflect.Method; + +public class BlsiTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsiTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /3 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_1000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsiTestI::new, TestBlsiI.BlsiIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsiTestI::new, TestBlsiI.BlsiICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsiTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestL + */ + +import java.lang.reflect.Method; + +public class BlsiTestL extends BlsiTestI { + + protected BlsiTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsiTestL::new, TestBlsiL.BlsiLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsiTestL::new, TestBlsiL.BlsiLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsmskTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestI + */ + +import java.lang.reflect.Method; + +public class BlsmskTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsmskTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /2 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_0000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsmskTestI::new, TestBlsmskI.BlsmskIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsmskTestI::new, TestBlsmskI.BlsmskICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsmskTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestL + */ + +import java.lang.reflect.Method; + +public class BlsmskTestL extends BlsmskTestI { + + protected BlsmskTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsmskTestL::new, TestBlsmskL.BlsmskLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsmskTestL::new, TestBlsmskL.BlsmskLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsrTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestI + */ + +import java.lang.reflect.Method; + +public class BlsrTestI extends BmiIntrinsicBase.BmiTestCase { + + protected BlsrTestI(Method method) { + super(method); + //from intel manual VEX.NDD.LZ.0F38.W0 F3 /1 + instrMask = new byte[]{ + (byte) 0xFF, + (byte) 0x1F, + (byte) 0x00, + (byte) 0xFF, + (byte) 0b0011_1000}; + instrPattern = new byte[]{ + (byte) 0xC4, // prefix for 3-byte VEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0000_1000}; // bits 543 == 011 (3) + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsrTestI::new, TestBlsrI.BlsrIExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsrTestI::new, TestBlsrI.BlsrICommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build BlsrTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestL + */ + +import java.lang.reflect.Method; + +public class BlsrTestL extends BlsrTestI { + + protected BlsrTestL(Method method) { + super(method); + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + BmiIntrinsicBase.verifyTestCase(BlsrTestL::new, TestBlsrL.BlsrLExpr.class.getDeclaredMethods()); + BmiIntrinsicBase.verifyTestCase(BlsrTestL::new, TestBlsrL.BlsrLCommutativeExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.Utils; +import sun.hotspot.code.NMethod; +import sun.hotspot.cpuinfo.CPUInfo; + +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.function.Function; + +public class BmiIntrinsicBase extends CompilerWhiteBoxTest { + + protected BmiIntrinsicBase(BmiTestCase testCase) { + super(testCase); + } + + public static void verifyTestCase(Function constructor, Method... methods) throws Exception { + for (Method method : methods) { + new BmiIntrinsicBase(constructor.apply(method)).test(); + } + } + + @Override + protected void test() throws Exception { + BmiTestCase bmiTestCase = (BmiTestCase) testCase; + + if (!(Platform.isX86() || Platform.isX64())) { + System.out.println("Unsupported platform, test SKIPPED"); + return; + } + + if (!Platform.isServer()) { + System.out.println("Not server VM, test SKIPPED"); + return; + } + + if (!CPUInfo.hasFeature(bmiTestCase.getCpuFlag())) { + System.out.println("Unsupported hardware, no required CPU flag " + bmiTestCase.getCpuFlag() + " , test SKIPPED"); + return; + } + + if (!Boolean.valueOf(getVMOption(bmiTestCase.getVMFlag()))) { + System.out.println("VM flag " + bmiTestCase.getVMFlag() + " disabled, test SKIPPED"); + return; + } + + System.out.println(testCase.name()); + + switch (MODE) { + case "compiled mode": + case "mixed mode": + if (TIERED_COMPILATION && TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_MAX) { + System.out.println("TieredStopAtLevel value (" + TIERED_STOP_AT_LEVEL + ") is too low, test SKIPPED"); + return; + } + deoptimize(); + compileAtLevelAndCheck(CompilerWhiteBoxTest.COMP_LEVEL_MAX); + break; + case "interpreted mode": // test is not applicable in this mode; + System.err.println("Warning: This test is not applicable in mode: " + MODE); + break; + default: + throw new AssertionError("Test bug, unknown VM mode: " + MODE); + } + } + + protected void compileAtLevelAndCheck(int level) { + WHITE_BOX.enqueueMethodForCompilation(method, level); + waitBackgroundCompilation(); + checkCompilation(method, level); + checkEmittedCode(method); + } + + protected void checkCompilation(Executable executable, int level) { + if (!WHITE_BOX.isMethodCompiled(executable)) { + throw new AssertionError("Test bug, expected compilation (level): " + level + ", but not compiled" + WHITE_BOX.isMethodCompilable(executable, level)); + } + final int compilationLevel = WHITE_BOX.getMethodCompilationLevel(executable); + if (compilationLevel != level) { + throw new AssertionError("Test bug, expected compilation (level): " + level + ", but level: " + compilationLevel); + } + } + + protected void checkEmittedCode(Executable executable) { + final byte[] nativeCode = NMethod.get(executable, false).insts; + if (!((BmiTestCase) testCase).verifyPositive(nativeCode)) { + throw new AssertionError(testCase.name() + "CPU instructions expected not found: " + Utils.toHexString(nativeCode)); + } else { + System.out.println("CPU instructions found, PASSED"); + } + } + + abstract static class BmiTestCase implements CompilerWhiteBoxTest.TestCase { + private final Method method; + protected byte[] instrMask; + protected byte[] instrPattern; + protected boolean isLongOperation; + + public BmiTestCase(Method method) { + this.method = method; + } + + @Override + public String name() { + return method.toGenericString(); + } + + @Override + public Executable getExecutable() { + return method; + } + + @Override + public Callable getCallable() { + return null; + } + + @Override + public boolean isOsr() { + return false; + } + + protected int countCpuInstructions(byte[] nativeCode) { + int count = 0; + int patternSize = Math.min(instrMask.length, instrPattern.length); + boolean found; + Asserts.assertGreaterThan(patternSize, 0); + for (int i = 0, n = nativeCode.length - patternSize; i < n; i++) { + found = true; + for (int j = 0; j < patternSize; j++) { + if ((nativeCode[i + j] & instrMask[j]) != instrPattern[j]) { + found = false; + break; + } + } + if (found) { + ++count; + i += patternSize - 1; + } + } + return count; + } + + public boolean verifyPositive(byte[] nativeCode) { + final int cnt = countCpuInstructions(nativeCode); + if (Platform.isX86()) { + return cnt >= (isLongOperation ? 2 : 1); + } else { + return Platform.isX64() && cnt >= 1; + } + } + + protected String getCpuFlag() { + return "bmi1"; + } + + protected String getVMFlag() { + return "UseBMI1Instructions"; + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build LZcntTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestI + */ + +import java.lang.reflect.Method; + +public class LZcntTestI extends BmiIntrinsicBase.BmiTestCase { + + protected LZcntTestI(Method method) { + super(method); + instrMask = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x0F, (byte) 0xBD}; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("class java.lang.Integer should be loaded. Proof: " + Integer.class); + BmiIntrinsicBase.verifyTestCase(LZcntTestI::new, TestLzcntI.LzcntIExpr.class.getDeclaredMethods()); + } + + @Override + protected String getVMFlag() { + return "UseCountLeadingZerosInstruction"; + } + + @Override + protected String getCpuFlag() { + return "lzcnt"; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build LZcntTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestL + */ + +import com.oracle.java.testlibrary.Platform; + +import java.lang.reflect.Method; + +public class LZcntTestL extends LZcntTestI { + + protected LZcntTestL(Method method) { + super(method); + isLongOperation = true; + if (Platform.isX64()) { + instrMask = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBD}; + } + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("classes java.lang.Long should be loaded. Proof: " + Long.class); + BmiIntrinsicBase.verifyTestCase(LZcntTestL::new, TestLzcntL.LzcntLExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build TZcntTestI + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestI + */ + +import java.lang.reflect.Method; + +public class TZcntTestI extends BmiIntrinsicBase.BmiTestCase { + + protected TZcntTestI(Method method) { + super(method); + instrMask = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x0F, (byte) 0xBC}; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("class java.lang.Integer should be loaded. Proof: " + Integer.class); + BmiIntrinsicBase.verifyTestCase(TZcntTestI::new, TestTzcntI.TzcntIExpr.class.getDeclaredMethods()); + } + + @Override + protected String getVMFlag() { + return "UseCountTrailingZerosInstruction"; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031321 + * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @build TZcntTestL + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestL + */ + +import com.oracle.java.testlibrary.Platform; + +import java.lang.reflect.Method; + +public class TZcntTestL extends TZcntTestI { + + protected TZcntTestL(Method method) { + super(method); + isLongOperation = true; + if (Platform.isX64()) { + instrMask = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; + instrPattern = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBC}; + } + isLongOperation = true; + } + + public static void main(String[] args) throws Exception { + // j.l.Integer and Long should be loaded to allow a compilation of the methods that use their methods + System.out.println("classes java.lang.Long should be loaded. Proof: " + Long.class); + BmiIntrinsicBase.verifyTestCase(TZcntTestL::new, TestTzcntL.TzcntLExpr.class.getDeclaredMethods()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +import java.util.function.BooleanSupplier; + +/** + * Base for all RTM-related CLI tests. + */ +public abstract class RTMGenericCommandLineOptionTest + extends CommandLineOptionTest { + protected static final String RTM_INSTR_ERROR + = "RTM instructions are not available on this CPU"; + protected static final String RTM_UNSUPPORTED_VM_ERROR + = "RTM locking optimization is not supported in this VM"; + protected static final String RTM_ABORT_RATIO_WARNING + = "RTMAbortRatio must be in the range 0 to 100, resetting it to 50"; + protected static final String RTM_FOR_STACK_LOCKS_WARNING + = "UseRTMForStackLocks flag should be off when UseRTMLocking " + + "flag is off"; + protected static final String RTM_COUNT_INCR_WARNING + = "RTMTotalCountIncrRate must be a power of 2, resetting it to 64"; + protected static final String RTM_BIASED_LOCKING_WARNING + = "Biased locking is not supported with RTM locking; " + + "ignoring UseBiasedLocking flag"; + + protected final String optionName; + protected final String errorMessage; + protected final String experimentalOptionError; + protected final boolean isExperimental; + protected final boolean isBoolean; + protected final String defaultValue; + protected final String[] optionValues; + + /** + * Constructs new genetic RTM CLI test, for option {@code optionName} which + * has default value {@code defaultValue}. Test cases will use option's + * values passed via {@code optionValues} for verification of correct + * option processing. + * + * Test constructed using this ctor will be started on any cpu regardless + * it's architecture and supported/unsupported features. + * + * @param predicate predicate responsible for test's preconditions check + * @param optionName name of option to be tested + * @param isBoolean {@code true} if option is binary + * @param isExperimental {@code true} if option is experimental + * @param defaultValue default value of tested option + * @param optionValues different option values + */ + public RTMGenericCommandLineOptionTest(BooleanSupplier predicate, + String optionName, boolean isBoolean, boolean isExperimental, + String defaultValue, String... optionValues) { + super(predicate); + this.optionName = optionName; + this.isExperimental = isExperimental; + this.isBoolean = isBoolean; + this.defaultValue = defaultValue; + this.optionValues = optionValues; + this.errorMessage = CommandLineOptionTest. + getUnrecognizedOptionErrorMessage(optionName); + this.experimentalOptionError = CommandLineOptionTest. + getExperimentalOptionErrorMessage(optionName); + } + + @Override + public void runTestCases() throws Throwable { + if (Platform.isX86() || Platform.isX64()) { + if (Platform.isServer() && !Platform.isEmbedded()) { + runX86SupportedVMTestCases(); + } else { + runX86UnsupportedVMTestCases(); + } + } else { + runNonX86TestCases(); + } + } + + /** + * Runs test cases on X86 CPU if VM supports RTM locking. + * @throws Throwable + */ + protected void runX86SupportedVMTestCases() throws Throwable { + runGenericX86TestCases(); + } + + /** + * Runs test cases on non-X86 CPU if VM does not support RTM locking. + * @throws Throwable + */ + protected void runX86UnsupportedVMTestCases() throws Throwable { + runGenericX86TestCases(); + } + + /** + * Runs test cases on non-X86 CPU. + * @throws Throwable + */ + protected void runNonX86TestCases() throws Throwable { + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + prepareOptionValue(defaultValue)); + } + + /** + * Runs generic X86 test cases. + * @throws Throwable + */ + protected void runGenericX86TestCases() throws Throwable { + verifyJVMStartup(); + verifyOptionValues(); + } + + protected void verifyJVMStartup() throws Throwable { + String optionValue = prepareOptionValue(defaultValue); + if (isExperimental) { + // verify that option is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[] { experimentalOptionError }, + new String[] { errorMessage }, ExitCode.FAIL, + optionValue); + // verify that it could be passed if experimental options + // are unlocked + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { + experimentalOptionError, + errorMessage + }, + ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + optionValue); + } else { + // verify that option could be passed + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{errorMessage}, ExitCode.OK, optionValue); + } + } + + protected void verifyOptionValues() throws Throwable { + // verify default value + if (isExperimental) { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + } else { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue); + } + // verify other specified option values + if (optionValues == null) { + return; + } + + for (String value : optionValues) { + if (isExperimental) { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + value, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue(value)); + } else { + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + value, prepareOptionValue(value)); + } + } + } + + protected String prepareOptionValue(String value) { + if (isBoolean) { + return CommandLineOptionTest.prepareBooleanFlag(optionName, + Boolean.valueOf(value)); + } else { + return String.format("-XX:%s=%s", optionName, value); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/RTMLockingAwareTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/RTMLockingAwareTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.util.Collections; +import java.util.List; +import java.util.LinkedList; + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Base for all RTM-related CLI tests on options whose processing depends + * on UseRTMLocking value. + * + * Since UseRTMLocking option could be used when both CPU and VM supports RTM + * locking, this test will be skipped on all unsupported configurations. + */ +public abstract class RTMLockingAwareTest + extends RTMGenericCommandLineOptionTest { + protected final String warningMessage; + protected final String[] correctValues; + protected final String[] incorrectValues; + /** + * Constructs new test for option {@code optionName} that should be executed + * only on CPU with RTM support. + * Test will be executed using set of correct values from + * {@code correctValues} and set of incorrect values from + * {@code incorrectValues}. + * + * @param optionName name of option to be tested + * @param isBoolean {@code true} if tested option is binary + * @param isExperimental {@code true} if tested option is experimental + * @param defaultValue default value of tested option + * @param correctValues array with correct values, that should not emit + * {@code warningMessage} to VM output + * @param incorrectValues array with incorrect values, that should emit + * {@code waningMessage} to VM output + * @param warningMessage warning message associated with tested option + */ + protected RTMLockingAwareTest(String optionName, boolean isBoolean, + boolean isExperimental, String defaultValue, + String[] correctValues, String[] incorrectValues, + String warningMessage) { + super(new AndPredicate(new SupportedCPU(), new SupportedVM()), + optionName, isBoolean, isExperimental, defaultValue); + this.correctValues = correctValues; + this.incorrectValues = incorrectValues; + this.warningMessage = warningMessage; + } + + @Override + protected void verifyJVMStartup() throws Throwable { + // Run generic sanity checks + super.verifyJVMStartup(); + // Verify how option values will be processed depending on + // UseRTMLocking value. + if (correctValues != null) { + for (String correctValue : correctValues) { + // For correct values it is expected to see no warnings + // regardless to UseRTMLocking + verifyStartupWarning(correctValue, true, false); + verifyStartupWarning(correctValue, false, false); + } + } + + if (incorrectValues != null) { + for (String incorrectValue : incorrectValues) { + // For incorrect values it is expected to see warning + // only with -XX:+UseRTMLocking + verifyStartupWarning(incorrectValue, true, true); + verifyStartupWarning(incorrectValue, false, false); + } + } + } + + @Override + protected void verifyOptionValues() throws Throwable { + super.verifyOptionValues(); + // Verify how option values will be setup after processing + // depending on UseRTMLocking value + if (correctValues != null) { + for (String correctValue : correctValues) { + // Correct value could be set up regardless to UseRTMLocking + verifyOptionValues(correctValue, false, correctValue); + verifyOptionValues(correctValue, true, correctValue); + } + } + + if (incorrectValues != null) { + for (String incorrectValue : incorrectValues) { + // With -XX:+UseRTMLocking, incorrect value will be changed to + // default value. + verifyOptionValues(incorrectValue, false, incorrectValue); + verifyOptionValues(incorrectValue, true, defaultValue); + } + } + } + + private void verifyStartupWarning(String value, boolean useRTMLocking, + boolean isWarningExpected) throws Throwable { + String warnings[] = new String[] { warningMessage }; + List options = new LinkedList<>(); + Collections.addAll(options, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", + useRTMLocking)); + + options.add(prepareOptionValue(value)); + + CommandLineOptionTest.verifySameJVMStartup( + (isWarningExpected ? warnings : null), + (isWarningExpected ? null : warnings), + ExitCode.OK, options.toArray(new String[options.size()])); + } + + private void verifyOptionValues(String value, boolean useRTMLocking, + String expectedValue) throws Throwable { + List options = new LinkedList<>(); + Collections.addAll(options, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", + useRTMLocking)); + + options.add(prepareOptionValue(value)); + + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + expectedValue, options.toArray(new String[options.size()])); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +import java.util.function.BooleanSupplier; + +public abstract class TestPrintPreciseRTMLockingStatisticsBase + extends RTMGenericCommandLineOptionTest { + protected static final String DEFAULT_VALUE = "false"; + + protected TestPrintPreciseRTMLockingStatisticsBase( + BooleanSupplier predicate) { + super(predicate, "PrintPreciseRTMLockingStatistics", true, false, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE); + } + + @Override + protected void runNonX86TestCases() throws Throwable { + verifyJVMStartup(); + verifyOptionValues(); + } + + @Override + protected void verifyJVMStartup() throws Throwable { + if (Platform.isServer()) { + if (!Platform.isDebugBuild()) { + String errorMessage = CommandLineOptionTest. + getDiagnosticOptionErrorMessage(optionName); + // verify that option is actually diagnostic + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + prepareOptionValue("true")); + + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { errorMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + prepareOptionValue("true")); + } else { + CommandLineOptionTest.verifySameJVMStartup( + null, null, ExitCode.OK, prepareOptionValue("true")); + } + } else { + String errorMessage = CommandLineOptionTest. + getUnrecognizedOptionErrorMessage(optionName); + + CommandLineOptionTest.verifySameJVMStartup( + new String[]{errorMessage}, null, ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + prepareOptionValue("true")); + } + } + + @Override + protected void verifyOptionValues() throws Throwable { + if (Platform.isServer()) { + // Verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs with + * rtm support and on VM with rtm locking support, + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig + extends TestPrintPreciseRTMLockingStatisticsBase { + private TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void verifyOptionValues() throws Throwable { + super.verifyOptionValues(); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking", prepareOptionValue("true")); + + // verify that option could be turned on + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", prepareOptionValue("true")); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() + .test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs without + * rtm support and/or unsupported VM. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig + extends TestPrintPreciseRTMLockingStatisticsBase { + private TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM()))); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() + .test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify RTMAbortRatio option processing on CPU with rtm + * support and on VM with rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatioOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnSupportedConfig + */ + +public class TestRTMAbortRatioOptionOnSupportedConfig + extends RTMLockingAwareTest { + private static final String DEFAULT_VALUE = "50"; + + private TestRTMAbortRatioOptionOnSupportedConfig() { + super("RTMAbortRatio", false, true, + TestRTMAbortRatioOptionOnSupportedConfig.DEFAULT_VALUE, + /* correct values */ + new String[] { "0", "20", "100" }, + /* incorrect values */ + new String[] { "-1", "101" }, + RTMGenericCommandLineOptionTest.RTM_ABORT_RATIO_WARNING); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatioOptionOnSupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify RTMAbortRatio option processing on CPU without rtm + * support or on VM that does not support rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatioOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestRTMAbortRatioOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "50"; + + private TestRTMAbortRatioOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedVM(), + new SupportedCPU())), + "RTMAbortRatio", false, true, + TestRTMAbortRatioOptionOnUnsupportedConfig.DEFAULT_VALUE, + "0", "10", "100", "200"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatioOptionOnUnsupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMAbortThresholdOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMAbortThresholdOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of RTMAbortThreshold option. + * @library /testlibrary + * @build TestRTMAbortThresholdOption + * @run main/othervm TestRTMAbortThresholdOption + */ + +public class TestRTMAbortThresholdOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "1000"; + + private TestRTMAbortThresholdOption() { + super(Boolean.TRUE::booleanValue, "RTMAbortThreshold", false, true, + TestRTMAbortThresholdOption.DEFAULT_VALUE, + "0", "42", "100", "10000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortThresholdOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of RTMLockingCalculationDelay option. + * @library /testlibrary + * @build TestRTMLockingCalculationDelayOption + * @run main/othervm TestRTMLockingCalculationDelayOption + */ + +public class TestRTMLockingCalculationDelayOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "0"; + + private TestRTMLockingCalculationDelayOption() { + super(Boolean.TRUE::booleanValue, "RTMLockingCalculationDelay", false, + true, TestRTMLockingCalculationDelayOption.DEFAULT_VALUE); + } + + public static void main(String agrs[]) throws Throwable { + new TestRTMLockingCalculationDelayOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMLockingThresholdOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMLockingThresholdOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of RTMLockingThreshold option. + * @library /testlibrary + * @build TestRTMLockingThresholdOption + * @run main/othervm TestRTMLockingThresholdOption + */ + +public class TestRTMLockingThresholdOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "10000"; + + private TestRTMLockingThresholdOption() { + super(Boolean.TRUE::booleanValue, "RTMLockingThreshold", false, true, + TestRTMLockingThresholdOption.DEFAULT_VALUE); + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingThresholdOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMRetryCountOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMRetryCountOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of RTMRetryCount option. + * @library /testlibrary + * @build TestRTMRetryCountOption + * @run main/othervm TestRTMRetryCountOption + */ + +public class TestRTMRetryCountOption extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "5"; + + private TestRTMRetryCountOption() { + super(Boolean.TRUE::booleanValue, "RTMRetryCount", false, true, + TestRTMRetryCountOption.DEFAULT_VALUE, + "0", "10", "100", "1000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMRetryCountOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMSpinLoopCountOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMSpinLoopCountOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of RTMSpinLoopCount option. + * @library /testlibrary + * @build TestRTMSpinLoopCountOption + * @run main/othervm TestRTMSpinLoopCountOption + */ + +public class TestRTMSpinLoopCountOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "100"; + + private TestRTMSpinLoopCountOption() { + super(Boolean.TRUE::booleanValue, "RTMSpinLoopCount", false, true, + TestRTMSpinLoopCountOption.DEFAULT_VALUE, + "0", "10", "42", "1000"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMSpinLoopCountOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify RTMTotalCountIncrRate option processing on CPU with + * rtm support and on VM with rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRateOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestRTMTotalCountIncrRateOptionOnSupportedConfig + */ + +public class TestRTMTotalCountIncrRateOptionOnSupportedConfig + extends RTMLockingAwareTest { + private static final String DEFAULT_VALUE = "64"; + + private TestRTMTotalCountIncrRateOptionOnSupportedConfig() { + super("RTMTotalCountIncrRate", false, true, + TestRTMTotalCountIncrRateOptionOnSupportedConfig.DEFAULT_VALUE, + /* correct values */ + new String[] { "1", "2", "128", "1024" }, + /* incorrect values */ + new String[] { "-1", "0", "3", "42" }, + RTMGenericCommandLineOptionTest.RTM_COUNT_INCR_WARNING); + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRateOptionOnSupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * @test + * @bug 8031320 + * @summary Verify RTMTotalCountIncrRate option processing on CPU without + * rtm support and/or on VM without rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + */ + +public class TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "64"; + + private TestRTMTotalCountIncrRateOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "RTMTotalCountIncrRate", false, true, + TestRTMTotalCountIncrRateOptionOnUnsupportedConfig + .DEFAULT_VALUE, + "-1", "0", "42", "128"); + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRateOptionOnUnsupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMDeopt option processing on CPUs with rtm support + * when rtm locking is supported by VM. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseRTMDeoptOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMDeoptOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMDeoptOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + String experimentalOptionError + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + "UseRTMDeopt"); + // verify that option is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[] { experimentalOptionError }, null, ExitCode.FAIL, + "-XX:+UseRTMDeopt"); + // verify that option could be turned on + CommandLineOptionTest.verifySameJVMStartup(null, null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMDeopt"); + // verify that option could be turned off + CommandLineOptionTest.verifySameJVMStartup(null, null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMDeopt"); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that option is off when UseRTMLocking is off + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "false", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt"); + // verify that option could be turned on + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "true", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeoptOptionOnSupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMDeopt option processing on CPUs without rtm support + * or on VMs without rtm locking support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseRTMDeoptOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; + +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMDeoptOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMDeoptOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "UseRTMDeopt", true, true, + TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, "true"); + } + + @Override + protected void runX86SupportedVMTestCases() throws Throwable { + super.verifyJVMStartup(); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that until RTMLocking is not used, value + // will be set to default false. + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + defaultValue, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMDeopt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeoptOptionOnUnsupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMForStackLocks option processing on CPU with + * rtm support when VM supports rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocksOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseRTMForStackLocksOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMForStackLocksOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMForStackLocksOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + String errorMessage + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + "UseRTMForStackLocks"); + String warningMessage + = RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING; + + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + "-XX:+UseRTMForStackLocks"); + // verify that we get a warning when trying to use rtm for stack + // lock, but not using rtm locking. + CommandLineOptionTest.verifySameJVMStartup( + new String[] { warningMessage }, null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMForStackLocks", + "-XX:-UseRTMLocking"); + // verify that we don't get a warning when no using rtm for stack + // lock and not using rtm locking. + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMForStackLocks", + "-XX:-UseRTMLocking"); + // verify that we don't get a warning when using rtm for stack + // lock and using rtm locking. + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMForStackLocks", + "-XX:+UseRTMLocking"); + // verify that default value if false + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that default value is false even with +UseRTMLocking + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that we can turn the option on + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", + "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseRTMForStackLocks"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocksOptionOnSupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMForStackLocks option processing on CPUs without + * rtm support and/or on VMs without rtm locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocksOptionOnUnsupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseRTMForStackLocksOptionOnUnsupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMForStackLocksOptionOnUnsupportedConfig + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMForStackLocksOptionOnUnsupportedConfig() { + super(new NotPredicate(new AndPredicate(new SupportedCPU(), + new SupportedVM())), + "UseRTMForStackLocks", true, true, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + "true"); + } + + @Override + protected void runX86SupportedVMTestCases() throws Throwable { + // verify that option is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ experimentalOptionError }, + null, ExitCode.FAIL, prepareOptionValue("true")); + + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ experimentalOptionError }, + null, ExitCode.FAIL, prepareOptionValue("false")); + + // verify that if we turn it on, then VM output will contain + // warning saying that this option could be turned on only + // when we use rtm locking + CommandLineOptionTest.verifySameJVMStartup( + new String[]{ + RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING + }, + null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue("true") + ); + // verify that options is turned off by default + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that it could not be turned on without rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, + TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + prepareOptionValue("true")); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocksOptionOnUnsupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMLocking option processing on CPU with rtm support and + * on VM with rtm-locking support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnSupportedConfig + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnSupportedConfig + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnSupportedConfig + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnSupportedConfig() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + public void runTestCases() throws Throwable { + String unrecongnizedOption + = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( + "UseRTMLocking"); + String experimentalOptionError + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + "UseRTMLocking"); + // verify that options is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[] { experimentalOptionError }, null, ExitCode.FAIL, + "-XX:+UseRTMLocking"); + // verify that there are no warning or error in VM output + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{ + RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, + unrecongnizedOption + }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + + CommandLineOptionTest.verifySameJVMStartup(null, + new String[]{ + RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, + unrecongnizedOption + }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking"); + // verify that UseRTMLocking is of by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + // verify that we can change UseRTMLocking value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking"); + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnSupportedConfig().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMLocking option processing on CPU without + * rtm support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnUnsupportedCPU + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedCPU + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnUnsupportedCPU + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnUnsupportedCPU() { + super(new AndPredicate(new NotPredicate(new SupportedCPU()), + new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + String unrecongnizedOption + = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( + "UseRTMLocking"); + String errorMessage = RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR; + + if (Platform.isX86() || Platform.isX64()) { + // verify that we get an error when use +UseRTMLocking + // on unsupported CPU + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, + new String[] { unrecongnizedOption }, + ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that we can pass -UseRTMLocking without + // getting any error messages + CommandLineOptionTest.verifySameJVMStartup( + null, + new String[]{ + errorMessage, + unrecongnizedOption + }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking"); + + // verify that UseRTMLocking is false by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); + } else { + // verify that on non-x86 CPUs RTMLocking could not be used + CommandLineOptionTest.verifySameJVMStartup( + new String[] { unrecongnizedOption }, + null, ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + + CommandLineOptionTest.verifySameJVMStartup( + new String[] { unrecongnizedOption }, + null, ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking"); + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnUnsupportedCPU().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify UseRTMLocking option processing on CPU with rtm support + * in case when VM should not support this option. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionOnUnsupportedVM + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedVM + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import com.oracle.java.testlibrary.cli.predicate.NotPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionOnUnsupportedVM + extends CommandLineOptionTest { + private static final String DEFAULT_VALUE = "false"; + + private TestUseRTMLockingOptionOnUnsupportedVM() { + super(new AndPredicate(new SupportedCPU(), + new NotPredicate(new SupportedVM()))); + } + @Override + public void runTestCases() throws Throwable { + String errorMessage + = RTMGenericCommandLineOptionTest.RTM_UNSUPPORTED_VM_ERROR; + String experimentalOptionError + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + "UseRTMLocking"); + // verify that options is experimental + CommandLineOptionTest.verifySameJVMStartup( + new String[] { experimentalOptionError }, null, ExitCode.FAIL, + "-XX:+UseRTMLocking"); + // verify that we can't use +UseRTMLocking + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that we can turn it off + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { errorMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:-UseRTMLocking"); + // verify that it is off by default + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", + TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionOnUnsupportedVM().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of UseRTMLocking and UseBiasedLocking + * options combination on CPU and VM with rtm support. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockingOptionWithBiasedLocking + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockingOptionWithBiasedLocking + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +public class TestUseRTMLockingOptionWithBiasedLocking + extends CommandLineOptionTest { + private TestUseRTMLockingOptionWithBiasedLocking() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + String warningMessage + = RTMGenericCommandLineOptionTest.RTM_BIASED_LOCKING_WARNING; + // verify that we will not get a warning + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:-UseBiasedLocking"); + // verify that we will get a warning + CommandLineOptionTest.verifySameJVMStartup( + new String[] { warningMessage }, null, ExitCode.OK, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); + // verify that UseBiasedLocking is false when we use rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", + "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + // verify that we can't turn on biased locking when + // using rtm locking + CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", + "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockingOptionWithBiasedLocking().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify processing of UseRTMXendForLockBusy option. + * @library /testlibrary + * @build TestUseRTMXendForLockBusyOption + * @run main/othervm TestUseRTMXendForLockBusyOption + */ + +public class TestUseRTMXendForLockBusyOption + extends RTMGenericCommandLineOptionTest { + private static final String DEFAULT_VALUE = "true"; + + public TestUseRTMXendForLockBusyOption() { + super(Boolean.TRUE::booleanValue, "UseRTMXendForLockBusy", true, true, + TestUseRTMXendForLockBusyOption.DEFAULT_VALUE, "true"); + } + + public static void main(String agrs[]) throws Throwable { + new TestUseRTMXendForLockBusyOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMAbortRatio.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMAbortRatio affects amount of aborts before + * deoptimization. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that method will be deoptimized on high abort ratio + * as soon as abort ratio reaches RTMAbortRatio's value. + */ +public class TestRTMAbortRatio extends CommandLineOptionTest { + private TestRTMAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyAbortRatio(0, false); + verifyAbortRatio(10, false); + verifyAbortRatio(50, false); + verifyAbortRatio(100, false); + + verifyAbortRatio(0, true); + verifyAbortRatio(10, true); + verifyAbortRatio(50, true); + verifyAbortRatio(100, true); + } + + private void verifyAbortRatio(int abortRatio, boolean useStackLock) + throws Throwable { + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:+UseRTMDeopt", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMAbortThreshold=0", + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + 10 * Test.TOTAL_ITERATIONS), + CommandLineOptionTest.prepareNumericFlag("RTMAbortRatio", + abortRatio), + "-XX:+PrintPreciseRTMLockingStatistics", + test.getClass().getName(), + Boolean.toString(!useStackLock)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry."); + + RTMLockingStatistics lock = statistics.get(0); + int actualRatio; + + if (lock.getTotalAborts() == 1L) { + actualRatio = 0; + } else { + actualRatio = (int) (lock.getTotalLocks() + / (lock.getTotalAborts() - 1L)); + } + + Asserts.assertLTE(actualRatio, abortRatio, String.format( + "Actual abort ratio (%d) should lower or equal to " + + "specified (%d).", actualRatio, abortRatio)); + } + + /** + * Force abort after {@code Test.WARMUP_ITERATIONS} is done. + */ + public static class Test implements CompilableTest { + private static final int TOTAL_ITERATIONS = 10000; + private static final int WARMUP_ITERATIONS = 1000; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + Unsafe.class.getName() + "::addressSize" + }; + } + + public void lock(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + t.lock(i >= Test.WARMUP_ITERATIONS); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortRatio().test(); + } +} + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMAbortThreshold.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMAbortThreshold.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMAbortThreshold option affects + * amount of aborts after which abort ratio is calculated. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAbortThreshold + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAbortThreshold + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that on RTMAbortThreshold option actually affects how soon + * method will be deoptimized on high abort ratio. + */ +public class TestRTMAbortThreshold extends CommandLineOptionTest { + private TestRTMAbortThreshold() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyAbortThreshold(false, 1); + verifyAbortThreshold(false, 10); + verifyAbortThreshold(false, 1000); + + verifyAbortThreshold(true, 1); + verifyAbortThreshold(true, 10); + verifyAbortThreshold(true, 1000); + } + + private void verifyAbortThreshold(boolean useStackLock, + long abortThreshold) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMDeopt", + "-XX:RTMAbortRatio=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + abortThreshold), + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + provoker.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalLocks(), abortThreshold, + String.format("Expected that method with rtm lock elision was" + + " deoptimized after %d lock attempts", + abortThreshold)); + } + + public static void main(String args[]) throws Throwable { + new TestRTMAbortThreshold().test(); + } +} + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that if we use RTMDeopt, then deoptimization + * caused by reason other then rtm_state_change will reset + * method's RTM state. And if we don't use RTMDeopt, then + * RTM state remain the same after such deoptimization. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMAfterNonRTMDeopt + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMAfterNonRTMDeopt + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * To verify that with +UseRTMDeopt method's RTM state will be + * changed to ProfileRTM on deoptimization unrelated to + * rtm_state_change following sequence of events is used: + *
+ *
+ *     rtm state ^
+ *               |
+ *       UseRTM  |      ******|     ******
+ *               |            |
+ *   ProfileRTM  |******|     |*****|
+ *               |      |     |     |
+ *              0-------|-----|-----|---------------------> time
+ *                      |     |     \ force abort
+ *                      |     |
+ *                      |     \ force deoptimization
+ *                      |
+ *                      \ force xabort
+ * 
+ * When xabort is forced by native method call method should + * change it's state to UseRTM, because we use RTMAbortRatio=100 + * and low RTMLockingThreshold, so at this point actual abort + * ratio will be below 100% and there should be enough lock + * attempts to recompile method without RTM profiling. + */ +public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { + private static final int ABORT_THRESHOLD = 1000; + private static final String RANGE_CHECK = "range_check"; + + private TestRTMAfterNonRTMDeopt() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMAfterDeopt(false, false); + verifyRTMAfterDeopt(true, false); + + verifyRTMAfterDeopt(false, true); + verifyRTMAfterDeopt(true, true); + } + + private void verifyRTMAfterDeopt(boolean useStackLock, + boolean useRTMDeopt) throws Throwable { + CompilableTest test = new Test(); + String logFile = String.format("rtm_%s_stack_lock_%s_deopt.xml", + (useStackLock ? "use" : "no"), (useRTMDeopt ? "use" : "no")); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFile, + test, + "-XX:CompileThreshold=1", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", + useRTMDeopt), + "-XX:RTMAbortRatio=100", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD / 2L), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int traps = RTMTestBase.firedRTMStateChangeTraps(logFile); + + if (useRTMDeopt) { + Asserts.assertEQ(traps, 2, "Two uncommon traps with " + + "reason rtm_state_change should be fired."); + } else { + Asserts.assertEQ(traps, 0, "No uncommon traps with " + + "reason rtm_state_change should be fired."); + } + + int rangeCheckTraps = RTMTestBase.firedUncommonTraps(logFile, + TestRTMAfterNonRTMDeopt.RANGE_CHECK); + + Asserts.assertEQ(rangeCheckTraps, 1, + "One range_check uncommon trap should be fired."); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + int expectedStatEntries = (useRTMDeopt ? 4 : 2); + + Asserts.assertEQ(statistics.size(), expectedStatEntries, + String.format("VM output should contain %d RTM locking " + + "statistics entries.", expectedStatEntries)); + } + + public static class Test implements CompilableTest { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int ITERATIONS = 10000; + private static final int RANGE_CHECK_AT = ITERATIONS / 2; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::forceAbort" + }; + } + + public void forceAbort(int a[], boolean abort) { + try { + synchronized(monitor) { + a[0]++; + if (abort) { + Test.field = Test.UNSAFE.addressSize(); + } + } + } catch (Throwable t) { + // suppress any throwables + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + + int tmp[] = new int[1]; + + for (int i = 0; i < Test.ITERATIONS; i++ ) { + if (i == Test.RANGE_CHECK_AT) { + t.forceAbort(new int[0], false); + } else { + boolean isThreshold + = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD); + boolean isThresholdPlusRange + = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD + + Test.RANGE_CHECK_AT); + t.forceAbort(tmp, isThreshold || isThresholdPlusRange); + } + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMAfterNonRTMDeopt().test(); + } +} + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that on high abort ratio method will be recompiled + * without rtm locking. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMDeoptOnHighAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMDeoptOnHighAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that on high abort ratio method wil be deoptimized with + * rtm_state_change reason and after that RTM-based lock elision will not + * be used for that method. + * This test make asserts on total locks count done by compiled method, + * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. + * For more details on that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMDeoptOnHighAbortRatio extends CommandLineOptionTest { + private static final long ABORT_THRESHOLD + = AbortProvoker.DEFAULT_ITERATIONS / 2L; + + private TestRTMDeoptOnHighAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyDeopt(false); + verifyDeopt(true); + } + + private void verifyDeopt(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:RTMRetryCount=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD), + "-XX:RTMAbortRatio=100", + "-XX:CompileThreshold=1", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 1, "Expected to get only one " + + "deoptimization due to rtm state change"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + provoker.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalLocks(), + TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD, + "After AbortThreshold was reached, method should be" + + " recompiled without rtm lock eliding."); + } + + public static void main(String args[]) throws Throwable { + new TestRTMDeoptOnHighAbortRatio().test(); + } +} + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that on low abort ratio method will be recompiled. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMDeoptOnLowAbortRatio + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMDeoptOnLowAbortRatio + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that low abort ratio method will be deoptimized with + * rtm_state_change reason and will continue to use RTM-based lock + * elision after that. + * This test make asserts on total locks count done by compiled method, + * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. + * For more details on that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { + private static final long LOCKING_THRESHOLD = 100L; + + private TestRTMDeoptOnLowAbortRatio() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMDeopt(false); + verifyRTMDeopt(true); + } + + private void verifyRTMDeopt(boolean useStackLock) throws Throwable { + CompilableTest test = new Test(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + useStackLock ? "use" : "no"); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + test, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD), + "-XX:RTMAbortThreshold=1", + "-XX:RTMAbortRatio=100", + "-XX:CompileThreshold=1", + "-XX:RTMRetryCount=0", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 1, + "Expected to get only one deoptimization due to rtm" + + " state change"); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, + "VM output should contain two RTM locking " + + "statistics entries for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics statisticsBeforeDeopt = null; + + for (RTMLockingStatistics s : statistics) { + if (s.getTotalLocks() + == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD + 1L) { + Asserts.assertNull(statisticsBeforeDeopt, + "Only one abort was expected during test run"); + statisticsBeforeDeopt = s; + } + } + + Asserts.assertNotNull(statisticsBeforeDeopt, + "After LockThreshold was reached, method should be recompiled " + + "with rtm lock eliding."); + } + + public static class Test implements CompilableTest { + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::addressSize" + }; + } + + public void forceAbort(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + t.forceAbort( + i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMDeoptOnLowAbortRatio().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMLockingCalculationDelay affect when + * abort ratio calculation is started. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMLockingCalculationDelay + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMLockingCalculationDelay + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that abort ratio calculation could be delayed using + * RTMLockingCalculationDelay option. + */ +public class TestRTMLockingCalculationDelay extends CommandLineOptionTest { + private static final boolean INFLATE_MONITOR = true; + + private TestRTMLockingCalculationDelay() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + // verify that calculation will be started immediately + verifyLockingCalculationDelay(0, 0, true); + + // verify that calculation will not be started during + // first 10 minutes, while test will be started immediately + verifyLockingCalculationDelay(600000, 0, false); + + // verify that calculation will be started after a second + verifyLockingCalculationDelay(1000, 1000, true); + } + + private void verifyLockingCalculationDelay(long delay, long testDelay, + boolean deoptExpected) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_delay_%d_%d.xml", delay, + testDelay); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + "-XX:+UseRTMDeopt", + CommandLineOptionTest.prepareNumericFlag( + "RTMLockingCalculationDelay", delay), + "-XX:RTMAbortRatio=0", + "-XX:RTMAbortThreshold=0", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString( + TestRTMLockingCalculationDelay.INFLATE_MONITOR), + Long.toString(AbortProvoker.DEFAULT_ITERATIONS), + Long.toString(testDelay) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int deopts = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + if (deoptExpected) { + Asserts.assertGT(deopts, 0, "At least one deoptimization due to " + + "rtm_state_chage is expected"); + } else { + Asserts.assertEQ(deopts, 0, "No deoptimizations due to " + + "rtm_state_chage are expected"); + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingCalculationDelay().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMLockingThreshold.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMLockingThreshold affects rtm state transition + * ProfileRTM => UseRTM. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMLockingThreshold + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMLockingThreshold + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; +import sun.misc.Unsafe; + +/** + * Test verifies that RTMLockingThreshold option actually affects how soon + * method will be deoptimized on low abort ratio. + */ +public class TestRTMLockingThreshold extends CommandLineOptionTest { + private TestRTMLockingThreshold() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + /** + * We use non-zero abort threshold to avoid abort related to + * interrupts, VMM calls, etc. during first lock attempt. + * + */ + private static final int ABORT_THRESHOLD = 10; + + @Override + protected void runTestCases() throws Throwable { + verifyLockingThreshold(0, false); + verifyLockingThreshold(100, false); + verifyLockingThreshold(1000, false); + + verifyLockingThreshold(0, true); + verifyLockingThreshold(100, true); + verifyLockingThreshold(1000, true); + } + + private void verifyLockingThreshold(int lockingThreshold, + boolean useStackLock) throws Throwable { + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + "-XX:CompileThreshold=1", + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + "-XX:+UseRTMDeopt", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", + TestRTMLockingThreshold.ABORT_THRESHOLD), + CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", + lockingThreshold), + "-XX:RTMAbortRatio=100", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock), + Integer.toString(lockingThreshold) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, "VM output should contain two " + + "RTM locking statistics entries."); + + /** + * We force abort on each odd iteration, so if RTMLockingThreshold==0, + * then we have to make 1 call without abort to avoid rtm state + * transition to NoRTM (otherwise actual abort ratio will be 100%), + * and after that make 1 call with abort to force deoptimization. + * This leads us to two locks for threshold 0. + * For other threshold values we have to make RTMLockingThreshold + 1 + * locks if locking threshold is even, or + 0 if odd. + */ + long expectedValue = lockingThreshold + + (lockingThreshold == 0L ? 2L : lockingThreshold % 2L); + + RTMLockingStatistics statBeforeDeopt = null; + for (RTMLockingStatistics s : statistics) { + if (s.getTotalLocks() == expectedValue) { + Asserts.assertNull(statBeforeDeopt, + "Only one statistics entry should contain aborts"); + statBeforeDeopt = s; + } + } + + Asserts.assertNotNull(statBeforeDeopt, "There should be exactly one " + + "statistics entry corresponding to ProfileRTM state."); + } + + public static class Test implements CompilableTest { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int TOTAL_ITERATIONS = 10000; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + private final Object monitor = new Object(); + + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + sun.misc.Unsafe.class.getName() + "::addressSize" + }; + } + + public void lock(boolean abort) { + synchronized(monitor) { + if (abort) { + Test.field += Test.UNSAFE.addressSize(); + } + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test t = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(t.monitor); + } + for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + t.lock(i % 2 == 1); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMLockingThreshold().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMRetryCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMRetryCount.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMRetryCount affects actual amount of retries. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMRetryCount + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMRetryCount + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTMRetryCount option actually affects amount of + * retries on lock busy. + */ +public class TestRTMRetryCount extends CommandLineOptionTest { + /** + * Time in ms, during which busy lock will be locked. + */ + private static final int LOCKING_TIME = 5000; + private static final boolean INFLATE_MONITOR = true; + + private TestRTMRetryCount() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyRTMRetryCount(0); + verifyRTMRetryCount(1); + verifyRTMRetryCount(5); + verifyRTMRetryCount(10); + } + + private void verifyRTMRetryCount(int retryCount) throws Throwable { + CompilableTest busyLock = new BusyLock(); + long expectedAborts = retryCount + 1L; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + busyLock, + "-XX:-UseRTMXendForLockBusy", + "-XX:RTMTotalCountIncrRate=1", + CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", + retryCount), + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(TestRTMRetryCount.INFLATE_MONITOR), + Integer.toString(TestRTMRetryCount.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + busyLock.getMethodWithLockName(), outputAnalyzer.getStdout()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one rtm locking statistics entry for method " + + busyLock.getMethodWithLockName()); + + Asserts.assertEQ(statistics.get(0).getTotalAborts(), expectedAborts, + String.format("It is expected to get %d aborts", + expectedAborts)); + } + + public static void main(String args[]) throws Throwable { + new TestRTMRetryCount().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMSpinLoopCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMSpinLoopCount.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMSpinLoopCount affects time spent + * between locking attempts. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMSpinLoopCount + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMSpinLoopCount + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTMSpinLoopCount increase time spent between retries + * by comparing amount of retries done with different RTMSpinLoopCount's values. + */ +public class TestRTMSpinLoopCount extends CommandLineOptionTest { + private static final int LOCKING_TIME = 1000; + private static final int RTM_RETRY_COUNT = 1000; + private static final boolean INFLATE_MONITOR = true; + private static final long MAX_ABORTS = RTM_RETRY_COUNT + 1L; + private static final int[] SPIN_LOOP_COUNTS + = new int[] { 0, 100, 1_000, 1_000_000, 10_000_000 }; + + private TestRTMSpinLoopCount() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + long[] aborts = new long[TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length]; + for (int i = 0; i < TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length; i++) { + aborts[i] = getAbortsCountOnLockBusy( + TestRTMSpinLoopCount.SPIN_LOOP_COUNTS[i]); + } + + for (int i = 1; i < aborts.length; i++) { + Asserts.assertLTE(aborts[i], aborts[i - 1], "Increased spin loop " + + "count should not increase retries count."); + } + } + + private long getAbortsCountOnLockBusy(int spinLoopCount) throws Throwable { + CompilableTest test = new BusyLock(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", + TestRTMSpinLoopCount.RTM_RETRY_COUNT), + CommandLineOptionTest.prepareNumericFlag("RTMSpinLoopCount", + spinLoopCount), + "-XX:-UseRTMXendForLockBusy", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(TestRTMSpinLoopCount.INFLATE_MONITOR), + Integer.toString(TestRTMSpinLoopCount.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one entry for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertLTE(lock.getTotalAborts(), + TestRTMSpinLoopCount.MAX_ABORTS, String.format("Total aborts " + + "count (%d) should be less or equal to %d", + lock.getTotalAborts(), + TestRTMSpinLoopCount.MAX_ABORTS)); + + return lock.getTotalAborts(); + } + + public static void main(String args[]) throws Throwable { + new TestRTMSpinLoopCount().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that RTMTotalCountIncrRate option affects + * RTM locking statistics. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestRTMTotalCountIncrRate + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that with RTMTotalCountIncrRate=1 RTM locking statistics + * contains precise information abort attempted locks and that with other values + * statistics contains information abort non-zero locking attempts. + * Since assert done for RTMTotalCountIncrRate=1 is pretty strict, test uses + * -XX:RTMRetryCount=0 to avoid issue with retriable aborts. For more details on + * that issue see {@link TestUseRTMAfterLockInflation}. + */ +public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { + private TestRTMTotalCountIncrRate() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyLocksCount(1, false); + verifyLocksCount(64, false); + verifyLocksCount(128, false); + verifyLocksCount(1, true); + verifyLocksCount(64, true); + verifyLocksCount(128, true); + } + + private void verifyLocksCount(int incrRate, boolean useStackLock) + throws Throwable{ + CompilableTest test = new Test(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + CommandLineOptionTest.prepareNumericFlag( + "RTMTotalCountIncrRate", incrRate), + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one RTM locking statistics entry for method " + + test.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + if (incrRate == 1) { + Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS, + "Total locks should be exactly the same as amount of " + + "iterations."); + } else { + Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM statistics " + + "should contain information for at least on lock."); + } + } + + public static class Test implements CompilableTest { + private static final long TOTAL_ITERATIONS = 10000L; + private final Object monitor = new Object(); + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::lock"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName() + }; + } + + public void lock() { + synchronized(monitor) { + Test.field++; + } + } + + /** + * Usage: + * Test <inflate monitor> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGTE(args.length, 1, "One argument required."); + Test test = new Test(); + + if (Boolean.valueOf(args[0])) { + AbortProvoker.inflateMonitor(test.monitor); + } + for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { + test.lock(); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestRTMTotalCountIncrRate().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that rtm locking is used for stack locks before + * inflation and after it used for inflated locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMAfterLockInflation + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMAfterLockInflation + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM is used after lock inflation by executing compiled + * method with RTM-based lock elision using stack lock first, then that lock + * is inflated and the same compiled method invoked again. + * + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before + * lock inflation and the same amount of times after inflation. + * As a result total locks count should be equal to + * {@code 2*AbortProvoker.DEFAULT_ITERATIONS}. + * It is a pretty strict assertion which could fail if some retriable abort + * happened: it could be {@code AbortType.RETRIABLE} or + * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these + * reasons simultaneously. In order to avoid false negative failures related + * to incorrect aborts counting, -XX:RTMRetryCount=0 is used. + */ +public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { + private static final long EXPECTED_LOCKS + = 2L * AbortProvoker.DEFAULT_ITERATIONS; + + private TestUseRTMAfterLockInflation() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + long totalLocksCount = 0; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + Test.class.getName(), + AbortType.XABORT.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 2, + "VM output should contain two rtm locking statistics entries " + + "for method " + provoker.getMethodWithLockName()); + + for (RTMLockingStatistics s : statistics) { + totalLocksCount += s.getTotalLocks(); + } + + Asserts.assertEQ(totalLocksCount, + TestUseRTMAfterLockInflation.EXPECTED_LOCKS, + "Total lock count should be greater or equal to " + + TestUseRTMAfterLockInflation.EXPECTED_LOCKS); + } + + public static class Test { + + /** + * Usage: + * Test <provoker type> + */ + public static void main(String args[]) throws Throwable { + Asserts.assertGT(args.length, 0, + "AbortType name is expected as first argument."); + + AbortProvoker provoker + = AbortType.lookup(Integer.valueOf(args[0])).provoker(); + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + provoker.forceAbort(); + } + provoker.inflateMonitor(); + for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + provoker.forceAbort(); + } + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMAfterLockInflation().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestUseRTMDeopt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestUseRTMDeopt.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that UseRTMDeopt affects uncommon trap installation in + * copmpiled methods with synchronized block. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMDeopt + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMDeopt + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that usage of UseRTMDeopt option affects uncommon traps usage + * for methods that use locking. + */ +public class TestUseRTMDeopt extends CommandLineOptionTest { + private TestUseRTMDeopt() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + verifyUseRTMDeopt(false); + verifyUseRTMDeopt(true); + } + + private void verifyUseRTMDeopt(boolean useRTMDeopt) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_%s_deopt.xml", + useRTMDeopt ? "use" : "no"); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", + useRTMDeopt), + AbortProvoker.class.getName(), + AbortType.XABORT.toString() + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int expectedUncommonTraps = useRTMDeopt ? 1 : 0; + int installedUncommonTraps + = RTMTestBase.installedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(expectedUncommonTraps, installedUncommonTraps, + String.format("Expected to find %d uncommon traps " + + "installed with reason rtm_state_change.", + expectedUncommonTraps)); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMDeopt().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that rtm locking is used for inflated locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForInflatedLocks + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMForInflatedLocks + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM-based lock elision could be used for inflated locks + * by calling compiled method that use RTM-based lock elision and using + * manually inflated lock. + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, + * so total locks count should be the same. + * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 + * is used. For more information abort that issue see + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMForInflatedLocks extends CommandLineOptionTest { + private TestUseRTMForInflatedLocks() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + RTMLockingStatistics lock; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:-UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one rtm locking statistics " + + "entry for method " + provoker.getMethodWithLockName()); + + lock = statistics.get(0); + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Total lock count should be greater or equal to " + + AbortProvoker.DEFAULT_ITERATIONS); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForInflatedLocks().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestUseRTMForStackLocks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestUseRTMForStackLocks.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that rtm locking is used for stack locks. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMForStackLocks + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMForStackLocks + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that RTM-based lock elision could be used for stack locks + * by calling compiled method that use RTM-based lock elision and using + * stack lock. + * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, + * so total locks count should be the same. + * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 + * is used. For more information abort that issue see + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMForStackLocks extends CommandLineOptionTest { + private static final boolean INFLATE_MONITOR = false; + + private TestUseRTMForStackLocks() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + protected void runTestCases() throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + RTMLockingStatistics lock; + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+UseRTMForStackLocks", + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(TestUseRTMForStackLocks.INFLATE_MONITOR)); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one rtm locking statistics " + + "entry for method " + provoker.getMethodWithLockName()); + + lock = statistics.get(0); + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Total locks count should be greater or equal to " + + AbortProvoker.DEFAULT_ITERATIONS); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMForStackLocks().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that UseRTMXendForLockBusy option affects + * method behaviour if lock is busy. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMXendForLockBusy + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMXendForLockBusy + */ + +import java.util.List; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that with +UseRTMXendForLockBusy there will be no aborts + * forced by the test. + */ +public class TestUseRTMXendForLockBusy extends CommandLineOptionTest { + private final static int LOCKING_TIME = 5000; + + private TestUseRTMXendForLockBusy() { + super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + } + + @Override + protected void runTestCases() throws Throwable { + // inflated lock, xabort on lock busy + verifyXendForLockBusy(true, false); + // inflated lock, xend on lock busy + verifyXendForLockBusy(true, true); + // stack lock, xabort on lock busy + verifyXendForLockBusy(false, false); + // stack lock, xend on lock busy + verifyXendForLockBusy(false, true); + } + + private void verifyXendForLockBusy(boolean inflateMonitor, + boolean useXend) throws Throwable { + CompilableTest test = new BusyLock(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + test, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + inflateMonitor), + CommandLineOptionTest.prepareBooleanFlag( + "UseRTMXendForLockBusy", + useXend), + "-XX:RTMRetryCount=0", + "-XX:RTMTotalCountIncrRate=1", + "-XX:+PrintPreciseRTMLockingStatistics", + BusyLock.class.getName(), + Boolean.toString(inflateMonitor), + Integer.toString(TestUseRTMXendForLockBusy.LOCKING_TIME) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + test.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, "VM output should contain " + + "exactly one rtm locking statistics entry for method " + + test.getMethodWithLockName()); + + long aborts = statistics.get(0).getAborts(AbortType.XABORT); + + if (useXend) { + Asserts.assertEQ(aborts, 0L, + "Expected to get no aborts on busy lock"); + } else { + Asserts.assertGT(aborts, 0L, + "Expected to get at least one abort on busy lock"); + } + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMXendForLockBusy().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that NoRTMLockEliding option could be applied to + * specified method and that such method will not use rtm. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestNoRTMLockElidingOption + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestNoRTMLockElidingOption + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that method tagged with option NoRTMLockElidingOption + * will not use RTM-based lock elision. + * Test invokes compiled method and checks that no deoptimization with + * rtm_state_change reason had happened and that that VM output + * does not contain RTM locking statistics for compiled method. + */ +public class TestNoRTMLockElidingOption extends CommandLineOptionTest { + private TestNoRTMLockElidingOption() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyOption(false); + verifyOption(true); + } + + public void verifyOption(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + String methodOption = String.format("-XX:CompileCommand=option," + + "%s,NoRTMLockEliding", provoker.getMethodWithLockName()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + methodOption, + "-XX:RTMTotalCountIncrRate=1", + "-XX:+UseRTMDeopt", + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 0, + "No deoptimizations with rtm_state_change reason are expected"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 0, + "VM output should not contain RTM locking statistics entries " + + "for method " + provoker.getMethodWithLockName()); + } + + public static void main(String args[]) throws Throwable { + new TestNoRTMLockElidingOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that UseRTMLockEliding option could be applied to + * specified method and that such method will not be deoptimized + * on high abort ratio. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestUseRTMLockElidingOption + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseRTMLockElidingOption + */ + +import java.util.List; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that method tagged with option UseRTMLockElidingOption + * will use RTM-based lock elision, but will be never deoptimized with + * rtm_state_change reason. + * Test invokes compiled method and checks that no deoptimization with + * rtm_state_change reason had happened and that that VM output + * contains RTM locking statistics for compiled method and that total locks + * count equals to method's invocations. + * Since last assert is pretty strict, test uses -XX:RTMRetryCount=0 in order + * to avoid issue with retriable aborts described in + * {@link TestUseRTMAfterLockInflation}. + */ +public class TestUseRTMLockElidingOption extends CommandLineOptionTest { + private TestUseRTMLockElidingOption() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyOption(false); + verifyOption(true); + } + + public void verifyOption(boolean useStackLock) throws Throwable { + AbortProvoker provoker = AbortType.XABORT.provoker(); + String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", + (useStackLock ? "use" : "no")); + String methodOption = String.format("-XX:CompileCommand=option," + + "%s,UseRTMLockEliding", provoker.getMethodWithLockName()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + logFileName, + provoker, + CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", + useStackLock), + methodOption, + "-XX:RTMTotalCountIncrRate=1", + "-XX:RTMRetryCount=0", + "-XX:+UseRTMDeopt", + "-XX:+PrintPreciseRTMLockingStatistics", + provoker.getClass().getName(), + AbortType.XABORT.toString(), + Boolean.toString(!useStackLock) + ); + + outputAnalyzer.shouldHaveExitValue(0); + + int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); + + Asserts.assertEQ(firedTraps, 0, + "Method deoptimization with rtm_state_change is unexpected"); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 1, + "VM output should contain exactly one RTM locking " + + "statistics entry for method " + + provoker.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, + "Expected to get total locks count equal to total amount of " + + "lock attempts."); + } + + public static void main(String args[]) throws Throwable { + new TestUseRTMLockElidingOption().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031320 + * @summary Verify that rtm locking statistics contain proper information + * on overall aborts and locks count and count of aborts of + * different types. Test also verify that VM output does not + * contain rtm locking statistics when it should not. + * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @build TestPrintPreciseRTMLockingStatistics + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestPrintPreciseRTMLockingStatistics + */ + +import java.util.*; + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; +import com.oracle.java.testlibrary.cli.predicate.AndPredicate; +import rtm.*; +import rtm.predicate.SupportedCPU; +import rtm.predicate.SupportedVM; + +/** + * Test verifies that VM output does not contain RTM locking statistics when it + * should not (when PrintPreciseRTMLockingStatistics is off) and that with + * -XX:+PrintPreciseRTMLockingStatistics locking statistics contains sane + * total locks and aborts count as well as for specific abort types. + */ +public class TestPrintPreciseRTMLockingStatistics + extends CommandLineOptionTest { + private TestPrintPreciseRTMLockingStatistics() { + super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + } + + @Override + public void runTestCases() throws Throwable { + verifyNoStatistics(); + verifyStatistics(); + } + + // verify that VM output does not contain + // rtm locking statistics + private void verifyNoStatistics() throws Throwable { + verifyNoStatistics(AbortType.XABORT); + + verifyNoStatistics(AbortType.XABORT, + "-XX:-PrintPreciseRTMLockingStatistics"); + + verifyNoStatistics(AbortType.XABORT, "-XX:-UseRTMLocking", + "-XX:+PrintPreciseRTMLockingStatistics"); + } + + // verify that rtm locking statistics contain information + // about each type of aborts + private void verifyStatistics() throws Throwable { + verifyAbortsCount(AbortType.XABORT); + verifyAbortsCount(AbortType.MEM_CONFLICT); + verifyAbortsCount(AbortType.BUF_OVERFLOW); + verifyAbortsCount(AbortType.NESTED_ABORT); + } + + private void verifyNoStatistics(AbortType abortProvokerType, + String... vmOpts) throws Throwable { + AbortProvoker provoker = abortProvokerType.provoker(); + List finalVMOpts = new LinkedList<>(); + Collections.addAll(finalVMOpts, vmOpts); + Collections.addAll(finalVMOpts, AbortProvoker.class.getName(), + abortProvokerType.toString()); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(provoker, + finalVMOpts.toArray(new String[finalVMOpts.size()])); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + outputAnalyzer.getOutput()); + + Asserts.assertEQ(statistics.size(), 0, "VM output should not contain " + + "any RTM locking statistics"); + } + + private void verifyAbortsCount(AbortType abortType) throws Throwable { + AbortProvoker provoker = abortType.provoker(); + + OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( + provoker, + "-XX:+PrintPreciseRTMLockingStatistics", + AbortProvoker.class.getName(), + abortType.toString()); + + outputAnalyzer.shouldHaveExitValue(0); + + List statistics = RTMLockingStatistics.fromString( + provoker.getMethodWithLockName(),outputAnalyzer.getOutput()); + + Asserts.assertGT(statistics.size(), 0, "VM output should contain one " + + "rtm locking statistics entry for method " + + provoker.getMethodWithLockName()); + + RTMLockingStatistics lock = statistics.get(0); + + Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM locking statistics " + + "should contain non zero total locks count"); + + Asserts.assertGT(lock.getTotalAborts(), 0L, + "RTM locking statistics should contain non zero total aborts " + + "count"); + + Asserts.assertGT(lock.getAborts(abortType), 0L, String.format( + "RTM locking statistics should contain non zero aborts count " + + "for abort reason %s", abortType)); + } + + public static void main(String args[]) throws Throwable { + new TestPrintPreciseRTMLockingStatistics().test(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/AbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/AbortProvoker.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.Objects; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +/** + * Base class for different transactional execution abortion + * provokers aimed to force abort due to specified reason. + */ +public abstract class AbortProvoker implements CompilableTest { + public static final long DEFAULT_ITERATIONS = 10000L; + /** + * Inflates monitor associated with object {@code monitor}. + * Inflation is forced by entering the same monitor from + * two different threads. + * + * @param monitor monitor to be inflated. + * @return inflated monitor. + * @throws Exception if something went wrong. + */ + public static Object inflateMonitor(Object monitor) throws Exception { + Unsafe unsafe = Utils.getUnsafe(); + CyclicBarrier barrier = new CyclicBarrier(2); + + Runnable inflatingRunnable = () -> { + unsafe.monitorEnter(monitor); + try { + barrier.await(); + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException( + "Synchronization issue occurred.", e); + } finally { + unsafe.monitorExit(monitor); + } + }; + + Thread t = new Thread(inflatingRunnable); + t.start(); + // Wait until thread t enters the monitor. + barrier.await(); + // At this point monitor will be owned by thread t, + // so our attempt to enter the same monitor will force + // monitor inflation. + Asserts.assertFalse(unsafe.tryMonitorEnter(monitor), + "Not supposed to enter the monitor first"); + barrier.await(); + t.join(); + return monitor; + } + + + /** + * Get instance of specified AbortProvoker, inflate associated monitor + * if needed and then invoke forceAbort method in a loop. + * + * Usage: + * AbortProvoker <AbortType name> [<inflate monitor> + * [<iterations> [ <delay>]]] + * + * Default parameters are: + *
    + *
  • inflate monitor = true
  • + *
  • iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}
  • + *
  • delay = 0
  • + *
+ */ + public static void main(String args[]) throws Throwable { + Asserts.assertGT(args.length, 0, "At least one argument is required."); + + AbortType abortType = AbortType.lookup(Integer.valueOf(args[0])); + boolean monitorShouldBeInflated = true; + long iterations = AbortProvoker.DEFAULT_ITERATIONS; + + if (args.length > 1) { + monitorShouldBeInflated = Boolean.valueOf(args[1]); + + if (args.length > 2) { + iterations = Long.valueOf(args[2]); + + if (args.length > 3) { + Thread.sleep(Integer.valueOf(args[3])); + } + } + } + + AbortProvoker provoker = abortType.provoker(); + + if (monitorShouldBeInflated) { + provoker.inflateMonitor(); + } + + for (long i = 0; i < iterations; i++) { + provoker.forceAbort(); + } + } + + protected final Object monitor; + + protected AbortProvoker() { + this(new Object()); + } + + protected AbortProvoker(Object monitor) { + this.monitor = Objects.requireNonNull(monitor); + } + + /** + * Inflates monitor used by this AbortProvoker instance. + * @throws Exception + */ + public void inflateMonitor() throws Exception { + AbortProvoker.inflateMonitor(monitor); + } + + /** + * Forces transactional execution abortion. + */ + public abstract void forceAbort(); + + /** + * Returns names of all methods that have to be compiled + * in order to successfully force transactional execution + * abortion. + * + * @return array with methods' names that have to be compiled. + */ + @Override + public String[] getMethodsToCompileNames() { + return new String[] { getMethodWithLockName() }; + } + + /** + * Returns name of the method that will contain monitor whose locking + * will be elided using transactional execution. + * + * @return name of the method that will contain elided lock. + */ + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::forceAbort"; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/AbortType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/AbortType.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Asserts; + +import java.util.HashMap; +import java.util.Map; + +/** + * Type of transactional execution abort. + * For more details on different abort types please see + * shared/vm/runtime/rtmLocking.hpp + */ +public enum AbortType { + XABORT(0), + RETRIABLE(1), + MEM_CONFLICT(2), + BUF_OVERFLOW(3), + DEBUG_BREAKPOINT(4), + NESTED_ABORT(5); + + private final int type; + private static final Map LOOKUP_MAP = new HashMap<>(); + + static { + for (AbortType abortType : AbortType.values()) { + Asserts.assertFalse(LOOKUP_MAP.containsKey(abortType.type), + "Abort type values should be unique."); + LOOKUP_MAP.put(abortType.type, abortType); + } + } + + private AbortType(int type) { + this.type = type; + } + + /** + * Returns AbortProvoker for aborts represented by this abort type. + * + * @return an AbortProvoker instance + */ + public AbortProvoker provoker() { + return AbortType.createNewProvoker(this); + } + + public static AbortType lookup(int type) { + Asserts.assertLT(type, AbortType.values().length, + "Unknown abort type."); + return LOOKUP_MAP.get(type); + } + + /** + * Returns transaction execution abort provoker for specified abortion type. + * + * @param type a type of abort which will be forced by returned + * AbortProvoker instance. + * @return AbortProvoker instance that will force abort of specified type + * @throws RuntimeException if there is no provoker for specified type + */ + private static AbortProvoker createNewProvoker(AbortType type) { + switch (type) { + case XABORT: + return new XAbortProvoker(); + case MEM_CONFLICT: + return new MemoryConflictProvoker(); + case BUF_OVERFLOW: + return new BufferOverflowProvoker(); + case NESTED_ABORT: + return new NestedAbortProvoker(); + default: + throw new RuntimeException("No provoker exists for type " + + type.name()); + } + } + + @Override + public String toString() { + return Integer.toString(type); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/BufferOverflowProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/BufferOverflowProvoker.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +/** + * In order to provoke transactional execution abort due to + * internal's buffer overflow BufferOverflowProvoker modifies + * 1MB of BYTES during single transaction. + */ +class BufferOverflowProvoker extends AbortProvoker { + /** + * To force buffer overflow abort we modify memory region with + * size more then L1d cache size. + */ + private static final int MORE_THAN_L1D_SIZE = 1024 * 1024; + private static final byte[] DATA = new byte[MORE_THAN_L1D_SIZE]; + + @Override + public void forceAbort() { + synchronized(monitor) { + for (int i = 0; i < BufferOverflowProvoker.DATA.length; i++) { + BufferOverflowProvoker.DATA[i]++; + } + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/BusyLock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/BusyLock.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +/** + * Test case for busy lock scenario. + * One thread enters the monitor and sleep for a while. + * Another thread is blocked on the same monitor. + */ +public class BusyLock implements CompilableTest, Runnable { + private static final int DEFAULT_TIMEOUT = 1000; + private final CyclicBarrier barrier; + + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + protected final Object monitor; + protected final int timeout; + + public BusyLock() { + this(BusyLock.DEFAULT_TIMEOUT); + } + + public BusyLock(int timeout) { + this.timeout = timeout; + this.monitor = new Object(); + this.barrier = new CyclicBarrier(2); + } + + @Override + public void run() { + try { + // wait until forceAbort leave monitor + barrier.await(); + if (UNSAFE.tryMonitorEnter(monitor)) { + try { + barrier.await(); + Thread.sleep(timeout); + } finally { + UNSAFE.monitorExit(monitor); + } + } else { + throw new RuntimeException("Monitor should be entered by " + + "::run() first."); + } + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException("Synchronization error happened.", e); + } + } + + public void test() { + try { + barrier.await(); + // wait until monitor is locked by a ::run method + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException("Synchronization error happened.", e); + } + synchronized(monitor) { + BusyLock.field++; + } + } + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::test"; + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { getMethodWithLockName() }; + } + + /** + * Usage: + * BusyLock [ <inflate monitor> [ <timeout> ] ] + * + * Default values are: + *
    + *
  • inflate monitor = {@code true}
  • + *
  • timeout = {@code BusyLock.DEFAULT_TIMEOUT}
  • + *
+ */ + public static void main(String args[]) throws Exception { + int timeoutValue = BusyLock.DEFAULT_TIMEOUT; + boolean inflateMonitor = true; + + if (args.length > 0 ) { + inflateMonitor = Boolean.valueOf(args[0]); + + if (args.length > 1) { + timeoutValue = Integer.valueOf(args[1]); + } + } + + BusyLock busyLock = new BusyLock(timeoutValue); + + if (inflateMonitor) { + AbortProvoker.inflateMonitor(busyLock.monitor); + } + + Thread t = new Thread(busyLock); + t.start(); + busyLock.test(); + t.join(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/CompilableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/CompilableTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +/** + * Interface for test scenarios that contain methods + * that should be compiled. + */ +public interface CompilableTest { + /** + * @return array with methods' names that should be compiled. + */ + String[] getMethodsToCompileNames(); + + /** + * @return name of method with RTM-elided lock. + */ + String getMethodWithLockName(); +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/MemoryConflictProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +/** + * To force transactional execution abort due to memory conflict + * one thread should access memory region from transactional region + * while another thread should modify the same memory region. + * Since this scenario is based on the race condition between threads + * you should not expect some particular amount of aborts. + */ +class MemoryConflictProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final int INNER_ITERATIONS = 10000; + private final CyclicBarrier barrier; + /** + * This thread will access and modify memory region + * from outside of the transaction. + */ + private final Runnable conflictingThread; + + public MemoryConflictProvoker() { + this(new Object()); + } + + public MemoryConflictProvoker(Object monitor) { + super(monitor); + barrier = new CyclicBarrier(2); + conflictingThread = () -> { + try { + barrier.await(); + } catch (Exception e) { + throw new RuntimeException(e); + } + for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { + MemoryConflictProvoker.field++; + } + }; + } + + /** + * Accesses and modifies memory region from within the transaction. + */ + public void transactionalRegion() { + try { + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { + synchronized(monitor) { + MemoryConflictProvoker.field--; + } + } + } + + @Override + public void forceAbort() { + try { + Thread t = new Thread(conflictingThread); + t.start(); + transactionalRegion(); + t.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String getMethodWithLockName() { + return this.getClass().getName() + "::transactionalRegion"; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/NestedAbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/NestedAbortProvoker.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.Arrays; + +/** + * In order to force nested transaction abort NestedAbortProvoker + * invoke BufferOverflowProvoker from transactional region. + */ +class NestedAbortProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private final AbortProvoker nestedAbortProvoker; + + public NestedAbortProvoker() { + this.nestedAbortProvoker = new XAbortProvoker(monitor); + } + + @Override + public void forceAbort() { + synchronized(monitor) { + NestedAbortProvoker.field++; + nestedAbortProvoker.forceAbort(); + NestedAbortProvoker.field--; + } + } + + @Override + public String[] getMethodsToCompileNames() { + String nestedProvokerMethods[] + = nestedAbortProvoker.getMethodsToCompileNames(); + String methods[] = Arrays.copyOf(nestedProvokerMethods, + nestedProvokerMethods.length + 1); + methods[methods.length - 1] = getMethodWithLockName(); + return methods; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/RTMLockingStatistics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/RTMLockingStatistics.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.util.EnumMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Wrapper for +UsePreciseRTMLockingStatistics output. + * + * Example of locking statistics: + * + * java/lang/ClassLoader.loadClass@7 + * # rtm locks total (estimated): 0 + * # rtm lock aborts : 13 + * # rtm lock aborts 0: 12 + * # rtm lock aborts 1: 0 + * # rtm lock aborts 2: 0 + * # rtm lock aborts 3: 0 + * # rtm lock aborts 4: 0 + * # rtm lock aborts 5: 0 + */ +public class RTMLockingStatistics { + /** + * Pattern for aborts per abort type entries. + */ + private static final Pattern ABORT_PATTERN; + + /** + * Pattern for whole statistics. + */ + private static final Pattern RTM_LOCKING_STATISTICS_PATTERN; + + static { + String abortRe + = "# rtm lock aborts\\s+(?[0-9]+):\\s(?[0-9]+)"; + + ABORT_PATTERN = Pattern.compile(abortRe); + RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile( + "(?[^.\n]+)\\." + + "(?[^@\n]+)@(?[0-9]+)\n" + + "# rtm locks total \\(estimated\\):\\s*" + + "(?[0-9]+)\n" + + "# rtm lock aborts\\s+:\\s*(?[0-9]+)\n" + + "(?(" + abortRe + "\n)+)"); + } + + private final long totalLocks; + private final long totalAborts; + private final String className; + private final String methodName; + private final int bci; + private final Map aborts = new EnumMap<>(AbortType.class); + + /** + * Constructs RTMLockingStatistics from matcher captured statistics entry. + * @param matcher Matcher captured statistics entry. + */ + private RTMLockingStatistics(Matcher matcher) { + className = matcher.group("className"); + methodName = matcher.group("methodName"); + bci = Integer.valueOf(matcher.group("bci")); + totalLocks = Long.valueOf(matcher.group("totalLocks")); + totalAborts = Long.valueOf(matcher.group("totalAborts")); + + Matcher abortMatcher = ABORT_PATTERN.matcher(matcher. + group("abortStats")); + + while (abortMatcher.find()) { + int type = Integer.valueOf(abortMatcher.group("type")); + long count = Long.valueOf(abortMatcher.group("count")); + setAborts(AbortType.lookup(type), count); + } + } + + + /** + * Parses string and return all founded RTM locking statistics entries. + * + * @param str the string to be parsed. + * @return list with all founded RTM locking statistics entries or + * empty list if nothing was found. + */ + public static List fromString(String str) { + List statistics = new LinkedList<>(); + Matcher matcher = RTM_LOCKING_STATISTICS_PATTERN.matcher(str); + + while (matcher.find()) { + RTMLockingStatistics lock = new RTMLockingStatistics(matcher); + statistics.add(lock); + } + + return statistics; + } + + /** + * Parses string and return all founded RTM locking statistics entries + * for locks in method {@code methodName}. + * + * @param methodName a name of the method for locks from which statistics + * should be gathered. + * @param str the string to be parsed. + * @return list with all founded RTM locking statistics entries or + * empty list if nothing was found. + */ + public static List fromString(String methodName, + String str) { + String formattedMethodName = formatMethodName(methodName); + + List statisticsForMethod = new LinkedList<>(); + for (RTMLockingStatistics statistics : fromString(str)) { + if (statistics.getLockName().startsWith(formattedMethodName)) { + statisticsForMethod.add(statistics); + } + } + return statisticsForMethod; + } + + /** + * Formats method's name so it will have the same format as + * in rtm locking statistics. + * + *
+     * Example:
+     * com/example/Klass::method => com/example/Klass.method
+     * com/example/Klass.method  => com/example/Klass.method
+     * com.example.Klass::method => com/example/Klass.method
+     * com.example.Klass.method  => com/example/Klass.method
+     * 
+ * + * @param methodName method's name that should be formatted. + * @return formatted method's name. + */ + private static String formatMethodName(String methodName) { + String m[]; + if (methodName.contains("::")) { + m = methodName.split("::"); + } else { + int splitAt = methodName.lastIndexOf('.'); + m = new String[2]; + m[0] = methodName.substring(0, splitAt); + m[1] = methodName.substring(splitAt + 1); + } + return String.format("%s.%s", m[0].replaceAll("\\.", "/"), m[1]); + } + + /** + * Returns name of lock for which this statistics was collected. + * Lock name has following format: + * <class name>.<method name>@<bci> + * + * @return name of lock. + */ + public String getLockName() { + return String.format("%s.%s@%d", className, methodName, bci); + } + + /** + * Returns aborts count for specified abort type. + * + * @param type an abort type. + * @return count of aborts. + */ + public long getAborts(AbortType type) { + return aborts.getOrDefault(type, 0L); + } + + /** + * Sets aborts count for specified abort type. + * + * @param type an abort type. + * @param count count of aborts. + */ + public void setAborts(AbortType type, long count) { + aborts.put(type, count); + } + + public long getTotalLocks() { + return totalLocks; + } + + public long getTotalAborts() { + return totalAborts; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getLockName()).append('\n'); + builder.append(String.format("# rtm locks total (estimated): %d\n", + getTotalLocks())); + builder.append(String.format("# rtm lock aborts: %d\n", + getTotalLocks())); + + for (AbortType type : AbortType.values()) { + builder.append(String.format("# rtm lock aborts %s %d\n", + type.toString(), getAborts(type))); + } + return builder.toString(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/RTMTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.LinkedList; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Utils; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; + +/** + * Auxiliary methods used for RTM testing. + */ +public class RTMTestBase { + private static final String RTM_STATE_CHANGE_REASON = "rtm_state_change"; + /** + * We don't parse compilation log as XML-document and use regular + * expressions instead, because in some cases it could be + * malformed. + */ + private static final String FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE + = "rtm_state_change + * installed during compilation. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @return count of installed uncommon traps with reason + * rtm_state_change. + * @throws IOException + */ + public static int installedRTMStateChangeTraps(String compilationLogFile) + throws IOException { + return RTMTestBase.installedUncommonTraps(compilationLogFile, + RTMTestBase.RTM_STATE_CHANGE_REASON); + } + + /** + * Finds count of fired uncommon traps with reason {@code reason}. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @param reason a reason of fired uncommon traps. + * @return count of fired uncommon traps with reason {@code reason}. + * @throws IOException + */ + public static int firedUncommonTraps(String compilationLogFile, + String reason) throws IOException { + String pattern = String.format( + RTMTestBase.FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE, + reason); + return RTMTestBase.findTraps(compilationLogFile, pattern); + } + + /** + * Finds count of fired uncommon traps with reason rtm_state_change. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @return count of fired uncommon traps with reason + * rtm_state_change. + * @throws IOException + */ + public static int firedRTMStateChangeTraps(String compilationLogFile) + throws IOException { + return RTMTestBase.firedUncommonTraps(compilationLogFile, + RTMTestBase.RTM_STATE_CHANGE_REASON); + } + + /** + * Finds count of uncommon traps that matches regular + * expression in {@code re}. + * + * @param compilationLogFile a path to file with LogCompilation output. + * @param re regular expression to match uncommon traps. + * @throws IOException + */ + private static int findTraps(String compilationLogFile, String re) + throws IOException { + String compilationLog = RTMTestBase.fileAsString(compilationLogFile); + Pattern pattern = Pattern.compile(re); + Matcher matcher = pattern.matcher(compilationLog); + int traps = 0; + while (matcher.find()) { + traps++; + } + return traps; + } + + /** + * Returns file's content as a string. + * + * @param path a path to file to operate on. + * @return string with content of file. + * @throws IOException + */ + private static String fileAsString(String path) throws IOException { + byte[] fileAsBytes = Files.readAllBytes(Paths.get(path)); + return new String(fileAsBytes); + } + + /** + * Prepares VM options for test execution. + * This method get test java options, filter out all RTM-related options, + * adds CompileCommand=compileonly,method_name options for each method + * from {@code methodToCompile} and finally appends all {@code vmOpts}. + * + * @param test test case whose methods that should be compiled. + * If {@code null} then no additional compileonly + * commands will be added to VM options. + * @param vmOpts additional options to pass to VM. + * @return Array with VM options. + */ + private static String[] prepareTestOptions(CompilableTest test, + String... vmOpts) { + return RTMTestBase.prepareFilteredTestOptions(test, null, vmOpts); + } + + /** + * Prepares VM options for test execution. + * This method get test java options, filter out all RTM-related options + * and all options that matches regexps in {@code additionalFilters}, + * adds CompileCommand=compileonly,method_name options for each method + * from {@code methodToCompile} and finally appends all {@code vmOpts}. + * + * @param test test case whose methods that should be compiled. + * If {@code null} then no additional compileonly + * commands will be added to VM options. + * @param additionalFilters array with regular expression that will be + * used to filter out test java options. + * If {@code null} then no additional filters + * will be used. + * @param vmOpts additional options to pass to VM. + * @return array with VM options. + */ + private static String[] prepareFilteredTestOptions(CompilableTest test, + String[] additionalFilters, String... vmOpts) { + List finalVMOpts = new LinkedList<>(); + String[] filters; + + if (additionalFilters != null) { + filters = Arrays.copyOf(additionalFilters, + additionalFilters.length + 1); + } else { + filters = new String[1]; + } + + filters[filters.length - 1] = "RTM"; + String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); + Collections.addAll(finalVMOpts, filteredVMOpts); + Collections.addAll(finalVMOpts, "-Xcomp", "-server", + "-XX:-TieredCompilation", + CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking"); + + if (test != null) { + for (String method : test.getMethodsToCompileNames()) { + finalVMOpts.add("-XX:CompileCommand=compileonly," + method); + } + } + Collections.addAll(finalVMOpts, vmOpts); + return finalVMOpts.toArray(new String[finalVMOpts.size()]); + } + + /** + * Adds additional options for VM required for successful execution of test. + * + * @param logFileName a name of compilation log file + * @param test a test case to execute + * @param options additional options to VM + * @return an array with VM options + */ + private static String[] prepareTestOptions(String logFileName, + CompilableTest test, String... options) { + String[] preparedOptions = RTMTestBase.prepareFilteredTestOptions( + test, + new String[] { + "LogCompilation", + "LogFile" + }); + List updatedOptions = new LinkedList<>(); + Collections.addAll(updatedOptions, preparedOptions); + Collections.addAll(updatedOptions, + "-XX:+LogCompilation", + "-XX:LogFile=" + logFileName); + Collections.addAll(updatedOptions, options); + + return updatedOptions.toArray(new String[updatedOptions.size()]); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/XAbortProvoker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/XAbortProvoker.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm; + +import com.oracle.java.testlibrary.Utils; +import sun.misc.Unsafe; + +/** + * Current RTM locking implementation force transaction abort + * before native method call by explicit xabort(0) call. + */ +class XAbortProvoker extends AbortProvoker { + // Following field have to be static in order to avoid escape analysis. + @SuppressWarnings("UnsuedDeclaration") + private static int field = 0; + private static final Unsafe UNSAFE = Utils.getUnsafe(); + + public XAbortProvoker() { + this(new Object()); + } + + public XAbortProvoker(Object monitor) { + super(monitor); + } + + @Override + public void forceAbort() { + synchronized(monitor) { + XAbortProvoker.field = UNSAFE.addressSize(); + } + } + + @Override + public String[] getMethodsToCompileNames() { + return new String[] { + getMethodWithLockName(), + Unsafe.class.getName() + "::addressSize" + }; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/predicate/SupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm.predicate; + +import sun.hotspot.cpuinfo.CPUInfo; + +import java.util.function.BooleanSupplier; + +public class SupportedCPU implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return CPUInfo.hasFeature("rtm"); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/testlibrary/rtm/predicate/SupportedVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/testlibrary/rtm/predicate/SupportedVM.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package rtm.predicate; + +import com.oracle.java.testlibrary.Platform; + +import java.util.function.BooleanSupplier; + +public class SupportedVM implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return Platform.isServer() && !Platform.isEmbedded(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/CorrectnessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/CorrectnessTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CorrectnessTest + * @bug 8038418 + * @library /testlibrary /testlibrary/whitebox + * @compile execution/TypeConflict.java execution/TypeProfile.java + * execution/MethodHandleDelegate.java + * @build CorrectnessTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest RETURN + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest PARAMETERS + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation + * -XX:CompileCommand=exclude,execution/*::methodNotToCompile + * -XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType + * CorrectnessTest ARGUMENTS + * @summary Tests correctness of type usage with type profiling and speculations + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; +import execution.Execution; +import execution.MethodHandleDelegate; +import execution.TypeConflict; +import execution.TypeProfile; +import hierarchies.*; +import scenarios.*; +import sun.hotspot.WhiteBox; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; + +public class CorrectnessTest { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + public static void main(String[] args) { + if (!Platform.isServer()) { + System.out.println("ALL TESTS SKIPPED"); + } + Asserts.assertGTE(args.length, 1); + ProfilingType profilingType = ProfilingType.valueOf(args[0]); + if (runTests(profilingType)) { + System.out.println("ALL TESTS PASSED"); + } else { + throw new RuntimeException("SOME TESTS FAILED"); + } + } + + @SuppressWarnings("unchecked") + public static boolean runTests(ProfilingType profilingType) { + boolean result = true; + + List executionList = new ArrayList<>(); + executionList.add(new TypeConflict()); + executionList.add(new TypeProfile()); + for (int i = 0, n = executionList.size(); i < n; i++) { + executionList.add(new MethodHandleDelegate(executionList.get(i))); + } + + List hierarchyList = new ArrayList<>(); + hierarchyList.add(new DefaultMethodInterface.Hierarchy()); + hierarchyList.add(new DefaultMethodInterface2.Hierarchy()); + hierarchyList.add(new Linear.Hierarchy()); + hierarchyList.add(new Linear2.Hierarchy()); + hierarchyList.add(new OneRank.Hierarchy()); + for (int i = 0, n = hierarchyList.size(); i < n; i++) { + hierarchyList.add(new NullableType(hierarchyList.get(i))); + } + + List>> testCasesConstructors + = new ArrayList<>(); + testCasesConstructors.add(ArrayCopy::new); + testCasesConstructors.add(ArrayReferenceStore::new); + testCasesConstructors.add(ClassIdentity::new); + testCasesConstructors.add(ClassInstanceOf::new); + testCasesConstructors.add(ClassIsInstance::new); + testCasesConstructors.add(ReceiverAtInvokes::new); + testCasesConstructors.add(CheckCast::new); + + for (TypeHierarchy hierarchy : hierarchyList) { + for (BiFunction> constructor : testCasesConstructors) { + for (Execution execution : executionList) { + Scenario scenario = constructor.apply(profilingType, hierarchy); + if (scenario.isApplicable()) { + result &= executeTest(hierarchy, execution, scenario); + } + } + } + } + return result; + } + + /** + * Executes test case + * + * @param hierarchy type hierarchy for the test + * @param execution execution scenario + * @param scenario test scenario executed with given Execution + */ + private static boolean executeTest(TypeHierarchy hierarchy, Execution execution, Scenario scenario) { + boolean testCaseResult = false; + String testName = hierarchy.getClass().getName() + " :: " + scenario.getName() + " @ " + execution.getName(); + clearAllMethodsState(scenario.getClass()); + try { + execution.execute(scenario); + testCaseResult = true; + } catch (Exception e) { + System.err.println(testName + " failed with exception " + e); + e.printStackTrace(); + } + System.out.println((testCaseResult ? "PASSED: " : "FAILED: ") + testName); + return testCaseResult; + } + + private static void clearAllMethodsState(Class aClass) { + while (aClass != null) { + for (Method m : aClass.getDeclaredMethods()) { + WHITE_BOX.clearMethodState(m); + } + aClass = aClass.getSuperclass(); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/OffTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/OffTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CorrectnessTest + * @bug 8038418 + * @library /testlibrary /testlibrary/whitebox + * @compile execution/TypeConflict.java execution/TypeProfile.java + * execution/MethodHandleDelegate.java + * @build CorrectnessTest + * @build OffTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/timeout=1200 OffTest + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import scenarios.ProfilingType; + +import java.util.Random; + +public class OffTest { + private static final String[] OPTIONS = { + "-Xbootclasspath/a:.", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:CompileCommand=exclude,execution/*::methodNotToCompile", + "-XX:CompileCommand=dontinline,scenarios/Scenario::collectReturnType", + "", // -XX:TypeProfileLevel=? + "", // -XX:?UseTypeSpeculation + CorrectnessTest.class.getName(), + "", // ProfilingType.name() + }; + + private static final String TYPE_PROFILE_LEVEL = "TypeProfileLevel"; + private static final String USE_TYPE_SPECULATION = "UseTypeSpeculation"; + private static final int TYPE_PROFILE_LEVEL_LENGTH = 3; + private static final int TYPE_PROFILE_LEVEL_BOUND = 3; + private static final int DEFAULT_COUNT = 10; + private static final int PROFILING_TYPE_INDEX = OPTIONS.length - 1; + private static final int TYPE_PROFILE_INDEX = OPTIONS.length - 4; + private static final int USE_TYPE_SPECULATION_INDEX = OPTIONS.length - 3; + private static final Random RNG; + + static { + String str = System.getProperty("seed"); + long seed = str != null ? Long.parseLong(str) : new Random().nextLong(); + RNG = new Random(seed); + System.out.printf("-Dseed=%d%n", seed); + } + + public static void main(String[] args) throws Exception { + int count = DEFAULT_COUNT; + if (args.length > 0) { + count = Integer.parseInt(args[0]) ; + } + for (int i = 0; i < count; ++i) { + runTest(); + } + } + + private static void runTest() throws Exception { + String useTypeSpeculation = "-XX:" + (RNG.nextBoolean() ? "+" : "-") + USE_TYPE_SPECULATION; + String typeProfileLevel = "-XX:" + TYPE_PROFILE_LEVEL + "=" + randomTypeProfileLevel(); + ProfilingType type = randomProfileType(); + OPTIONS[TYPE_PROFILE_INDEX] = typeProfileLevel; + OPTIONS[USE_TYPE_SPECULATION_INDEX] = useTypeSpeculation; + OPTIONS[PROFILING_TYPE_INDEX] = type.name(); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(/* addTestVmOptions= */ true, OPTIONS); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(processBuilder.start()); + outputAnalyzer.shouldHaveExitValue(0); + } + + private static ProfilingType randomProfileType() { + ProfilingType[] value = ProfilingType.values(); + return value[RNG.nextInt(value.length)]; + } + + private static String randomTypeProfileLevel() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < TYPE_PROFILE_LEVEL_LENGTH; ++i) { + stringBuilder.append(RNG.nextInt(TYPE_PROFILE_LEVEL_BOUND)); + } + return stringBuilder.toString(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/execution/Execution.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/execution/Execution.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Execution scenario represents test methods execution type. + * @param parameter type + * @param result Type + */ +public interface Execution { + /** + * Executes the test code of the given scenario + * See {@link scenarios.Scenario#run(T)} + * + * @param scenario test scenario + */ + void execute(Scenario scenario); + + default String getName() { + return this.getClass().getName(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/execution/MethodHandleDelegate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/execution/MethodHandleDelegate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +/** + * Executes test scenario using {@link MethodHandle#invoke(Object...)}. + * Delegates execution to the given {@link Execution} by creating + * new test scenario, see {@link Scenario} + */ +public class MethodHandleDelegate implements Execution { + private final Execution delegate; + + public MethodHandleDelegate(Execution delegate) { + this.delegate = delegate; + } + + @Override + public void execute(Scenario scenario) { + delegate.execute(new MHScenario(scenario)); + } + + @Override + public String getName() { + return "MethodHandleDelegate # " + delegate.getName(); + } + + private static class MHScenario extends Scenario { + private final Scenario scenario; + private static final MethodHandle METHOD_HANDLE_RUN; + + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType methodType = MethodType.methodType(Object.class, TypeHierarchy.I.class); + + try { + METHOD_HANDLE_RUN = lookup.findVirtual(Scenario.class, "run", methodType); + } catch (NoSuchMethodException | IllegalAccessException e) { + System.err.println("Failed to get target method run() with " + e); + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + * Constructor + * + * @param scenario test scenario to be executed + */ + private MHScenario(Scenario scenario) { + super("MethodHandle::" + scenario.getName(), scenario.profilingType, scenario.hierarchy); + this.scenario = scenario; + } + + /** + * Runs {@link Scenario#run(T)} with {@link MethodHandle#invoke(Object...)} + * + * @param t subject of the test + * @return result of the underlying {@link Scenario#run(T)} invocation + */ + @SuppressWarnings("unchecked") + @Override + public R run(T t) { + try { + return (R) METHOD_HANDLE_RUN.invoke(scenario, t); + } catch (Throwable thr) { + System.err.println(scenario.getName() + + " failed to invoke target method run() with " + thr); + throw new RuntimeException("Invocation failed", thr); + } + } + + @Override + public void check(R r, T t) { + scenario.check(r, t); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/execution/TypeConflict.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/execution/TypeConflict.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Type profiling conflict execution scenario. The main goal is + * to make compiler profile and compile methods with different types. + * Scenario tests guards by passing conflicting types (incompatible + * for the profiled data). + */ +public class TypeConflict implements Execution { + /** Test methods execution number to make profile */ + private final static int POLLUTION_THRESHOLD = 5000; + /** Test methods execution number to make it profiled and compiled*/ + private final static int PROFILE_THRESHOLD = 20000; + + @Override + public void execute(Scenario scenario) { + T base = scenario.getProfiled(); + T incompatible = scenario.getConflict(); + + // pollute profile by passing different types + R baseResult = null; + R incResult = null; + for (int i = 0; i < POLLUTION_THRESHOLD; i++) { + baseResult = methodNotToCompile(scenario, base); + incResult = methodNotToCompile(scenario, incompatible); + } + scenario.check(baseResult, base); + scenario.check(incResult, incompatible); + + // profile and compile + R result = null; + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, base); + } + scenario.check(result, base); + + // pass another type to make guard work and recompile + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, incompatible); + } + scenario.check(result, incompatible); + } + + private R methodNotToCompile(Scenario scenario, T t) { + return scenario.run(t); + } +} + diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/execution/TypeProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/execution/TypeProfile.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package execution; + +import hierarchies.TypeHierarchy; +import scenarios.Scenario; + +/** + * Profile type execution scenario. Executes tester method + * in a loop without any manipulation with types or instances. + */ +public class TypeProfile implements Execution { + /** Number of test method execution to make it profiled and compiled */ + private final static int PROFILE_THRESHOLD = 100000; + + /** + * Makes scenario code be profiled and compiled + * @param scenario Test scenario + */ + @Override + public void execute(Scenario scenario) { + R result = null; + T prof = scenario.getProfiled(); + T confl = scenario.getConflict(); + + for (int i = 0; i < PROFILE_THRESHOLD; i++) { + result = methodNotToCompile(scenario, prof); + } + scenario.check(result, prof); + + result = methodNotToCompile(scenario, confl); + scenario.check(result, confl); + } + + protected R methodNotToCompile(Scenario scenario, T t) { + return scenario.run(t); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/DefaultMethodInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/DefaultMethodInterface.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class DefaultMethodInterface { + private DefaultMethodInterface() { + } + + public static class Hierarchy + extends TypeHierarchy { + public Hierarchy() { + super(new DefaultMethodInterface.A(), new DefaultMethodInterface.B(), + DefaultMethodInterface.A.class, DefaultMethodInterface.B.class); + } + } + + public static interface I2 extends TypeHierarchy.I { + default int m() { + return TypeHierarchy.ANSWER; + } + } + + public static class A implements I2 { + // use default method from I2 + } + + public static class B extends A { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/DefaultMethodInterface2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/DefaultMethodInterface2.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class DefaultMethodInterface2 { + private DefaultMethodInterface2() { + } + + public static class Hierarchy + extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new DefaultMethodInterface2.B(), + TypeHierarchy.A.class, DefaultMethodInterface2.B.class); + } + } + + public static interface I2 extends TypeHierarchy.I { + default int m() { + return TypeHierarchy.ANSWER; + } + } + + public static class B implements I2 { + // default method I2.m() + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/Linear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/Linear.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class Linear { + private Linear() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new Linear.B(), + TypeHierarchy.A.class, Linear.B.class); + } + } + + public static class B extends TypeHierarchy.A { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/Linear2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/Linear2.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class Linear2 { + private Linear2() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new A(), new Linear2.B(), + A.class, Linear2.B.class); + } + } + + public static interface I2 { + int m(); + } + + public static class B extends TypeHierarchy.A implements Linear2.I2 { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/NullableType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/NullableType.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class NullableType + extends TypeHierarchy { + + public NullableType(TypeHierarchy delegate) { + super(delegate.getM(), null, + delegate.getClassM(), delegate.getClassN()); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/OneRank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/OneRank.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +public class OneRank { + private OneRank() { + } + + public static class Hierarchy extends TypeHierarchy { + public Hierarchy() { + super(new TypeHierarchy.A(), new OneRank.B(), + TypeHierarchy.A.class, OneRank.B.class); + } + } + + public static class B implements TypeHierarchy.I { + @Override + public int m() { + return TypeHierarchy.YEAR; + } + } + +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/hierarchies/TypeHierarchy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/hierarchies/TypeHierarchy.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package hierarchies; + +/** + * Type hierarchy contains classes the type profiling and speculation are tested with + */ +public abstract class TypeHierarchy { + // Magic numbers + public static final int ANSWER = 42; + public static final int TEMP = 451; + public static final int YEAR = 1984; + + private final M m; + private final N n; + private final Class classM; + private final Class classN; + + protected TypeHierarchy(M m, N n, Class classM, Class classN) { + this.m = m; + this.n = n; + this.classM = classM; + this.classN = classN; + } + + public final M getM() { + return m; + } + + public final N getN() { + return n; + } + + public final Class getClassM() { + return classM; + } + + public final Class getClassN() { + return classN; + } + + public interface I { + int m(); + } + + public static class A implements I { + @Override + public int m() { + return TypeHierarchy.ANSWER; + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ArrayCopy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ArrayCopy.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +import java.util.Arrays; + +/** + * Tests System.arraycopy() + */ +public class ArrayCopy extends ArrayScenario { + public ArrayCopy(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ArrayCopy", profilingType, hierarchy); + } + + /** + * @param obj is used to fill arrays + * @return the same obj + */ + @Override + public TypeHierarchy.I run(TypeHierarchy.I obj) { + switch (profilingType) { + case RETURN: + TypeHierarchy.I t = collectReturnType(obj); + Arrays.fill(array, t); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + case ARGUMENTS: + field = obj; + Arrays.fill(array, field); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + case PARAMETERS: + Arrays.fill(array, obj); + System.arraycopy(array, 0, matrix[0], 0, array.length); + return array[0]; + } + throw new RuntimeException("Should not reach here"); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ArrayReferenceStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ArrayReferenceStore.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +import java.util.Arrays; + +/** + * Tests aastore bytecode + */ +public class ArrayReferenceStore extends ArrayScenario { + public ArrayReferenceStore(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ArrayReferenceStore", profilingType, hierarchy); + } + + /** + * @param obj is used to fill arrays + * @return obj + */ + @Override + public TypeHierarchy.I run(TypeHierarchy.I obj) { + switch (profilingType) { + case RETURN: + TypeHierarchy.I t = collectReturnType(obj); + Arrays.fill(array, t); + matrix[0] = array; + return matrix[0][0]; + case ARGUMENTS: + field = obj; + Arrays.fill(array, field); + matrix[0] = array; + return matrix[0][0]; + case PARAMETERS: + Arrays.fill(array, obj); + matrix[0] = array; + return matrix[0][0]; + } + throw new RuntimeException("Should not reach here"); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ArrayScenario.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ArrayScenario.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +import java.lang.reflect.Array; +import java.util.Arrays; + +/** + * Base class for array scenarios + */ +public abstract class ArrayScenario extends Scenario { + protected final TypeHierarchy.I[] array; + protected final TypeHierarchy.I[][] matrix; + + protected ArrayScenario(String name, ProfilingType profilingType, + TypeHierarchy hierarchy) { + super(name, profilingType, hierarchy); + final int x = 20; + final int y = 10; + + TypeHierarchy.I prof = hierarchy.getM(); + TypeHierarchy.I confl = hierarchy.getN(); + + this.array = (TypeHierarchy.I[]) Array.newInstance(hierarchy.getClassM(), y); + Arrays.fill(array, prof); + + this.matrix = (TypeHierarchy.I[][]) Array.newInstance(hierarchy.getClassM(), x, y); + for (int i = 0; i < x; i++) { + this.matrix[i] = this.array; + } + + Asserts.assertEquals(array.length, matrix[0].length, "Invariant"); + } + + @Override + public boolean isApplicable() { + return hierarchy.getClassM().isAssignableFrom(hierarchy.getClassN()); + } + + @Override + public void check(TypeHierarchy.I res, TypeHierarchy.I orig) { + Asserts.assertEquals(res, orig, "Check failed"); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/CheckCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/CheckCast.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +import java.util.Objects; + +/** + * Checkcast scenario + * @param profiling parameter + */ +public class CheckCast extends Scenario { + public CheckCast(ProfilingType profilingType, TypeHierarchy hierarchy) { + super("CheckCast", profilingType, hierarchy); + } + + /** + * Returns type profiling. + * @param obj is a profiled parameter for the test + * @return parameter casted to the type R + */ + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t != null) { + return t.m(); + } + return null; + case ARGUMENTS: + field = obj; + if (field != null) { + return field.m(); + } + return null; + case PARAMETERS: + if (obj != null) { + return obj.m(); + } + return null; + } + throw new RuntimeException("Should not reach here"); + } + + @Override + public void check(Integer result, T orig) { + if (result != null || orig != null) { + Objects.requireNonNull(result); + Objects.requireNonNull(orig); + Asserts.assertEquals(result, orig.m(), "Results mismatch"); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ClassIdentity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ClassIdentity.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests pattern: if (a.getClass() == D.class) + */ +public class ClassIdentity extends Scenario { + public ClassIdentity(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassIdentity", profilingType, hierarchy); + } + + @Override + public boolean isApplicable() { + return hierarchy.getM() != null && hierarchy.getN() != null; + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t.getClass() == TypeHierarchy.A.class) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (field.getClass() == TypeHierarchy.A.class) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (obj.getClass() == TypeHierarchy.A.class) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (orig.getClass() == TypeHierarchy.A.class) { + Asserts.assertEquals(result, orig.m(), + "Results are not equal for TypeHierarchy.A.class"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ClassInstanceOf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ClassInstanceOf.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests instanceof + */ +public class ClassInstanceOf extends Scenario { + public ClassInstanceOf(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassInstanceOf", profilingType, hierarchy); + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (t instanceof TypeHierarchy.A) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (field instanceof TypeHierarchy.A) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (obj instanceof TypeHierarchy.A) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (orig instanceof TypeHierarchy.A) { + Asserts.assertEquals(result, orig.m(), "Results are not equal for TypeHierarchy.A"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ClassIsInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ClassIsInstance.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Tests {@link Class#isInstance(Object)} + */ +public class ClassIsInstance extends Scenario { + private final Class baseClass; + + public ClassIsInstance(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ClassIsInstance", profilingType, hierarchy); + this.baseClass = hierarchy.getClassM(); + } + + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + if (baseClass.isInstance(t)) { + return inlinee(t); + } + return TypeHierarchy.TEMP; + case ARGUMENTS: + field = obj; + if (baseClass.isInstance(field)) { + return inlinee(field); + } + return TypeHierarchy.TEMP; + case PARAMETERS: + if (baseClass.isInstance(obj)) { + return inlinee(obj); + } + return TypeHierarchy.TEMP; + } + throw new RuntimeException("Should not reach here"); + } + + public int inlinee(T obj) { + return obj.m(); + } + + @Override + public void check(Integer result, T orig) { + if (baseClass.isInstance(orig)) { + Asserts.assertEquals(result, orig.m(), "Results are not equal for base class"); + } else { + Asserts.assertEquals(result, TypeHierarchy.TEMP, "Result differs from expected"); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ProfilingType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ProfilingType.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +public enum ProfilingType { + /** type profiling of return values of reference types from an invoke */ + RETURN, + /** type profiling for reference parameters on method entries */ + PARAMETERS, + /** type profiling for reference arguments at an invoke */ + ARGUMENTS, +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/ReceiverAtInvokes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/ReceiverAtInvokes.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import com.oracle.java.testlibrary.Asserts; +import hierarchies.TypeHierarchy; + +/** + * Receiver at invokes profiling and speculation + * + * @param parameter to be returned + */ +public class ReceiverAtInvokes extends Scenario { + public ReceiverAtInvokes(ProfilingType profilingType, + TypeHierarchy hierarchy) { + super("ReceiverAtInvokes", profilingType, hierarchy); + } + + @Override + public boolean isApplicable() { + return hierarchy.getM() != null && hierarchy.getN() != null; + } + + /** + * Receiver profiling + * + * @param obj is a profiled parameter for the test + * @return parameter casted to the type R + */ + @Override + public Integer run(T obj) { + switch (profilingType) { + case RETURN: + T t = collectReturnType(obj); + return inlinee(t); + case ARGUMENTS: + field = obj; + return inlinee(field); + case PARAMETERS: + return inlinee(obj); + } + throw new RuntimeException("Should not reach here"); + } + + private Integer inlinee(T obj) { + return obj.m(); // should be inlined + } + + @Override + public void check(Integer result, T orig) { + Asserts.assertEquals(result, orig.m(), "Results mismatch"); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/types/correctness/scenarios/Scenario.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/types/correctness/scenarios/Scenario.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package scenarios; + +import hierarchies.TypeHierarchy; + +/** + * Test scenario + * + * @param parameter type + * @param result type + */ +public abstract class Scenario { + + private final String name; + public final ProfilingType profilingType; + public final TypeHierarchy hierarchy; + protected volatile T field; + + /** + * Constructor + * + * @param name scenario name + * @param profilingType tested profiling type + * @param hierarchy type hierarchy + */ + protected Scenario(String name, ProfilingType profilingType, + TypeHierarchy hierarchy) { + this.profilingType = profilingType; + this.name = name + " # " + profilingType.name(); + this.hierarchy = hierarchy; + } + + /** + * Returns the object which should be used as a parameter + * for the methods used for profile data + * + * @return profiled type object + */ + public T getProfiled() { + return hierarchy.getM(); + } + + /** + * Returns the object which makes a conflict for a profiled data + * when passed instead of {@linkplain Scenario#getProfiled} + * + * @return incompatible to profiled object + */ + public T getConflict() { + return hierarchy.getN(); + } + + /** + * @return scenario name + */ + public String getName() { + return name; + } + + /** Is this scenario applicable for a hierarchy it was constructed with */ + public boolean isApplicable() { + return true; + } + + /** + * Runs test scenario + * + * @param t subject of the test + * @return result of the test invocation + */ + public abstract R run(T t); + + /** Used for a return type profiling */ + protected final T collectReturnType(T t) { + return t; + } + + /** + * Checks the result for R and T + * + * @param r result + * @param t original + * @throws java.lang.RuntimeException on result mismatch + */ + public abstract void check(R r, T t); +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -197,6 +197,29 @@ } /** + * Checks, that {@linkplain #method} is not compiled at the given compilation + * level or above. + * + * @param compLevel + * + * @throws RuntimeException if {@linkplain #method} is in compiler queue or + * is compiled, or if {@linkplain #method} has zero + * compilation level. + */ + + protected final void checkNotCompiled(int compLevel) { + if (WHITE_BOX.isMethodQueuedForCompilation(method)) { + throw new RuntimeException(method + " must not be in queue"); + } + if (WHITE_BOX.getMethodCompilationLevel(method, false) >= compLevel) { + throw new RuntimeException(method + " comp_level must be >= maxCompLevel"); + } + if (WHITE_BOX.getMethodCompilationLevel(method, true) >= compLevel) { + throw new RuntimeException(method + " osr_comp_level must be >= maxCompLevel"); + } + } + + /** * Checks, that {@linkplain #method} is not compiled. * * @throws RuntimeException if {@linkplain #method} is in compiler queue or diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/compiler/whitebox/IsMethodCompilableTest.java --- a/test/compiler/whitebox/IsMethodCompilableTest.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -24,13 +24,17 @@ /* * @test IsMethodCompilableTest * @bug 8007270 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /testlibrary/whitebox /testlibrary/com/oracle/java/testlibrary * @build IsMethodCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest + * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform + * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest * @summary testing of WB::isMethodCompilable() * @author igor.ignatyev@oracle.com */ + +import com.oracle.java.testlibrary.Platform; + public class IsMethodCompilableTest extends CompilerWhiteBoxTest { /** * Value of {@code -XX:PerMethodRecompilationCutoff} @@ -43,7 +47,7 @@ if (tmp == -1) { PER_METHOD_RECOMPILATION_CUTOFF = -1 /* Inf */; } else { - PER_METHOD_RECOMPILATION_CUTOFF = 1 + (0xFFFFFFFFL & tmp); + PER_METHOD_RECOMPILATION_CUTOFF = (0xFFFFFFFFL & tmp); } } @@ -60,16 +64,22 @@ /** * Tests {@code WB::isMethodCompilable()} by recompilation of tested method * 'PerMethodRecompilationCutoff' times and checks compilation status. Also - * checks that WB::clearMethodState() clears no-compilable flags. + * checks that WB::clearMethodState() clears no-compilable flags. Only + * applicable to c2 compiled methods. * * @throws Exception if one of the checks fails. */ @Override protected void test() throws Exception { + // Only c2 compilations can be disabled through PerMethodRecompilationCutoff + if (!Platform.isServer()) { + return; + } + if (skipXcompOSR()) { return; } - if (!isCompilable()) { + if (!isCompilable(COMP_LEVEL_FULL_OPTIMIZATION)) { throw new RuntimeException(method + " must be compilable"); } System.out.println("PerMethodRecompilationCutoff = " @@ -80,39 +90,37 @@ return; } - // deoptimize 'PerMethodRecompilationCutoff' times and clear state - for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) { - compileAndDeoptimize(); + // deoptimize 'PerMethodRecompilationCutoff' times + for (long attempts = 0, successes = 0; + (successes < PER_METHOD_RECOMPILATION_CUTOFF) && + (attempts < PER_METHOD_RECOMPILATION_CUTOFF*2) && + isCompilable(COMP_LEVEL_FULL_OPTIMIZATION); attempts++) { + if (compileAndDeoptimize() == COMP_LEVEL_FULL_OPTIMIZATION) { + successes++; + } } - if (!testCase.isOsr() && !isCompilable()) { + + if (!testCase.isOsr() && !isCompilable(COMP_LEVEL_FULL_OPTIMIZATION)) { // in osr test case count of deopt maybe more than iterations throw new RuntimeException(method + " is not compilable after " - + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations"); + + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); } - WHITE_BOX.clearMethodState(method); - // deoptimize 'PerMethodRecompilationCutoff' + 1 times - long i; - for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF - && isCompilable(); ++i) { - compileAndDeoptimize(); - } - if (!testCase.isOsr() && i != PER_METHOD_RECOMPILATION_CUTOFF) { - // in osr test case count of deopt maybe more than iterations - throw new RuntimeException(method + " is not compilable after " - + i + " iterations, but must only after " - + PER_METHOD_RECOMPILATION_CUTOFF); - } - if (isCompilable()) { + // Now compile once more + compileAndDeoptimize(); + + if (isCompilable(COMP_LEVEL_FULL_OPTIMIZATION)) { throw new RuntimeException(method + " is still compilable after " + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); } + checkNotCompiled(); compile(); - checkNotCompiled(); + waitBackgroundCompilation(); + checkNotCompiled(COMP_LEVEL_FULL_OPTIMIZATION); // WB.clearMethodState() must reset no-compilable flags WHITE_BOX.clearMethodState(method); - if (!isCompilable()) { + if (!isCompilable(COMP_LEVEL_FULL_OPTIMIZATION)) { throw new RuntimeException(method + " is not compilable after clearMethodState()"); } @@ -120,9 +128,11 @@ checkCompiled(); } - private void compileAndDeoptimize() throws Exception { + private int compileAndDeoptimize() throws Exception { compile(); waitBackgroundCompilation(); + int compLevel = getCompLevel(); deoptimize(); + return compLevel; } } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/runtime/ClassFile/UnsupportedClassFileVersion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/ClassFile/UnsupportedClassFileVersion.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @compile -XDignore.symbol.file UnsupportedClassFileVersion.java + * @run main UnsupportedClassFileVersion + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import com.oracle.java.testlibrary.*; + +public class UnsupportedClassFileVersion implements Opcodes { + public static void main(String... args) throws Exception { + writeClassFile(); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("ClassFile has been compiled by a more recent version of the " + + "Java Runtime (class file version 99.0), this version of " + + "the Java Runtime only recognizes class file versions up to " + + System.getProperty("java.class.version")); + + output.shouldHaveExitValue(1); + } + + public static void writeClassFile() throws Exception { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(99, ACC_PUBLIC + ACC_SUPER, "ClassFile", null, "java/lang/Object", null); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + cw.visitEnd(); + + try (FileOutputStream fos = new FileOutputStream(new File("ClassFile.class"))) { + fos.write(cw.toByteArray()); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/runtime/verifier/TestMultiANewArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/verifier/TestMultiANewArray.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import static jdk.internal.org.objectweb.asm.Opcodes.*; +import com.oracle.java.testlibrary.*; + +/* + * @test TestMultiANewArray + * @bug 8038076 + * @library /testlibrary + * @compile -XDignore.symbol.file TestMultiANewArray.java + * @run main/othervm TestMultiANewArray 49 + * @run main/othervm TestMultiANewArray 50 + * @run main/othervm TestMultiANewArray 51 + * @run main/othervm TestMultiANewArray 52 + */ + +public class TestMultiANewArray { + public static void main(String... args) throws Exception { + int cfv = Integer.parseInt(args[0]); + writeClassFile(cfv); + System.err.println("Running with cfv: " + cfv); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("VerifyError"); + output.shouldHaveExitValue(1); + } + + public static void writeClassFile(int cfv) throws Exception { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(cfv, ACC_PUBLIC + ACC_SUPER, "ClassFile", null, "java/lang/Object", null); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); + mv.visitCode(); + mv.visitInsn(ICONST_1); + mv.visitInsn(ICONST_2); + mv.visitMultiANewArrayInsn("[I", 2); + mv.visitVarInsn(ASTORE, 1); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + + cw.visitEnd(); + + try (FileOutputStream fos = new FileOutputStream(new File("ClassFile.class"))) { + fos.write(cw.toByteArray()); + } + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/Platform.java --- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Apr 17 16:09:07 2014 -0700 @@ -28,6 +28,27 @@ 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 osArch = System.getProperty("os.arch"); + private static final String vmName = System.getProperty("java.vm.name"); + + 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 is32bit() { return dataModel.equals("32"); diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java --- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Thu Apr 17 16:09:07 2014 -0700 @@ -142,11 +142,23 @@ * with any platform specific arguments prepended */ public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + return createJavaProcessBuilder(false, command); + } + + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmOptions, String... command) throws Exception { String javapath = JDKToolFinder.getJDKTool("java"); ArrayList args = new ArrayList<>(); args.add(javapath); Collections.addAll(args, getPlatformSpecificVMArgs()); + + if (addTestVmOptions) { + String vmopts = System.getProperty("test.vm.opts"); + if (vmopts != null && vmopts.length() > 0) { + Collections.addAll(args, vmopts.split("\\s")); + } + } + Collections.addAll(args, command); // Reporting @@ -234,5 +246,4 @@ } return cmd.toString().trim(); } - } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/Utils.java --- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Apr 17 16:09:07 2014 -0700 @@ -38,6 +38,8 @@ import java.util.Collections; import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.lang.reflect.Field; +import sun.misc.Unsafe; /** * Common library for various test helper functions. @@ -59,6 +61,8 @@ */ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + private static Unsafe unsafe = null; + /** * Returns the value of 'test.timeout.factor' system property * converted to {@code double}. @@ -109,10 +113,10 @@ /** * Returns the default JTReg arguments for a jvm running a test without - * options that matches regular expresions in {@code filters}. + * options that matches regular expressions in {@code filters}. * This is the combination of JTReg arguments test.vm.opts and test.java.opts. * @param filters Regular expressions used to filter out options. - * @return An array of options, or an empty array if no opptions. + * @return An array of options, or an empty array if no options. */ public static String[] getFilteredTestJavaOpts(String... filters) { String options[] = getTestJavaOpts(); @@ -294,4 +298,38 @@ return output; } + /** + * @return Unsafe instance. + */ + public static synchronized Unsafe getUnsafe() { + if (unsafe == null) { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + return unsafe; + } + private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /** + * Returns hex view of byte array + * + * @param bytes byte array to process + * @return Space separated hexadecimal string representation of bytes + */ + + public static String toHexString(byte[] bytes) { + char[] hexView = new char[bytes.length * 3]; + int i = 0; + for (byte b : bytes) { + hexView[i++] = hexArray[(b >> 4) & 0x0F]; + hexView[i++] = hexArray[b & 0x0F]; + hexView[i++] = ' '; + } + return new String(hexView); + } } diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java --- a/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -23,22 +23,16 @@ package com.oracle.java.testlibrary.cli; -import sun.hotspot.cpuinfo.CPUInfo; -import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.predicate.CPUSpecificPredicate; /** * Base class for command line options tests that * requires specific CPU arch or specific CPU features. */ public abstract class CPUSpecificCommandLineOptionTest - extends CommandLineOptionTest { - - private String cpuArchPattern; - private String supportedCPUFeatures[]; - private String unsupportedCPUFeatures[]; - + extends CommandLineOptionTest { /** - * Create new CPU specific test instance that does not + * Creates new CPU specific test instance that does not * require any CPU features. * * @param cpuArchPattern Regular expression that should @@ -49,62 +43,23 @@ } /** - * Create new CPU specific test instance that does not + * Creates new CPU specific test instance that does not * require from CPU support of {@code supportedCPUFeatures} features * and no support of {@code unsupportedCPUFeatures}. * * @param cpuArchPattern Regular expression that should * match os.arch. * @param supportedCPUFeatures Array with names of features that - * should be supported by CPU. If null, + * should be supported by CPU. If {@code null}, * then no features have to be supported. * @param unsupportedCPUFeatures Array with names of features that * should not be supported by CPU. - * If null, then CPU may support any + * If {@code null}, then CPU may support any * features. */ public CPUSpecificCommandLineOptionTest(String cpuArchPattern, - String supportedCPUFeatures[], - String unsupportedCPUFeatures[]) { - this.cpuArchPattern = cpuArchPattern; - this.supportedCPUFeatures = supportedCPUFeatures; - this.unsupportedCPUFeatures = unsupportedCPUFeatures; - } - - /** - * Check that CPU on test box has appropriate architecture, support all - * required features and does not support all features that should not be - * supported. - * - * @return true if CPU on test box fulfill all requirements. - */ - @Override - public boolean checkPreconditions() { - if (!Platform.getOsArch().matches(cpuArchPattern)) { - System.out.println("CPU arch does not match " + cpuArchPattern); - return false; - } - - if (supportedCPUFeatures != null) { - for (String feature : supportedCPUFeatures) { - if (!CPUInfo.hasFeature(feature)) { - System.out.println("CPU does not support " + feature + - " feature"); - return false; - } - } - } - - if (unsupportedCPUFeatures != null) { - for (String feature : unsupportedCPUFeatures) { - if (CPUInfo.hasFeature(feature)) { - System.out.println("CPU support " + feature + " feature"); - return false; - } - } - } - - return true; + String supportedCPUFeatures[], String unsupportedCPUFeatures[]) { + super(new CPUSpecificPredicate(cpuArchPattern, supportedCPUFeatures, + unsupportedCPUFeatures)); } } - diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java --- a/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Wed Apr 16 12:32:23 2014 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Thu Apr 17 16:09:07 2014 -0700 @@ -26,6 +26,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Collections; +import java.util.function.BooleanSupplier; import com.oracle.java.testlibrary.*; @@ -33,34 +34,71 @@ * Base class for command line option tests. */ public abstract class CommandLineOptionTest { - - public static final String UNRECOGNIZED_OPTION_ERROR_FORMAT = - "Unrecognized VM option '[+-]?%s'"; - - public static final String printFlagsFinalFormat = "%s\\s*:?=\\s*%s"; + public static final String UNLOCK_DIAGNOSTIC_VM_OPTIONS + = "-XX:+UnlockDiagnosticVMOptions"; + public static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS + = "-XX:+UnlockExperimentalVMOptions"; + protected static final String UNRECOGNIZED_OPTION_ERROR_FORMAT + = "Unrecognized VM option '[+-]?%s(=.*)?'"; + protected static final String EXPERIMENTAL_OPTION_ERROR_FORMAT + = "VM option '%s' is experimental and must be enabled via " + + "-XX:\\+UnlockExperimentalVMOptions."; + protected static final String DIAGNOSTIC_OPTION_ERROR_FORMAT + = " VM option '%s' is diagnostic and must be enabled via " + + "-XX:\\+UnlockDiagnosticVMOptions."; + private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s"; /** - * Verify that JVM startup behaviour matches our expectations. + * Verifies that JVM startup behaviour matches our expectations. * - * @param option The option that should be passed to JVM - * @param excpectedMessages Array of patterns that should occur - * in JVM output. If null then + * @param option an option that should be passed to JVM + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then * JVM output could be empty. - * @param unexpectedMessages Array of patterns that should not - * occur in JVM output. If null then - * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. * @param exitCode expected exit code. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyJVMStartup(String option, - String expectedMessages[], - String unexpectedMessages[], - ExitCode exitCode) - throws Throwable { + String expectedMessages[], String unexpectedMessages[], + ExitCode exitCode) throws Throwable { + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitCode, false, option); + } - OutputAnalyzer outputAnalyzer = - ProcessTools.executeTestJvm(option, "-version"); + /** + * Verifies that JVM startup behaviour matches our expectations. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitCode expected exit code. + * @param addTestVMOptions if {@code true} then test VM options will be + * passed to VM. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyJVMStartup(String expectedMessages[], + String unexpectedMessages[], ExitCode exitCode, + boolean addTestVMOptions, String... options) throws Throwable { + List finalOptions = new ArrayList<>(); + if (addTestVMOptions) { + Collections.addAll(finalOptions, Utils.getTestJavaOpts()); + } + Collections.addAll(finalOptions, options); + finalOptions.add("-version"); + ProcessBuilder processBuilder + = ProcessTools.createJavaProcessBuilder(finalOptions.toArray( + new String[finalOptions.size()])); + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); outputAnalyzer.shouldHaveExitValue(exitCode.value); if (expectedMessages != null) { @@ -77,97 +115,216 @@ } /** - * Verify that value of specified JVM option is the same as + * Verifies that JVM startup behaviour matches our expectations when type + * of newly started VM is the same as the type of current. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitCode expected exit code. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifySameJVMStartup(String expectedMessages[], + String unexpectedMessages[], ExitCode exitCode, String... options) + throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + Collections.addAll(finalOptions, options); + + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitCode, false, + finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Verifies that value of specified JVM option is the same as * expected value. * This method filter out option with {@code optionName} * name from test java options. * - * @param optionName Name of tested option. - * @param expectedValue Expected value of tested option. - * @param additionalVMOpts Additonal options that should be + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param additionalVMOpts additional options that should be * passed to JVM. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, - String... additionalVMOpts) - throws Throwable { + String expectedValue, String... additionalVMOpts) throws Throwable { verifyOptionValue(optionName, expectedValue, true, additionalVMOpts); } /** - * Verify that value of specified JVM option is the same as + * Verifies that value of specified JVM option is the same as * expected value. * This method filter out option with {@code optionName} * name from test java options. * - * @param optionName Name of tested option. - * @param expectedValue Expected value of tested option. - * @param addTestVmOptions If true, then test VM options + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param addTestVmOptions if {@code true}, then test VM options * will be used. - * @param additionalVMOpts Additonal options that should be + * @param additionalVMOpts additional options that should be * passed to JVM. - * @throws Throwable if verification fails or some other issues occur. + * @throws Throwable if verification fails or some other issues + * occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, - boolean addTestVmOptions, - String... additionalVMOpts) - throws Throwable { - - List vmOpts = new ArrayList(); + String expectedValue, boolean addTestVmOptions, + String... additionalVMOpts) throws Throwable { + List vmOpts = new ArrayList<>(); if (addTestVmOptions) { Collections.addAll(vmOpts, Utils.getFilteredTestJavaOpts(optionName)); } Collections.addAll(vmOpts, additionalVMOpts); - Collections.addAll(vmOpts, new String[] { - "-XX:+PrintFlagsFinal", - "-version" - }); + Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version"); - ProcessBuilder processBuilder = - ProcessTools. - createJavaProcessBuilder(vmOpts. - toArray(new String[vmOpts.size()])); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); - OutputAnalyzer outputAnalyzer = - new OutputAnalyzer(processBuilder.start()); + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); outputAnalyzer.shouldHaveExitValue(0); - outputAnalyzer.shouldMatch(String. - format(printFlagsFinalFormat, - optionName, - expectedValue)); + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionName, expectedValue)); + } + + /** + * Verifies that value of specified JVM when type of newly started VM + * is the same as the type of current. + * This method filter out option with {@code optionName} + * name from test java options. + * Only mode flag will be passed to VM in addition to + * {@code additionalVMOpts} + * + * @param optionName name of tested option. + * @param expectedValue expected value of tested option. + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValueForSameVM(String optionName, + String expectedValue, String... additionalVMOpts) throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + Collections.addAll(finalOptions, additionalVMOpts); + + CommandLineOptionTest.verifyOptionValue(optionName, expectedValue, + false, finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Prepares boolean command line flag with name {@code name} according + * to it's {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareBooleanFlag(String name, boolean value) { + return String.format("-XX:%c%s", (value ? '+' : '-'), name); + } + + /** + * Prepares numeric command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareNumericFlag(String name, Number value) { + return String.format("-XX:%s=%s", name, value.toString()); } + /** + * Returns message that should occur in VM output if option + * {@code optionName} if unrecognized. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is unrecognized + */ + public static String getUnrecognizedOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * Returns message that should occur in VM output if option + * {@code optionName} is experimental and + * -XX:+UnlockExperimentalVMOptions was not passed to VM. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is experimental + */ + public static String getExperimentalOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.EXPERIMENTAL_OPTION_ERROR_FORMAT, + optionName); + } /** - * Run command line option test. + * Returns message that should occur in VM output if option + * {@code optionName} is diagnostic and -XX:+UnlockDiagnosticVMOptions + * was not passed to VM. * - * @throws Throwable if test failed. + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is diganostic + */ + public static String getDiagnosticOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.DIAGNOSTIC_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * @return option required to start a new VM with the same type as current. + * @throws RuntimeException when VM type is unknown. + */ + private static String getVMTypeOption() { + if (Platform.isServer()) { + return "-server"; + } else if (Platform.isClient()) { + return "-client"; + } else if (Platform.isMinimal()) { + return "-minimal"; + } else if (Platform.isGraal()) { + return "-graal"; + } + throw new RuntimeException("Unknown VM mode."); + } + + private final BooleanSupplier predicate; + + /** + * Constructs new CommandLineOptionTest that will be executed only if + * predicate {@code predicate} return {@code true}. + * @param predicate a predicate responsible for test's preconditions check. + */ + public CommandLineOptionTest(BooleanSupplier predicate) { + this.predicate = predicate; + } + + /** + * Runs command line option test. */ public final void test() throws Throwable { - if (checkPreconditions()) { + if (predicate.getAsBoolean()) { runTestCases(); } } /** - * Check that all preconditions for test execution are met. - * - * @return true if test could be executed. + * @throws Throwable if some issue happened during test cases execution. */ - public boolean checkPreconditions() { - return true; - } - - /** - * Run test cases. - * - * @throws Throwable if test failed. - */ - public abstract void runTestCases() throws Throwable; + protected abstract void runTestCases() throws Throwable; } - diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class AndPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + + public AndPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() && b.getAsBoolean(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import com.oracle.java.testlibrary.Platform; +import sun.hotspot.cpuinfo.CPUInfo; + +import java.util.function.BooleanSupplier; + +public class CPUSpecificPredicate implements BooleanSupplier { + private final String cpuArchPattern; + private final String supportedCPUFeatures[]; + private final String unsupportedCPUFeatures[]; + + public CPUSpecificPredicate(String cpuArchPattern, + String supportedCPUFeatures[], + String unsupportedCPUFeatures[]) { + this.cpuArchPattern = cpuArchPattern; + this.supportedCPUFeatures = supportedCPUFeatures; + this.unsupportedCPUFeatures = unsupportedCPUFeatures; + } + + @Override + public boolean getAsBoolean() { + if (!Platform.getOsArch().matches(cpuArchPattern)) { + System.out.println("CPU arch does not match " + cpuArchPattern); + return false; + } + + if (supportedCPUFeatures != null) { + for (String feature : supportedCPUFeatures) { + if (!CPUInfo.hasFeature(feature)) { + System.out.println("CPU does not support " + feature + + " feature"); + return false; + } + } + } + + if (unsupportedCPUFeatures != null) { + for (String feature : unsupportedCPUFeatures) { + if (CPUInfo.hasFeature(feature)) { + System.out.println("CPU support " + feature + " feature"); + return false; + } + } + } + return true; + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class NotPredicate implements BooleanSupplier { + private final BooleanSupplier s; + + public NotPredicate(BooleanSupplier s) { + this.s = s; + } + + @Override + public boolean getAsBoolean() { + return !s.getAsBoolean(); + } +} diff -r 70dc2c030c69 -r b6a2ba7d3ea7 test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java Thu Apr 17 16:09:07 2014 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.java.testlibrary.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class OrPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + + public OrPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() || b.getAsBoolean(); + } +}